0

I've got an activity with a retained fragment. This fragment handles DB queries and sends the results back to the activity via an interface.

When I rotate the device, the activity is destroyed and re-creates itself as expected. It also re-connects to the retained fragment (which wasn't destroyed) which is continuing to handle the DB queries despite the device rotation.

My problem is when the retained fragment gets the DB queries result back, it tries to send these via the interface to the activity. But, if the device has been rotated, the activity could be in the destroyed state (and not yet re-created) so the fragment can't send the results to the activity.

When the activity is eventually re-created, it's missed "it's chance" to receive the interface calls from the fragment and get the DB results. How to solve this?

Just a bit more detail - the activity has a button which the user presses to start the retained fragment doing the DB queries (they don't just start automatically when the activity is created or the activity attached to the fragment).

Activity.onCreate()

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);

    // Get our Retained Fragment if already exists, otherwise create a new one
    FragmentManager fragManager = getSupportFragmentManager();
    mRetFrag = (QueryFragment) fragManager.findFragmentByTag(QueryFragment.FRAGMENT_TAG);
    if (mRetFrag == null) {
        // First time - create a new retained fragment
        mRetFrag = QueryFragment.newInstance();
        fragManager.beginTransaction().add(mRetFrag, QueryFragment.FRAGMENT_TAG).commit();
    } 

    // Button to start DB querying in fragment
    Button queryBtn = (Button) findViewById(R.id.query_button);
    queryBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mRetFrag.runDBQueries();
        }
    });
}

And in the fragment when it has the DB query results, I try to send this back to the Activity. So, mCallbackListener could be null if the activity isn't yet created.

// Pass the data to the activity
if (mCallbackListener != null) {
      mCallbackListener.onQueryFinished(data);
}
MickeyR
  • 1,858
  • 2
  • 13
  • 24

1 Answers1

1

Your mCallbackListener points to an activity, which doesn't exist anymore, as long as it has been destroyed after rotation.

You have to get another instance of your activity:

if(null == mCallbackListener) {
mCallbackListener = (MainActivity) getActivity();    
}

Another solution is to use event bus like Greenrobot's EventBus or Otto.

Here's nice blog about how to use Otto.

azizbekian
  • 60,783
  • 13
  • 169
  • 249
  • Hi, yes I do the above in the fragment onActivityCreated(). So, I do get the new reference. But my problem is that the fragment has already tried sending the DB results and the activity missed theM. – MickeyR Dec 29 '15 at 16:54
  • It is possible only if you're calling `mCallbackListener.onQueryFinished(data);` from a worker thread (non UI thread) and had a bad luck that that call happened when activity hasn't yet been created. If you're calling that method from UI thread, than the activity can't miss it, because your activity has to be created in order your fragment (although retained) has chance to be started. – azizbekian Dec 29 '15 at 17:07
  • The fragment and activity both run on the UI thread. The Db query runs in an Async background thread. I think basically there is a small window of time when there is no Activity to send the results to (because it's destroyed and not yet re-created). I'm wondering how to handle this gap. Should the fragment 'wait' until the activity is recreated somehow and send again. Or should the Activity check with the fragment to see if it tried to send the data but couldn't? – MickeyR Dec 29 '15 at 22:05
  • You should use event bus, like Otto. [Here](http://www.nilzorblog.com/2014/06/building-solid-json-rest-client-in.html)'s a nice blog about it – azizbekian Dec 30 '15 at 06:21
  • Perfect ! That looks just like I was after. Thsnks a lot. If you can put this as a separate answer I can tick it. – MickeyR Dec 30 '15 at 12:51