动态替换片段时的RuntimeException

时间:2017-02-24 21:32:01

标签: java android android-fragments

我一直在尝试在我的应用程序中动态替换片段,但是这样做时我一直收到RuntimeException,因为它无法找到它应该添加片段的容器ID。我尝试过在类似线程上找到的每一个解决方案,从干净的构建到使用ChildFragmentManager,但我仍然有同样的错误。 最奇怪的是,当我在onCreate中指定没有容器时,一切都很顺利但是只要指定了容器,应用程序就会崩溃。这是代码和堆栈跟踪:

堆栈追踪:

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>

编辑:我尝试检查R.java以查看Id是否搞砸了,但似乎一切都很好,其中fragment_container id显然存在。还尝试清理项目,但正如我所料,这并没有改变任何东西。我尝试用replace()替换add,但仍然是相同的错误,除非我使用android.R.id.container作为容器。我正在使用数据绑定,也许这是冲突的原因?

EDIT2:我创建了一个新项目,在那里我做了相同的事务但是有一个简单的片段显示一个简单的TextView,一切似乎工作正常,看不到崩溃。所以我尝试删除我的片段中的模糊项目,例如回调,但我仍然遇到同样的错误。 DataBinding似乎不是问题,因为我试过没有它,仍然得到相同的堆栈跟踪。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您的代码中的问题是您尝试将signInFragment UI绑定到onCreate方法中的行为,但此方法在onCreateView之前调用,如您所见fragment lifecycle

如果您在onCreate中移动onCreateView方法的内容,或之后调用的任何方法,则不会再发生此类崩溃。