3

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.

naifmeh
  • 408
  • 5
  • 15
  • By the way... "authentication", not "authentification" – OneCricketeer Feb 24 '17 at 21:35
  • :) The rest of the variables are english... Anyways.. `fragment_container` definitely exists, and you only use it three spots, but the error comes from an `onStart` of an Activity, which it's not clear where – OneCricketeer Feb 24 '17 at 21:43
  • Yes that's what the stack trace is showing but i don't even override the onStart() .I tried running it on 2 different devices but the bug is code related and not device related – naifmeh Feb 24 '17 at 21:52
  • The crash only happens when you swap? – OneCricketeer Feb 24 '17 at 21:56
  • If i specify the container in the add() method , the app doesn't even start . It crashes immediately , if i specify no container ID except in the replace() method , it crashes when I swap ! – naifmeh Feb 24 '17 at 21:59
  • Worth checking out - http://stackoverflow.com/a/16843590/2308683 – OneCricketeer Feb 24 '17 at 22:05
  • Already checked this thread , most of the answers did not work out for me , or were not suited to my case . I will read it again and see if i missed something – naifmeh Feb 24 '17 at 22:12
  • Check that one answer I linked to. Open up the `R.java` file and see if your id's are messed up. Even if not, cleaning the app, or making sure you have no other `fragment_container` ID in another layout file. – OneCricketeer Feb 24 '17 at 22:43
  • Just checked the R file again but everything seems right . Tried cleaning the project , but same mistake. I'm using data binding , maybe it's causing the errors ? – naifmeh Feb 25 '17 at 12:37
  • I just realized you had data-binding and you are doing it wrong in a Fragment. http://stackoverflow.com/questions/34706399/how-to-use-data-binding-with-fragment#34719627 – OneCricketeer Mar 06 '17 at 09:29
  • Thank you! The problem was coming from here! – naifmeh Mar 06 '17 at 10:21

1 Answers1

1

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.

aveuiller
  • 1,511
  • 1
  • 10
  • 25
  • Thank you ! This has fixed my main issue , however , when I click on the button which is supposed to show the SignUpFragment , I get the IllegalStateArgument exception , even though I moved most of the critical code to the onActivityCreated() . Any hints ? I'm thinking of just getting rid of the DataBinding since it has caused only problems so far. – naifmeh Mar 06 '17 at 20:24