rx android vs mosby pattern load data recyclerview



Answers

What you can do is whatever you do in activity like your AsycTask and RecyclerView, put it inside a fragment and, setRetainInstance(true) in onCreateView() method of fragment and load that fragment in your activity.

setRetainInstance(true) won't let your fragment instance destroy when screen is rotated.

Question

I am working on an Android app. The code I attach is creating a recyclerview. The very first thing we do is to create an asynctask that would fetch data on an SQLite database and load it into the adapter->recylcerview. While the background task is working, a progressdialog is shown to the user.

public class HomeActivity extends AppCompatActivity
{
    private RecyclerView recycler;
    private RecyclerViewAdapter adapter;
    private SwipeRefreshLayout swipeRefresh;
    private progressDialog progressDialog;

     // ... some code here

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ... some code here


    createRecyclerView();
    loadRecyclerView();


    // ... some code here

    }


    private void loadRecyclerView()
    {
        new LoadingBackgroundTask().execute();
    }



    private void createRecyclerView()
{

    Context context = getApplicationContext();

    recycler = (RecyclerView) findViewById(R.id.recycle_view_home);
    recycler.setHasFixedSize(true);

    RecyclerView.LayoutManager lManager = new LinearLayoutManager(context);
    recycler.setLayoutManager(lManager);

    adapter = new RecyclerViewAdapter();

    recycler.setAdapter(adapter);
    recycler.setItemAnimator(new DefaultItemAnimator());

}

private class LoadingBackgroundTask extends AsyncTask<Void, Void, List<items>> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = ProgressDialog.show(HomeActivity.this, getString(R.string.dialog_load_list),getString(R.string.dialog_please_wait), false, false);

    }

    @Override
    protected List doInBackground(Void... params) {

        List<items> lists;
        //Data Source Class ( SQLite)
        ListDS listDS = new ListDS(getApplicationContext());
        list = listDS.getList();

        return list;
    }

    @Override
    protected void onPostExecute(List result) {
        super.onPostExecute(result);

        //it inserts de list on recyclerview performing animation
        adapter.animate(result);

        progressDialog.dissmiss();
        swipeRefresh.setRefreshing(false);
        recycler.scrollToPosition(0);
    }

}

}

So far, so good. However, as you probably know this code has some well-known issues; for example if I rotate the screen while asynctask is doing its magic, it will crash the app.

I've tried an alternative I've seen Googling, rxandroid.

(Sorry if I typed something wrong, I am doing it by memory)

public class HomeActivity extends AppCompatActivity
{
 private Subscriber suscriptor;
private progressDialog progressDialog;

 //some code ....

  @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    suscriptor = new Subscriber() {
        @Override
        public void onCompleted() {
            progressDialog.dismiss();
            Log.d("SUSCRIPTOR","ON COMPLETE");
        }

        @Override
        public void onError(Throwable e) {
            Log.d("SUSCRIPTOR","ON ERROR");
        }

        @Override
        public void onNext(Object o) {
            adapter.animate((List<items>)o);

        }
    };


    Observable.create(
            new Observable.OnSubscribe<List<items>>() {
                @Override
                public void call(Subscriber<? super List<items>> sub) {
                progressDialog = ProgressDialog.show(HomeActivity.this,  getString(R.string.dialog_load_list),getString(R.string.dialog_please_wait), false, false);
                    List<items> lists;
                    //Data Source Class ( SQLite)
                    ListDS listDS = new ListDS(getApplicationContext());
                    list = listDS.getList();

                    sub.onNext(list);
                    sub.onCompleted();

                }

                @Override
                protected void finalize() throws Throwable {
                    super.finalize();
                    Log.d("OBSERAVBLE","FINALIZED");
                }
            })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.newThread())
           .cache()
    .subscribe(suscriptor);

    }


@Override
public void onDestroy()
{
    if(suscriptor!=null)
    {
        if(!suscriptor.isUnsubscribed())
        {
            suscriptor.unsubscribe();
        }
    }

    super.onDestroy();
}

}

Now the app is not crashing anymore when I rotate the screen. However, the observable keeps working on the background until it finishes but as I unsubscribe to avoid crashing, I don't receive the results properly. Moreover, progressbar disappears even though the observable keeps working as I mentioned.

Looking for a solution, I found there is a pattern called "Ted Mosby" which seems to solve my problem. Although it looks promising, I think is too much coding for something I felt it is not worth it and that rxandroid may have a workaround.

So, my question is how can I get what I want without getting immersed in an architectural coding mess too big for my purpose? Could you give an example if you guys have solved this? Do you think I am wrong and I should implement TedMosby pattern?




Links



Tags