Stop execution until User selects a button from the Alert dialog

In my Android app, I use inonordHandler to detect conflicts between mobile device database records and server database records. When a conflict is detected, I want to display an alert dialog so that the user can choose which version of the entry "wins" (server or mobile). I have placed the Alert dialog code in the ConflictHandler class, so when a conflict is detected, the Alert dialog appears. The problem is that the code doesn't stop executing when the Alert Dialog appears, so the user can choose what action to take. It always returns 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 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 {
    }
}

      

+3


source to share


2 answers


You need to block the thread that is executing executeTableOperation

until the user clicks something in the dialog. For example, using CountDownLatch

as in the code below:



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 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


source


To stop execution, I added a boolean variable called "loop" with the value true in the while loop. When the user selects a button from the Alert dialog, the "loop" variable is set to false. The code I added is in bold. Although I believe this practice should be avoided.



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


}

      

+1


source







All Articles