在我的Android应用程序中,我使用conflictHandler类来检测移动设备的DB和服务器的DB的记录之间的冲突。当检测到冲突时,我想显示一个警告对话框,以便用户可以选择哪个记录版本将赢得"赢得服务器或移动设备等。 我已将Alert Dialog的代码放在conflictHandler的类中,因此当检测到冲突时,会弹出Alert Dialog。问题是当警报对话框弹出时代码执行不会停止,以便用户可以选择将要执行的操作。它总是返回serverItem。
private class ConflictResolvingSyncHandler implements MobileServiceSyncHandler {
@Override
public JsonObject executeTableOperation(
final RemoteTableOperationProcessor processor, final TableOperation operation)
throws MobileServiceSyncHandlerException {
final JsonObject clientItem = processor.getItem().getAsJsonObject();
MobileServicePreconditionFailedExceptionBase ex = null;
final JsonObject[] result = {null};
try {
result[0] = operation.accept(processor);
} catch (MobileServicePreconditionFailedExceptionBase e) {
ex = e;
} catch (Throwable e) {
ex = (MobileServicePreconditionFailedExceptionBase) e.getCause();
}
if (ex != null) {
// A conflict was detected; let's force the server to "win"
// by discarding the client version of the item
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set title
alertDialogBuilder.setTitle("Conflict Detected");
// set dialog message
final MobileServicePreconditionFailedExceptionBase finalEx = ex;
alertDialogBuilder
.setMessage("Choose winner")
.setCancelable(false)
.setPositiveButton("Server",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Server wins
JsonObject serverItem = finalEx.getValue();
if (serverItem == null) {
// Item not returned in the exception, retrieving it from the server
try {
serverItem = mClient.getTable(operation.getTableName()).lookUp(operation.getItemId()).get();
} catch (Exception e) {
try {
throw new MobileServiceSyncHandlerException(e);
} catch (MobileServiceSyncHandlerException e1) {
e1.printStackTrace();
}
}
}
result[0] = serverItem;
}
})
.setNegativeButton("Client",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Client wins
result[0]=clientItem;
}
});
runOnUiThread(new Runnable() {
@Override
public void run() {
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
}
return result[0];
}
@Override
public void onPushComplete(MobileServicePushCompletionResult result)
throws MobileServiceSyncHandlerException {
}
}
答案 0 :(得分:1)
您需要阻止正在执行executeTableOperation
的线程,直到用户点击对话框中的内容为止。例如,使用CountDownLatch
,如下面的代码所示:
private class ConflictResolvingSyncHandler implements MobileServiceSyncHandler {
@Override
public JsonObject executeTableOperation(
final RemoteTableOperationProcessor processor, final TableOperation operation)
throws MobileServiceSyncHandlerException {
final JsonObject clientItem = processor.getItem().getAsJsonObject();
MobileServicePreconditionFailedExceptionBase ex = null;
final JsonObject[] result = {null};
try {
result[0] = operation.accept(processor);
} catch (MobileServicePreconditionFailedExceptionBase e) {
ex = e;
} catch (Throwable e) {
ex = (MobileServicePreconditionFailedExceptionBase) e.getCause();
}
if (ex != null) {
// A conflict was detected; let's make the client choose who "wins"
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
final CountDownLatch latch = new CountDownLatch(1);
// set title
alertDialogBuilder.setTitle("Conflict Detected");
// set dialog message
final MobileServicePreconditionFailedExceptionBase finalEx = ex;
alertDialogBuilder
.setMessage("Choose winner")
.setCancelable(false)
.setPositiveButton("Server",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Server wins
JsonObject serverItem = finalEx.getValue();
if (serverItem == null) {
// Item not returned in the exception, retrieving it from the server
try {
serverItem = mClient.getTable(operation.getTableName()).lookUp(operation.getItemId()).get();
} catch (Exception e) {
try {
throw new MobileServiceSyncHandlerException(e);
} catch (MobileServiceSyncHandlerException e1) {
e1.printStackTrace();
}
}
}
result[0] = serverItem;
latch.countDown();
}
})
.setNegativeButton("Client",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Client wins
result[0] = clientItem;
latch.countDown();
}
});
runOnUiThread(new Runnable() {
@Override
public void run() {
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result[0];
}
@Override
public void onPushComplete(MobileServicePushCompletionResult result)
throws MobileServiceSyncHandlerException {
}
}
答案 1 :(得分:1)
为了停止执行,我添加了一个名为" loop"的布尔变量。值为true,在while循环中。 当用户从警报对话框中选择一个按钮时,变量" loop"变得虚假。我添加的代码是粗体。虽然我相信应该避免这种做法。
private class ConflictResolvingSyncHandler implements MobileServiceSyncHandler {
**private boolean loop = true;**
@Override
public JsonObject executeTableOperation(
final RemoteTableOperationProcessor processor, final TableOperation operation)
throws MobileServiceSyncHandlerException {
final JsonObject clientItem = processor.getItem().getAsJsonObject();
MobileServicePreconditionFailedExceptionBase ex = null;
final JsonObject[] result = {null};
try {
result[0] = operation.accept(processor);
} catch (MobileServicePreconditionFailedExceptionBase e) {
ex = e;
} catch (Throwable e) {
ex = (MobileServicePreconditionFailedExceptionBase) e.getCause();
}
if (ex != null) {
// A conflict was detected
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set title
alertDialogBuilder.setTitle("Conflict Detected");
// set dialog message
final MobileServicePreconditionFailedExceptionBase finalEx = ex;
alertDialogBuilder
.setMessage("Choose winner")
.setCancelable(true)
.setPositiveButton("Server",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Server wins
JsonObject serverItem = finalEx.getValue();
if (serverItem == null) {
// Item not returned in the exception, retrieving it from the server
try {
serverItem = mClient.getTable(operation.getTableName()).lookUp(operation.getItemId()).get();
} catch (Exception e) {
try {
throw new MobileServiceSyncHandlerException(e);
} catch (MobileServiceSyncHandlerException e1) {
e1.printStackTrace();
}
}
}
result[0] = serverItem;
**loop = false;**
}
})
.setNegativeButton("Client",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
ToDoItem item = new ToDoItem();
// if this button is clicked, Client wins
result[0] = clientItem;
// Convert Json object to an item of my class
item.setId(clientItem.get("id").getAsString());
item.setText(clientItem.get("text").getAsString());
item.setComplete(clientItem.get("complete").getAsBoolean());
// update server's table
updateItem(item);
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
// send changes to the server DB
mClient.getSyncContext().push().get();
// get query answer from the server DB
mToDoTable.pull(mPullQuery).get();
refreshItemsFromTable();
} catch (final Exception exception) {
runOnUiThread(new Runnable() {
@Override
public void run() {
createAndShowDialog(exception, "Error");
}
});
}
return null;
}
}.execute();
**loop = false;**
}
});
runOnUiThread(new Runnable() {
@Override
public void run() {
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
}
**while(loop){}**
return result[0];
}
@Override
public void onPushComplete(MobileServicePushCompletionResult result)
throws MobileServiceSyncHandlerException {
}
}