2017-12-31 31 views
0

Ich habe eine Authentifizierungsaktivität erstellt, die ein FrameLayout als Container enthält, in dem ich die entsprechenden Fragmente ersetze, die der Benutzer verwenden möchte.Einzelaktivität mit 3 Fragmenten Absturz

Das erste Fragment in dem Behälter ist der WelcomeFragment, das nur ein ConstraintLayout mit einem Hintergrund, ein Image für das Logo und zwei Tasten zum LoginFragment oder SignUpFragment zu bewegen.

Das Problem ist, dass, wenn ich aus dem WelcomeFragment gehen zum LoginFragment, kommen zurück in die WelcomeFragment, gehen Sie auf die SignUpFragment, und versuchen Sie es erneut zu Comeback zum WelcomeFragment, die App abstürzt, und gibt mir die folgende Fehlermeldung:

Stack-Trace Fehler:

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:

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(); 
     } 

    } 

} 

Antwort

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) 

Wie Sie die ersetzen sehen kann (Methode) entfernt alle vorherigen Fragmente , es ist unnötig zu verwenden popBackStackImmediate Methode in Ihrer Funktion replaceFragmentInActivity()

Ich würde empfehlen, findFragmentByTag(String tag) zu verwenden, um zu finden, ob das gegebene Fragment vorhanden ist und die Transaktion überspringt.

+0

Vielen Dank! Ich wusste nicht, dass die Ersetzungsmethode alle Fragmente im Container anstelle von nur 1 ersetzt hat, jetzt verstehe ich, warum WelcomeFragment nicht mehr da war, als ich die Ersetzung durchführte. Mein Code wurde aktualisiert, um findFragmentByTag wie vorgeschlagen zu verwenden, und popBackStackImmediate wurde verwendet, um das vorhandene Fragment wiederherzustellen. es funktioniert jetzt großartig! Danke noch einmal. – Pujolsluis