2

I am using Otto to get result to a fragment when an http request is made successfully.

In my application I have a viewpager. And because the pages are very similar, I use the same fragments in viewpager with different data, to download data.

The fragment methods looks like

 @Override
public void onResume() {
    super.onResume();

    MMApp.getBus().register(this);
}


@Override
public void onPause() {
    super.onPause();
    MMApp.getBus().unregister(this);
}

  @Subscribe
public void onHttpResponseReceived(VolleySuccesObject results) {
}

The data getting mixed, for example the result in page one is showing in page two also.Does any one know how to solve this

Jithin Sunny
  • 3,352
  • 4
  • 26
  • 42
  • This is because all of your fragments under the viewpager are subscribed to VolleySuccesObject. So when the data is posted on the bus with this object all the listeners are called. I am also facing a similar problem and looking for a solution. – MarutiB Mar 18 '15 at 09:43
  • @MarutiB wrap the result in an object that knows which page it is destined for and check that value in the subscriber. – Jithin Sunny Mar 23 '15 at 06:43
  • yup followed something similar :) Here is my source http://itbrokeand.ifixit.com/2013/11/12/android-api-calls.html – MarutiB Mar 23 '15 at 06:49

2 Answers2

1

This is because ViewPager keeps multiple fragments started for performance reasons. If you want to know which fragment is really visible, you should override setUserVisibleHint() method and register/unregister fragments at the bus there. Be aware that this method defaults to true. This means Android won't call it with true value initially. Thus your logic inside setUserVisibleHint() must check registration status and call register()/unregister() only when needed. Same is valid for onStop() method. If unregister has been already called inside setUserVisibleHint() then you don't need to call it inside onPause(), otherwise Otto will throw an exception.

Open source TinyBus uses Otto-like API and has a special method called hasRegistered(Object) intended exactly for this situation, to check whether given object is registered to the bus or not.

sergej shafarenka
  • 20,071
  • 7
  • 67
  • 86
0

I encountered the same issue. As @sergej shafarenka pointed out, viewpagers basically pre-loads a fragment based on your viewpager settings (which defaults to 1).

What's happening is your subscribed to the same object for each of your Fragments (i.e., VolleySuccesObject for your case). Now, while your Fragment A is in the foreground, Fragment B also gets loaded and so does its lifecycles, which where you register your bus.

At this point Fragment A and B (assuming, you're currently at Fragment A) are both listening to VolleySuccesObject.

The solution is based on your use-case, of course. My scenario is that I send a request for a Person object based off of an id. Now my Fragment A and B will receive these Person A and Person B, but both my fragments will receive this object. The Person object I get back doesn't give the Person's id, so that was a big issue since I had no way to find out for which the Person object is for.

Solution: I used a wrapper for my Person objects (PersonResponseWrapper) where my API Service responsible for returning this PersonResponseWrapper that contains both the Person AND the id. So when on my @Subscribe, I have this code:

private String mId; //id used for the API call

@Subscribe
public void onPersonReponseReceived(PersonResponseWrapper response) {
   if(mId.equalsIgnoreCase(response.getid()) { //Yup, this the Person object for me. Processing...
        process(response.getPerson());
   }
}

Hope this helped. This plagued me for days! Will answer this post in case someone encounters a similar requirement.

hadez30
  • 503
  • 5
  • 18