用户从“警报”对话框中选择一个按钮,停止执行

时间:2014-11-14 09:45:30

标签: android conflict azure-mobile-services

在我的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 {
    }
}

2 个答案:

答案 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 {
    }


}