Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42710

Why I'm getting java.lang.IllegalArgumentException during android.support.v4.app.Fragment.setTargetFragment

After upgrading my app to

I am getting the following crash log from live

Caused by: java.lang.IllegalArgumentException:  
  at android.support.v4.app.Fragment.setTargetFragment (Fragment.java:545)

I look at the source code of support fragment (Not exactly line 545. I'm not sure how I can get the latest source code of support fragment library)

https://android.googlesource.com/platform/frameworks/support/+/cef09fe/v4/java/android/support/v4/app/Fragment.java#598

598 public void setTargetFragment(Fragment fragment, int requestCode) {
599     mTarget = fragment;
560     mTargetRequestCode = requestCode;
561 }

I can't see a reason why java.lang.IllegalArgumentException is thrown. Maybe I'm looking at wrong version of support library source code?

Do you have any idea, why I'm getting java.lang.IllegalArgumentException during android.support.v4.app.Fragment.setTargetFragment


My source code is as follow

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;

public class BuyPortfolioFragment extends Fragment {

    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...

        // If not retained (or first time running), we need to create it.
        if (this.statusBarUpdaterFragment == null) {
            this.statusBarUpdaterFragment = StatusBarUpdaterFragment.newInstance();
            // Tell it who it is working with.
            this.statusBarUpdaterFragment.setTargetFragment(this, 0);
            fm.beginTransaction().add(statusBarUpdaterFragment, STATUS_BAR_UPDATER_FRAGMENT).commitAllowingStateLoss();
        } else {
            statusBarUpdaterFragment.setTargetFragment(this, 0);
        }

Upvotes: 2

Views: 219

Answers (1)

Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42710

This is my code, which may crash sometimes. You may reproduce, by reducing background process limit to 1.

enter image description here

public class BuyPortfolioFragment extends Fragment {

    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...

        // If not retained (or first time running), we need to create it.
        if (this.statusBarUpdaterFragment == null) {
            this.statusBarUpdaterFragment = StatusBarUpdaterFragment.newInstance();
            // Tell it who it is working with.
            this.statusBarUpdaterFragment.setTargetFragment(this, 0);
            fm.beginTransaction().add(statusBarUpdaterFragment, STATUS_BAR_UPDATER_FRAGMENT).commitAllowingStateLoss();
        } else {
            statusBarUpdaterFragment.setTargetFragment(this, 0);
        }

Note, calling setTargetFragment might not be always necessary due to Is calling setTargetFragment on headless fragment no longer necessary during UI fragment re-creation?

However, to play a safe game, I use the following fix.

public class BuyPortfolioFragment extends Fragment {

    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...

        // If not retained (or first time running), we need to create it.
        if (this.statusBarUpdaterFragment == null) {
            this.statusBarUpdaterFragment = StatusBarUpdaterFragment.newInstance();
            // Tell it who it is working with.
            this.statusBarUpdaterFragment.setTargetFragment(this, 0);
            fm.beginTransaction().add(statusBarUpdaterFragment, STATUS_BAR_UPDATER_FRAGMENT).commitAllowingStateLoss();
        } else {
            // Google poses new restriction recently. A fragment need to have same fragment
            // manager as StatusBarUpdaterFragment, in order to become its target fragment. It
            // is OK not to call setTargetFragment. Although you may get null from
            // statusBarUpdaterFragment.getTargetFragment, during onResume,
            // statusBarUpdaterFragment.getTargetFragment will magically return correct fragment.

            //statusBarUpdaterFragment.setTargetFragment(this, 0);
        }
    }

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

        ...

        // This code block might not be necessary. Just to be safe.
        if (statusBarUpdaterFragment != null) {
            // Google poses new restriction recently. A fragment need to have same fragment
            // manager as StatusBarUpdaterFragment, in order to become its target fragment. It
            // is OK not to call setTargetFragment. Although you may get null from
            // statusBarUpdaterFragment.getTargetFragment, during onResume,
            // statusBarUpdaterFragment.getTargetFragment will magically return correct fragment.

            try {
                statusBarUpdaterFragment.setTargetFragment(this, 0);
            } catch (java.lang.IllegalArgumentException e) {
                // Shouldn't happen. Just to be safe.
                Log.e(TAG, "", e);
            }
        }

Upvotes: 1

Related Questions