Search code examples
androidmultithreadingandroid-fragmentsandroid-networking

IllegalStateException when applying arguments to a fragment after a network response


I'm getting an IllegalStateException error when I'm trying to add arguments to a fragment after a network call has completed. The crash happens while the network is doing a call and hasn't completed yet (slow networks) and you take the activity into the background (Say switching activities for example)

I need to pass data that comes from the network call to the fragment (List of urls that will populate a pageradapter for scrolling images.

My Code:

`onResume` I do the network call by calling `doWebserviceCall();`

After network call I call this method:

  private void configureImageScroller() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    Bundle bundle = new Bundle();
    // Boolean to hide the thumbnails when the Scrolling images is embedded in the item activity
    bundle.putBoolean(ScrollingTradeImagesFragment.INTENT_BOOL_EMBEDDED, false);
    // Pass the object to the Scrolling images fragment
    bundle.putParcelable(INTENT_KEY_TRADE_OBJECT, Parcels.wrap(mTradeItem));
    ScrollingTradeImagesFragment fragment = new ScrollingTradeImagesFragment();
    FragmentManager fm = getSupportFragmentManager();

    //-------Crash happens here-------//
    fragment.setArguments(bundle);
    fragmentTransaction.add(R.id.scrollable_image_container, fragment);
    fragmentTransaction.commit();
  }

method that is run when network call is complete:

      @Override
  public void populateItemViews(final TradeItem aTradeItem) {
    mTradeItem = aTradeItem;
    // Do some stuff here that is irrelevant
    configureImageScroller();
    // Do some other stuff here that is irrelevant
  }

Whats the best way to do this to prevent this crash?

EDIT:

Stacktrace:

Fatal Exception: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
   at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1493)
   at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1511)
   at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:638)
   at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:617)
   at com.bidorbuy.app.item.ItemActivity.configureImageScroller(ItemActivity.java:112)
   at com.bidorbuy.app.item.ItemActivity.populateItemViews(ItemActivity.java:233)
   at com.bidorbuy.app.item.ItemPresenter.handleNetworkResponse(ItemPresenter.java:37)
   at com.bidorbuy.app.network.NetworkManager$3.onResponse(NetworkManager.java:422)
   at com.bidorbuy.app.network.NetworkManager$3.onResponse(NetworkManager.java:419)
   at com.bidorbuy.app.network.volley.BobeRequest.deliverResponse(BobeRequest.java:127)
   at com.bidorbuy.app.network.volley.BobeRequest.deliverResponse(BobeRequest.java:26)
   at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
   at android.os.Handler.handleCallback(Handler.java:810)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:189)
   at android.app.ActivityThread.main(ActivityThread.java:5529)
   at java.lang.reflect.Method.invoke(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:372)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:950)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)

Solution

  • Your main problem is that you have not canceling a request. In your case it should be onPause method. Avoiding to do it you can bring at least to main errors to your code:

    • Running in parrallel to or more same requests. For example if you run request in onResume and have not good network connection and then exit/return to application (by pressing home button), you will have multiple same requests running since onResume will be called several times and each request takes some time.

    • Running "onComplete" callback in inconsistent state of Activity (or any other component like Fragment). Suppose you ran your request in onResume and then exit from application. onPause and onStop are invoked. onSaveInstanceState invoke and probably onDestroy too. Then your request gives success answer and you try to run some fragment for activity that was alredy stopped and saved. Thus, you have a exception.

    How to solve it You need just to cancel your request in onPause. Eventually, if you exit from application before callback will be invoked you will prevent invokation in inconsistent state. And also will prevent from multiply same request if you, for example, faslty reentering to application.