James Massey
James Massey

Reputation: 3

findFragmentById and findFragmentByTag both return null

I am trying to implement a card flip animation with fragments that have widgets in them, so I need to get access to the fragments, but I am not succeeding.

I can attach the fragments to the placeholder view in the activity and flip back and forth between two fragments, but cannot get access to the fragments.

I have tried adding the fragment with and without a tag and either way, I always get a null response from findFragmentById or findFragmentByTag.

Here are my code snippets - Thanks in advance for any insight.

File - activity_line.xml

...
    <FrameLayout
        android:id="@+id/card_placeholder_view" />
...

File - LineActivity.java

import android.app.Fragment;


public class LineActivity extends Activity {

    ...

    ControlFragment controlFragment;

    public static class CardFrontFragment extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_control, container, false);
        }
    }

    @Override
    public void onCreate {

        setContentView(R.layout.activity_line);

        getFragmentManager()
           .beginTransaction()
           .add(R.id.card_placeholder_view, new CardFrontFragment(), "fragment_tag")
           .commit();

        controlFragment = (ControlFragment)getFragmentManager().findFragmentByTag("fragment_tag");
        controlFragment = (ControlFragment)getFragmentManager().findFragmentById(R.id.card_placeholder_view);
    }
}

Upvotes: 0

Views: 118

Answers (1)

Ben P.
Ben P.

Reputation: 54194

The problem is that you are calling findFragmentByTag() and/or findFragmentById() immediately after commiting a FragmentTransaction.

Fragment transactions are, by their very nature, asynchronous. You've told the system that you want it to add your fragment, and it will... but it won't necessarily do it instantaneously (though sometimes it might).

You could make the transaction synchronous by replacing .commit() with .commitNow() or .commitNowAllowingStateLoss(), but generally I don't recommend doing that. I think you're better off just embracing the fact that the transaction is async.

Move any code that depends on the results of findFragmentByTag() or findFragmentById() out of onCreate() and into onResumeFragments() (or into the Fragments themselves).

@Override
protected void onResumeFragments() {
    super.onResumeFragments();

    controlFragment = (ControlFragment)getFragmentManager().findFragmentByTag("fragment_tag");
    controlFragment = (ControlFragment)getFragmentManager().findFragmentById(R.id.card_placeholder_view);
}

Edit

I just realized you're extending Activity and not AppCompatActivity, so onResumeFragments() doesn't exist for you. Instead, you could use onAttachFragment():

@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);

    if (fragment instanceof ControlFragment) {
        controlFragment = (ControlFragment)fragment;
    }
}

Upvotes: 1

Related Questions