2017-12-31 253 views
0

私は認証アクティビティを作成しました。これは、ユーザが使用したい対応するフラグメントを置き換えるコンテナとしてFrameLayoutです。3つの断片の単一アクティビティがクラッシュする

容器内の最初の断片はLoginFragment又はSignUpFragmentに移動するロゴと2つのボタンの背景、ImageViewのとちょうどConstraintLayoutあるWelcomeFragment、です。

問題は、私はLoginFragmentWelcomeFragmentから行くとき、バックWelcomeFragmentに来SignUpFragmentに行き、そしてWelcomeFragment、再びカムバックしよう、ということですアプリケーションがクラッシュし、私に次のエラーを与える:

エラーのスタックトレース:

12-31 18:44:45.558 4367-4367/com.nopeia.fitassistant E/MessageQueue-JNI: android.view.InflateException: Binary XML file line #0: Binary XML file line #0: Error inflating class 
<unknown> 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:539) at android.view.LayoutInflater.inflate(LayoutInflater.java:423) at com.nopeia.fitassistant.ui.authentication.welcome.WelcomeFragment.onCreateView(WelcomeFragment.java:50) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419) at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809) 
    at android.support.v4.app.BackStackRecord.executePopOps(BackStackRecord.java:857) at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2577) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367) 
    at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322) at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:851) at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:794) 
    at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:174) at android.app.Activity.onKeyUp(Activity.java:2482) at android.view.KeyEvent.dispatch(KeyEvent.java:2665) at android.app.Activity.dispatchKeyEvent(Activity.java:2735) 
    at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:534) at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:58) at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:316) 
    at com.android.internal.policy.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2352) at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4206) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4168) 
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3682) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3735) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3701) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3709) 
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3682) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3735) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3701) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3828) 
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3709) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3885) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3682) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3735) 
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3701) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3709) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3682) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3735) 
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3701) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3861) at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4022) at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2257) 
    at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1878) at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1869) at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2234) 
    at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:1 12-31 18:44:45.559 4367-4367/com.nopeia.fitassistant E/AndroidRuntime: FATAL EXCEPTION: main Process: com.nopeia.fitassistant, PID: 4367 android.view.InflateException: 
    Binary XML file line #0: Binary XML file line #0: Error inflating class 
    <unknown> 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:539) at android.view.LayoutInflater.inflate(LayoutInflater.java:423) at com.nopeia.fitassistant.ui.authentication.welcome.WelcomeFragment.onCreateView(WelcomeFragment.java:50) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419) at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809) 
    at android.support.v4.app.BackStackRecord.executePopOps(BackStackRecord.java:857) at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2577) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367) 
    at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322) at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:851) at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:794) 
    at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:174) at android.app.Activity.onKeyUp(Activity.java:2482) at android.view.KeyEvent.dispatch(KeyEvent.java:2665) at android.app.Activity.dispatchKeyEvent(Activity.java:2735) 
    at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:534) at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:58) at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:316) 
    at com.android.internal.policy.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2352) at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4206) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4168) 
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3682) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3735) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3701) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3709) 
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3682) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3735) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3701) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3828) 
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3709) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3885) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3682) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3735) 
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3701) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3709) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3682) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3735) 
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3701) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3861) at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4022) at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2257) 
    at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1878) at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1869) at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2234) 
    at android.view.Inp 

AuthenticationActivity.class:

package com.nopeia.fitassistant.ui.authentication; 

import android.content.Intent; 
import android.support.annotation.NonNull; 
import android.os.Bundle; 
import android.support.annotation.Nullable; 
import android.util.Log; 

import com.google.android.gms.auth.api.Auth; 
import com.google.android.gms.auth.api.signin.GoogleSignInOptions; 
import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.api.GoogleApiClient; 
import com.google.firebase.auth.FirebaseAuth; 
import com.google.firebase.auth.FirebaseUser; 
import com.nopeia.fitassistant.R; 
import com.nopeia.fitassistant.ui.authentication.login.LoginContract; 
import com.nopeia.fitassistant.ui.authentication.login.LoginFragment; 
import com.nopeia.fitassistant.ui.authentication.signup.SignUpContract; 
import com.nopeia.fitassistant.ui.authentication.signup.SignUpFragment; 
import com.nopeia.fitassistant.ui.authentication.welcome.WelcomeContract; 
import com.nopeia.fitassistant.ui.authentication.welcome.WelcomeFragment; 
import com.nopeia.fitassistant.ui.myzone.MyZoneActivity; 
import com.nopeia.fitassistant.util.ActivityUtils; 

import javax.inject.Inject; 

import dagger.android.support.DaggerAppCompatActivity; 

public class AuthenticationActivity extends DaggerAppCompatActivity 
     implements WelcomeContract.onWelcomeLoginClickListener, 
     WelcomeContract.onWelcomeSignUpClickListener, 
     LoginContract.View.onLoginButtonClickListener, 
     LoginContract.View.onSignupClickListener, 
     SignUpContract.View.onLoginClickListener, 
     SignUpContract.View.onSignupButtonClickListener, GoogleApiClient.OnConnectionFailedListener { 

    private static final String TAG = AuthenticationActivity.class.getSimpleName(); 

    @Inject 
    WelcomeFragment mWelcomeFragmentProvider; 

    @Inject 
    LoginFragment mLoginFragmentProvider; 

    @Inject 
    SignUpFragment mSignUpFragmentProvider; 
    private GoogleApiClient mGoogleApiClient; 

    // Firebase 
    @Inject 
    FirebaseAuth mFirebaseAuth; 

    FirebaseUser mFirebaseUser; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_welcome); 


     WelcomeFragment welcomeFragment = (WelcomeFragment) getSupportFragmentManager() 
       .findFragmentById(R.id.authenticationActivity_fragment); 

     if(welcomeFragment == null){ 

      welcomeFragment = mWelcomeFragmentProvider; 

      Log.d("AuthActivity", mWelcomeFragmentProvider.toString()); 

      ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), 
        welcomeFragment, R.id.authenticationActivity_fragment); 

     } 

     GoogleSignInOptions googleSignInOptions = new GoogleSignInOptions 
       .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 
       .requestIdToken(getString(R.string.default_web_client_id)) 
       .requestEmail() 
       .build(); 

     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .enableAutoManage(this, this) 
       .addApi(Auth.GOOGLE_SIGN_IN_API, googleSignInOptions) 
       .build(); 


     // Load previously saved state, if available. 
     if (savedInstanceState != null) { 
//   TasksFilterType currentFiltering = 
//     (TasksFilterType) savedInstanceState.getSerializable(CURRENT_FILTERING_KEY); 
//   mTasksPresenter.setFiltering(currentFiltering); 
     } 

    } 


    @Override 
    public void onWelcomeSignUpButtonClicked() { 
     SignUpFragment signUpFragment = mSignUpFragmentProvider; 

     ActivityUtils.replaceFragmentInActivity(getSupportFragmentManager(), 
       signUpFragment, R.id.authenticationActivity_fragment); 
    } 

    @Override 
    public void onWelcomeLoginButtonClicked() { 

     LoginFragment loginFragment = mLoginFragmentProvider; 

     ActivityUtils.replaceFragmentInActivity(getSupportFragmentManager(), 
       loginFragment, R.id.authenticationActivity_fragment); 

    } 

    @Override 
    public void onLoginButtonClicked() { 

    } 

    @Override 
    public void onSignupTextViewClicked() { 
     onWelcomeSignUpButtonClicked(); 
    } 

    @Override 
    public void onSignupButtonClicked() { 

    } 

    @Override 
    public void onLoginTextViewClicked() { 
     onWelcomeLoginButtonClicked(); 
    } 

    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 
     Log.d(TAG, "onConnectionFailed:" + connectionResult); 
    } 

    public GoogleApiClient getmGoogleApiClient() { 
     return mGoogleApiClient; 
    } 

    public void setmGoogleApiClient(GoogleApiClient mGoogleApiClient) { 
     this.mGoogleApiClient = mGoogleApiClient; 
    } 

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

     // Check if user is signed in. 
     mFirebaseAuth = FirebaseAuth.getInstance(); 
     mFirebaseUser = mFirebaseAuth.getCurrentUser(); 

     if (mFirebaseUser != null) { 
      //Not signed in launch the Sign In activity 
      startActivity(new Intent(this, MyZoneActivity.class)); 
      finish(); 
     } 
    } 
} 

WelcomeFragment.java:

package com.nopeia.fitassistant.ui.authentication.welcome; 

import android.content.Context; 
import android.net.Uri; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Button; 

import com.nopeia.fitassistant.R; 
import com.nopeia.fitassistant.ui.authentication.login.LoginContract; 

import javax.inject.Inject; 

import butterknife.BindView; 
import butterknife.ButterKnife; 
import dagger.android.support.DaggerFragment; 


public class WelcomeFragment extends DaggerFragment { 


    @BindView(R.id.welcome_activity_login_ButtonView) 
    Button mLoginButtonView; 

    @BindView(R.id.welcome_activity_signup_ButtonView) 
    Button mSignUpButtonView; 

    private WelcomeContract.onWelcomeSignUpClickListener mSignupCallback; 
    private WelcomeContract.onWelcomeLoginClickListener mLoginCallback; 


    @Inject 
    public WelcomeFragment() { 
     // Required empty public constructor 
    } 

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

    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     View rootView = inflater.inflate(R.layout.fragment_welcome, container, false); 
     ButterKnife.bind(this, rootView); 

     mLoginButtonView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       mLoginCallback.onWelcomeLoginButtonClicked(); 
      } 
     }); 

     mSignUpButtonView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       mSignupCallback.onWelcomeSignUpButtonClicked(); 
      } 
     }); 

     return rootView; 
    } 


    @Override 
    public void onAttach(Context context) { 

     try { 
      mSignupCallback = (WelcomeContract.onWelcomeSignUpClickListener) context; 
     } catch (ClassCastException e){ 
      throw new ClassCastException(context.toString() 
        + " must implement onSignupButtonClickListener" 
      ); 
     } 

     // Get login callback activity 
     try { 
      mLoginCallback = (WelcomeContract.onWelcomeLoginClickListener) context; 
     } catch (ClassCastException e){ 
      throw new ClassCastException(context.toString() 
        + " must implement onLoginClickListener" 
      ); 
     } 

     super.onAttach(context); 



    } 

    @Override 
    public void onDetach() { 

     mSignupCallback = null; 
     mLoginCallback = null; 

     super.onDetach(); 

    } 

} 

ActivityUtil.java:あなたはreplace()メソッドを見ることができるように

package com.nopeia.fitassistant.util; 

import android.annotation.SuppressLint; 
import android.support.annotation.NonNull; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentTransaction; 

import com.nopeia.fitassistant.R; 

import static android.support.v4.util.Preconditions.checkNotNull; 

/** 
* Created by Pujolsluis on 12/7/2017. 
*/ 

public class ActivityUtils { 


    @SuppressLint("RestrictedApi") 
    public static void addFragmentToActivity (@NonNull FragmentManager fragmentManager, 
               @NonNull Fragment fragment, int frameId) { 
     checkNotNull(fragmentManager); 
     checkNotNull(fragment); 
     String backStateName = fragment.getClass().getName(); 
     FragmentTransaction transaction = fragmentManager.beginTransaction(); 
     transaction.add(frameId, fragment, backStateName); 
     transaction.commit(); 
    } 

    public static void replaceFragmentInActivity(@NonNull FragmentManager fragmentManager, 
               @NonNull Fragment fragment, int frameId){ 

     //Avoid Fragments stacking up in the backstack if they already exist in it 
     String backStateName = fragment.getClass().getName(); 

     boolean fragmentPopped = fragmentManager.popBackStackImmediate (backStateName, 0); 

     if (!fragmentPopped){ //fragment not in back stack, create it. 

      FragmentTransaction transaction = fragmentManager.beginTransaction(); 

      // Replace fragment, with fade in and fadeout animation 
      // and add transaction to backstack to allow the user to undo 
      // the action he just did and recover the last fragment state 
      transaction.setCustomAnimations(
        android.R.anim.slide_in_left, 
        android.R.anim.slide_out_right, 
        android.R.anim.slide_in_left, 
        android.R.anim.slide_out_right 
      ); 
      transaction.replace(frameId, fragment); 
      transaction.addToBackStack(backStateName); 

      transaction.commit(); 
     } 

    } 

} 

答えて

0
/** 
* Replace an existing fragment that was added to a container. This is 
* essentially the same as calling {@link #remove(Fragment)} for all 
* currently added fragments that were added with the same containerViewId 
* and then {@link #add(int, Fragment, String)} with the same arguments 
* given here. 
**/ 
public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment, 
     String tag) 

削除し、以前のすべての断片、あなたの関数にpopBackStackImmediateメソッドを使用する必要はありませんreplaceFragmentInActivity()

findFragmentByTag(String tag)を使用して、指定されたフラグメントが存在するかどうかを調べ、トランザクションをスキップすることをお勧めします。

+0

ありがとうございました!コンテナ内のすべてのフラグメントを1つではなく置き換える方法がわかっていませんでしたが、今ではReplaceFragmentが廃止された理由を理解しています。提案したようにfindFragmentByTagを使用するように自分のコードを更新し、popBackStackImmediateを使用して既存のフラグメントを回復しました。それは今素晴らしいです!再度、感謝します。 – Pujolsluis

関連する問題