1

I have an hour of experience using RxJava and I am trying to implement it in my project instead of using interfaces and listeners.

I have an async task which calls a google cloud endpoint method in a separate module and receives a List<Profile> when done.

In the onPostExecute() method of the async task, I call onNext so that any subscribers receive this data.

Here is what the AsyncTask looks like:

private BirthpayApi mApi;
private String mUserId;
private ReplaySubject<List<Profile>> notifier = ReplaySubject.create();

public GetFriends(String userId) {
    mUserId = userId;
}

public Observable<List<Profile>> asObservable() {
    return notifier;
}

@Override
protected List<Profile> doInBackground(Void... params) {
    if (mApi == null) {
        BirthpayApi.Builder builder = new BirthpayApi.Builder(AndroidHttp.newCompatibleTransport(),
                    new AndroidJsonFactory(), null)
                    // options for running against local devappserver
                    // - 10.0.2.2 is localhost's IP address in Android emulator
                    // - turn off compression when running against local devappserver
                    .setRootUrl("http://10.0.2.2:8080/_ah/api/")
                    .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                    @Override
                    public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                            abstractGoogleClientRequest.setDisableGZipContent(true);
                        }
                    });
            mApi = builder.build();
    }

    try {
        return mApi.getFriends(mUserId).execute().getItems();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

@Override
protected void onPostExecute(List<Profile> friends) {
    super.onPostExecute(friends);
    notifier.onNext(friends);
}

In my Fragment I then want to collect this data from the async task calling the onNext() method. I therefore use implements Action1<List<Profile>> when declaring my class which also extends Fragment.

In the onCall() method that comes from the Action1 interface I collect the data sent from the Async task:

@Override
public void call(List<Profile> profiles) {
    if (profiles.size() > 0) {
        updateAdapter(profiles);
    } else
        setUpNoFriendsViews();
}

I am following along with treehouse but they use a object to model their data which becomes the observable instead of using an async class and they use an adapter as the observer. Am I doing this wrong, either way how do I get it to work?

Aftab
  • 2,863
  • 32
  • 41
Tom Finet
  • 2,056
  • 6
  • 30
  • 54
  • so you want your observable to emit an updated profile list when you make your call? – Will Evers Jul 13 '16 at 14:56
  • Then you want an observable that observes events that would change your list and maps it into your updated list by calling your api in a function. to do this asynchronously you will have to use the RXbindings library OR call continue to use your async call – Will Evers Jul 13 '16 at 15:27
  • Could you give me an example please (in code)? – Tom Finet Jul 13 '16 at 15:29
  • http://stackoverflow.com/questions/33415151/asynctask-replacement-with-rxjava-help-needed/33421148#33421148 the answer I provided creates an observable of events and maps it to a String. then I make my rest call in subscribe. what I did is different but it may give you a better idea. – Will Evers Jul 13 '16 at 15:32
  • Where should this code be placed, activity? – Tom Finet Jul 13 '16 at 15:40

1 Answers1

5

It doesn't look like you're subscribing to the Observable you're creating anywhere and it's not clear where you're calling execute on the AsyncTask. Also I don't think you'd want a ReplaySubject but that depends on what you're trying to achieve.

All that aside I'd suggest completely switching over to Rx rather than mixing up Rx and AsyncTasks. In this case in your model class make a method something like:

public Observable<List<Profile>> getProfiles() {

    return Observable.defer(new Func0<Observable<List<Profile>>>() {
        @Override
        public Observable<List<Profile>> call() {

            if (mApi == null) {
                BirthpayApi.Builder builder = new BirthpayApi.Builder(AndroidHttp.newCompatibleTransport(),
                        new AndroidJsonFactory(), null)
                        // options for running against local devappserver
                        // - 10.0.2.2 is localhost's IP address in Android emulator
                        // - turn off compression when running against local devappserver
                        .setRootUrl("http://10.0.2.2:8080/_ah/api/")
                        .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                            @Override
                            public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                                abstractGoogleClientRequest.setDisableGZipContent(true);
                            }
                        });
                mApi = builder.build();
            }

            try {
                List<Profile> profiles = mApi.getFriends(mUserId).execute().getItems();
                return Observable.just(profiles);
            } catch (IOException e) {
                return Observable.error(e);
            }
        }
    });
}

Then in your Fragment:

modal.getProfiles()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
        new Action1<List<Profile>>() {
                //...
        },
        new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    );
Jahnold
  • 7,623
  • 2
  • 37
  • 31