How to use Two NotifyDataSetChanged() Atomically

70 views Asked by At

To summarize my problem:

I have a list of items and a button that I click to query an API

When I click the button, two methods are called. The first method displays a progress bar, clears the list, and uses notifyDataSetChanged()

public void methodOne(){
      mProgressBar.setVisibility(View.VISIBLE);
      mList.clear;
      mAdapter.notifyDataSetChanged();
}

The second method uses retrofit to make a query, and in the callback method, I hide the progress bar, add to the list and call notifyDataSetChanged();

public void methodTwo(){
      RetrofitInterfaces.SearchForPosts service = RetrofitClientInstance.getRetrofitInstance()
                .create(RetrofitInterfaces.SearchForPosts.class);
        Call<Feed> call = service.listRepos(url);
        call.enqueue(new Callback<Feed>() {
            @Override
            public void onResponse(@NonNull Call<Feed> call, @NonNull Response<Feed> response) {
               
                try{

                   mProgressBar.setVisibility(View.INVISIBLE);
                   mList.addAll(response.body().getData()); 
                   mAdapter.notifyDataSetChanged();

                } catch(Exception e){
                   Log.e(TAG, "Error: " + e);
                }
                
            }

            @Override
            public void onFailure(@NonNull Call<Feed> call, @NonNull Throwable t) {
                Log.e(TAG, "onFailure: " + t);
     
            }
        });
    }

}

My problem is when I call these two ones after another:

methodOne();
methodTwo();

The second method with the retrofit call sometimes returns an IndexOutOfBounds exception because methodOne() calls mList.clear() and mAdapter.notifyDataSetChanged(); while I am making edits to mList.

My question is how can I make the two happen atomically so that they don't interfere with each other? (I want methodOne() to do everything even before the query happens in methodTwo)

1

There are 1 answers

0
Hayssam Soussi On BEST ANSWER

You can use AsyncTask that will execute methodTwo() when methodOne() finished executing

private class MethodsTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... voids) {
        methodOne();
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        methodTwo();
    }
}

So instead of calling the two methods

methodOne();
methodTwo();

Use this

MethodsTask task = new MethodsTask();
task.execute();