Search code examples
androidthread-prioritybackendless

Priority on AsyncCallback


I have another problem in my application. I use the following code in the MainActivity to fetch the user data from my ContactAdapter:

private List<String> loadContactData() {
    ContactAdapter db = new ContactAdapter(getApplicationContext());
    // Spinner Drop down elements
    List<String> contacts = db.getAllContacts();        
    // Creating adapter for spinner
    ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, contacts);
    // Drop down layout style - list view with radio button   
 dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);        
    Log.d("SPINNER", String.valueOf(contacts));
    return contacts;
}

And the ContactAdapter:

public List<String> getAllContacts(){
    final List<String> contacts_id = new ArrayList<String>();
    final List<String> contacts_name = new ArrayList<String>();
    Backendless.Data.of(BackendlessUser.class).find(new AsyncCallback<BackendlessCollection<BackendlessUser>>() {
        public void handleResponse(BackendlessCollection<BackendlessUser> users) {
            Iterator<BackendlessUser> userIterator = users.getCurrentPage().iterator();
            while (userIterator.hasNext()) {
                BackendlessUser user = userIterator.next();
                String user_mail = user.getEmail();
                String user_id = user.getUserId();
                contacts_name.add(user_mail);
                contacts_id.add(user_id);
            }
            Log.d("getAllContacts: ", String.valueOf(contacts_name)); }
        public void handleFault(BackendlessFault backendlessFault) {
            System.out.println("Server reported an error - " + backendlessFault.getMessage());}});
    return contacts_name;
}

Certainly my problem is that the Backendless query is to slow... so in my Logcat I see first an empty "SPINNER" and second "getAllContacts" with the user data from the server. As a result of that the return contacts statement from loadContactData() is empty too.

How can I achieve that getAllContacts() is finished first to get the user data in loadContactData()?


Solution

  • Your issue is that the find call is asynchronous (which is good and means handleResponse() is called on a new thread). So when your return contacts_name is run, contacts_name is still empty because your code in handleResponse() has not yet run because the new thread is still waiting for the response of the database.

    The call to your database is slow because it may include file or even network IO. You should never do this on the main thread which is working with your views, otherwise the app will no longer respond because the main thread updating the UI (and painting the spinner animation) is busy waiting for the database. By making the database request asynchronous your app stays responsive and the UI will not get "stuck".

    To keep things simple you can do it like this:

    public class MyActivity extends AppCompatActivity {
    
       private List<String> mContactIds = new ArrayList<>();
    
        private Spinner mSpinner;
    
        private ProgressDialog mProgressDialog;
    
        @Overrride
        public void onCreate() {
    
            this.setContentView(...);
            this.mSpinner = ...;
    
            this.showLoadingDialog();
    
            Backendless.Data.of(BackendlessUser.class).find(new AsyncCallback<BackendlessCollection<BackendlessUser>>() {
                public void handleResponse(BackendlessCollection<BackendlessUser> users) {
    
                    List<String> mails = new ArrayList<>();
                    List<String> ids = new ArrayList<>();
                    Iterator<BackendlessUser> userIterator = users.getCurrentPage().iterator();
                    while (userIterator.hasNext()) {
                        BackendlessUser user = userIterator.next();
                        String mail = user.getEmail();
                        String id = user.getUserId();
                        mails.add(user_mail);
                        ids.add(user_id);
                    }
    
                    Log.d("getAllContacts: ", String.valueOf(contacts_name)); 
                    applyData(mails, ids);
    
                } 
    
                public void handleFault(BackendlessFault backendlessFault) {
                    Log.e("error: ", "Something went wrong");
    
                }
            });
        }
    
        private void applyData(List<String> mails, List<String> ids) {
           Log.d("getAllContacts: ", String.valueOf(contacts_name)); 
           this.hideLoadingDialog();
           this.mContactIds = ids;
           this.mSpinner.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mails);
    
        }
    
        private void showLoadingDialog() {
            this.mLoadingDialog = new ProgressDialog(this, null, "Loading contacts...", true);
            this.mLoadingDialog.dismiss();
    
        }
    
        private void hideLoadingDialog() {
            if(this.mLoadingDialog != null) {
                this.mLoadingDialog().dismiss();
    
            }
        }
    
        private void showErrorDialog() {
            this.hideLoadingDialog();
            new AlertDialog.Builder(this)
                .setMessage("Something went wrong, try again")
                .setPositiveButton("Ok", null)
                .show();
    
        }
    }