Adapter subscribing to multiple observables

My question What is the best way for an Adapter to subscribe to multiple observables

I have an adapter that has a header and normal item types. The information for the adapter comes from the database using Sqlbrite. Using Sqlbrite, I want to update the title and list by subscribing the adapter to the observable.

Not a problem for the first observable. In my OnResume fragment:

    mSubscription = TrackerDbUtils.getListSubmissionObservable(db)
            .map(Submission.MAP)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(mAdapter);

      

However, I then try to add a second Observable to the fragment

    mHeaderSubscription = TrackerDbUtils.getSummaryObservable(db)
            .map(Summary.MAP)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(mAdapter);

      

So, I need to implement Action1 in my adapter:

public class MileageTrackerAdapter extends HeaderRecyclerViewAdapter
    implements Action1<List<Submission>>, Action1<Summary> { 
    .
    .
    .

}

      

However, I am getting duplicate class error. So I tried to implement a generic type:

public class MileageTrackerAdapter extends HeaderRecyclerViewAdapter
    implements Action1<Object> { 
    .
    .
    .
    @Override
    public void call(Object o) {
        if(o instanceof Summary){
              // Logic
        } else {
              // Logic
        }
    }
}

      

But I am getting a runtime error that I cannot display the summary for the view. Even then, I'm not sure if the best approach to the problem is to choose a pedigree.

Based on feedback from dwursteisen:

I changed my class "Summary" to map "View". I also created a new field called "isSummary". I changed my observable to the following as suggested:

TrackerDbUtils.getListSubmissionObservable(db)
    .map(Submission.MAP)
    .mergeWith(TrackerDbUtils.getSummaryObservable(db)
                              .map(Summary.MAP))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(mAdapter);

      

This creates an Observable that will fire twice; once for a bulk ticket list and another time as a size 1 list. This list is actually a summary. In my adapter:

@Override
public void call(List<Submission> mSubmissions) {

    if(mSubmissions.size() == 1 && mSubmissions.get(0).isSummary()){
        mSummary = mSubmissions.get(0);
    } else {
        mArray = new ArrayList<>(mSubmissions);
    }

    notifyDataSetChanged();

}

      

+3


source to share


2 answers


You should avoid using the same adapter for two different threads as it will deal with the concurrent problem that you can avoid using RxJava.

Why not try to combine the streams into one and then use only one adapter?



TrackerDbUtils.getListSubmissionObservable(db)
        .map(Submission.MAP)
        .mergeWith(TrackerDbUtils.getSummaryObservable(db)
                                  .map(Summary.MAP))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(mAdapter);

      

You may need to compare List<Submission>

and Summary

with the same general type or edit the object in your adapter

+2


source


Perhaps someone will give a better answer, but in situations like this, I usually create a public final anonymous instance of these interfaces. Therefore, the code looks something like this:

public class Adapter extends HeaderRecyclerViewAdapter {

    public final Action1<Summary> summary = new Action1<Summary> { ... }
    public final Action1<List<Submission>> submissions = new Action1<List<Submission>> { ... }

}

      



This way, methods inside both Action1 implementations can access everyone in the Adapter class as if they were normal methods, and I can distinguish them at the same time using mAdapter.summary or mAdapter.submissions

+1


source







All Articles