naifmeh
naifmeh

Reputation: 408

RuntimeException when dynamically replacing a fragment

I have been trying to replace a fragment dynamically in my app , but I keep getting a RuntimeException when doing so , as it can't find the container ID it is supposed to add the fragment to . I have tried every single solution I found on similar threads , from doing a clean build to using a ChildFragmentManager but still , I have the same error . The weirdest thing is that when I specify no container in the onCreate , everything goes fine but as soon as a container is specified , the app crashes . Here is the code and the stack trace :

Stack Trace :

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.user.onceuponatime, PID: 23668
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.user.onceuponatime/com.example.user.onceuponatime.activity.AuthentificationActivity}: java.lang.IllegalArgumentException: No view found for id 0x7f0d007f (com.example.user.onceuponatime:id/fragment_container) for fragment SignInFragment{42d6c688 #0 id=0x7f0d007f signinfragment}
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2394)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2452)
                      at android.app.ActivityThread.access$900(ActivityThread.java:172)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1302)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:136)
                      at android.app.ActivityThread.main(ActivityThread.java:5586)
                      at java.lang.reflect.Method.invokeNative(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:515)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
                      at dalvik.system.NativeStart.main(Native Method)
                   Caused by: java.lang.IllegalArgumentException: No view found for id 0x7f0d007f (com.example.user.onceuponatime:id/fragment_container) for fragment SignInFragment{42d6c688 #0 id=0x7f0d007f signinfragment}
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1293)
                      at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
                      at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:757)
                      at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2355)
                      at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2146)
                      at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2098)
                      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2008)
                      at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388)
                      at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:607)
                      at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
                      at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1177)
                      at android.app.Activity.performStart(Activity.java:5461)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2367)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2452) 
                      at android.app.ActivityThread.access$900(ActivityThread.java:172) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1302) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:136) 
                      at android.app.ActivityThread.main(ActivityThread.java:5586) 
                      at java.lang.reflect.Method.invokeNative(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:515) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) 
                      at dalvik.system.NativeStart.main(Native Method) 

AuthentificationActivity :

public class AuthentificationActivity extends AppCompatActivity implements SignInFragment.SignInFragmentCallBack
        ,SignUpFragment.SignUpFragmentCallBack{

    public static final String SIGNINFRAGMENT_TAG = "signinfragment";
    public static final String SIGNUPFRAGMENT_TAG = "signupfragment";

    public static final int SIGNIN_FRAGMENT_ID = 846464;
    public static final int SIGNUP_FRAGMENT_ID = 125478;
    public static final int LOST_PWD_FRAGMENT_ID = 85546;

    private FragmentManager mFragmentManager;
    private SignInFragment mSignInFragment;
    private SignUpFragment mSignUpFragment;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_authentification);


        mSignInFragment = SignInFragment.getInstance();

        mFragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();


        fragmentTransaction.add(R.id.fragment_container,mSignInFragment,SIGNINFRAGMENT_TAG);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();


    }

    @Override
    public void onFragmentSwapRequested(int FragmentId) {

        mFragmentManager = this.getSupportFragmentManager();

        FragmentTransaction fgTransaction = mFragmentManager.beginTransaction();

        switch(FragmentId) {
            case SIGNUP_FRAGMENT_ID:
                if(!isFinishing()) {
                    mSignUpFragment = (SignUpFragment) mFragmentManager.findFragmentByTag(SIGNUPFRAGMENT_TAG);
                    if (mSignUpFragment == null) {
                        mSignUpFragment = SignUpFragment.getInstance();
                        fgTransaction.replace(R.id.fragment_container, mSignUpFragment, SIGNUPFRAGMENT_TAG);
                    } else {
                        fgTransaction.show(mSignUpFragment);
                    }
                    fgTransaction.addToBackStack(null);
                    fgTransaction.commit();
                }
                break;
            case LOST_PWD_FRAGMENT_ID:
                break;


        }



    }
}

SignInFragment :

public class SignInFragment extends Fragment {
    FragmentSignInBinding signInBinding;

    private CoordinatorLayout mCoordinatorLayout;
    private EditText mEmailEdit,mPasswordEdit;
    private Button btnSignIn,btnSignUp,btnLostPwd;
    private ProgressBar mProgressBar;

    private FirebaseAuth mAuth;

    private SignInFragmentCallBack mCallBack;



    public interface SignInFragmentCallBack {
        void onFragmentSwapRequested(int FragmentId);
    }

    public SignInFragment() {}


    public static SignInFragment getInstance() {
        return new SignInFragment();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mCallBack = (SignInFragmentCallBack) context;
        } catch(ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implements SignInCallaback");
        }
        Toast.makeText(context,mCallBack.toString(),Toast.LENGTH_LONG).show();
    }

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

        signInBinding = DataBindingUtil.setContentView(getActivity(),R.layout.fragment_sign_in);
        mEmailEdit = signInBinding.emailSignin;
        mPasswordEdit = signInBinding.passwordSignin;
        mProgressBar = signInBinding.progressBarSignIn;
        btnSignIn = signInBinding.signInButton;
        btnSignUp = signInBinding.signUpButton;
        btnLostPwd = signInBinding.passwordReset;
        mCoordinatorLayout = signInBinding.coordinatorSignin;



        mAuth = FirebaseAuth.getInstance();



        btnSignIn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signInAction();
            }
        });

        btnSignUp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mCallBack instanceof SignInFragmentCallBack)
                mCallBack.onFragmentSwapRequested(AuthentificationActivity.SIGNUP_FRAGMENT_ID);
            }
        });

        btnLostPwd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mCallBack instanceof SignInFragmentCallBack)
                mCallBack.onFragmentSwapRequested(AuthentificationActivity.LOST_PWD_FRAGMENT_ID);
            }
        });


    }

    private void signInAction() {
        String email = mEmailEdit.getText().toString().trim();
        final String password = mPasswordEdit.getText().toString().trim();

        if(TextUtils.isEmpty(email)) {
            Snackbar.make(mCoordinatorLayout,getString(R.string.no_email_entered),Snackbar.LENGTH_LONG).show();
            return;
        }

        if(TextUtils.isEmpty(password)) {
            Snackbar.make(mCoordinatorLayout,getString(R.string.no_password_entered),Snackbar.LENGTH_LONG).show();
            return;
        }

        mProgressBar.setVisibility(View.VISIBLE);
        mAuth.signInWithEmailAndPassword(email,password).addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                mProgressBar.setVisibility(View.GONE);
                if(task.isSuccessful()) {
                    Snackbar.make(mCoordinatorLayout,getString(R.string.login_success),Snackbar.LENGTH_LONG).show();
                    startActivity(new Intent(getActivity(), MainActivity.class));
                    getActivity().finish();
                }
                else
                {
                    Snackbar.make(mCoordinatorLayout,getString(R.string.login_failed),Snackbar.LENGTH_LONG).show();

                }
            }
        });
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_sign_in,container,false);
    }

    @Override
    public void onResume() {
        super.onResume();
        mProgressBar.setVisibility(View.GONE);
    }
}

activity_authentification.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_authentification"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.onceuponatime.activity.AuthentificationActivity">

<FrameLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/fragment_container"/>



</LinearLayout>

EDIT : I tried checking the R.java to see if the Id's were messed up but it seems like everything is fine , with the fragment_container id clearly exisisting . Also tried cleaning the project but as I expected , this didn't change anything . I tried replacing add with replace() but still , same error , except when I use android.R.id.container as the container . I am using data binding , maybe it's the cause of the conflict ?

EDIT2 : I have created a new project where I did the same transaction but with a simple fragment displaying a simple TextView , and everything seems to work fine , no crash in sight . So I tried deleting the ambiguous items in my fragment such as the callback , but I still get the same mistake . DataBinding doesn't seem to be the issue since I tried without it and still get the same stack trace .

Thank you for your help.

Upvotes: 3

Views: 1197

Answers (1)

aveuiller
aveuiller

Reputation: 1551

The problem in your code is that you are trying to bind the signInFragment UI to its behavior in the onCreate method, but this method is called before onCreateView as you can see on the fragment lifecycle.

If you move the content of your onCreate method in your onCreateView, or any method called afterward you won't have this crash anymore.

Upvotes: 1

Related Questions