onBackPressed 片段(A,B,C)

onBackPressed to fragment(A, B, C)

我有主要的 activity 和三个片段(一、二、三)。 所有这些片段都扩展了 BaseFragment:

public abstract class BaseFragment extends Fragment {
private Toolbar mToolbar;
private ActionBar mActionBar;

@Override
@CallSuper
public void onAttach(Activity context) {
    super.onAttach(context);

    mToolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
    mActionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
    //mActionBar.setTitle(setMyTitle());
    //Log.i("BaseFragment", "onAttach = "+getBackStackCount());
    resetToolbarNavigation(getBackStackCount()!=0);
}

//protected abstract String setMyTitle();

@Override
@CallSuper
public void onDetach() {
    super.onDetach();
    Log.i("BaseFragment", "onDetach = " + (getBackStackCount() - 1));
    resetToolbarNavigation((getBackStackCount() - 1 )!= 0);
}

private int getBackStackCount() {
    int b = getActivity().getSupportFragmentManager().getBackStackEntryCount();
    Log.i("BaseFragment", "getBackStackCount = "+b);

    return b;
}

private void resetToolbarNavigation(boolean backNavigationEnabled) {
    mActionBar.setDisplayHomeAsUpEnabled(backNavigationEnabled);
    Log.i("BaseFragment", "resetToolbarNavigation");
    if (backNavigationEnabled) {
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.i("resetToolbarNavigation", "setNavigationOnClickListener");
                getActivity().onBackPressed();
            }
        });
    }
    else {
        ((StartPageActivity) getActivity()).initToolbar();
        ((StartPageActivity) getActivity()).syncState();
    }
}

}

但是当我点击后退箭头时,我得到了 Exeption

09-22 19:28:13.233    5643-5643/com.test.mylist E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
        at com.test.exemple.BaseFragment.onClick(BaseFragment.java:56)
        at android.view.View.performClick(View.java:2485)
        at android.view.View$PerformClick.run(View.java:9080)
        at android.os.Handler.handleCallback(Handler.java:587)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:130)
        at android.app.ActivityThread.main(ActivityThread.java:3683)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:507)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
        at dalvik.system.NativeStart.main(Native Method)

onBackPressed inside main activity

    @Override
public void onBackPressed() {
        getSupportFragmentManager().popBackStack();
        Log.d("StartPageActivity", "onBackPressed " + getSupportFragmentManager().getBackStackEntryCount());

}

你能帮帮我吗?错误在哪里?我做错了什么?

这是我根据您的评论认为正在发生的事情。

  1. 您打开片段 1 并且 resetToolbarNavigation(boolean)onAttach
  2. 调用
  3. 您导航到片段 2,resetToolbarNavigation(boolean)onAttach
  4. 调用
  5. 您导航到片段 3 并且 resetToolbarNavigation(boolean)onAttach
  6. 调用
  7. 你点击导航按钮,fragment 3 会正确处理它,弹出 backstack 并将你导航回 fragment 2
    • resetToolbarNavigation(boolean) not 在片段 2 上从 onAttach 调用,因为 fragment/activity 没有被破坏并且片段从未分离。
  8. 您按下导航按钮,它再次由未启动的片段 3 处理,所以 getActivity() returns null

您应该尝试在片段显示时设置导航侦听器。如果您正在正确执行您的片段事务,您应该能够在 onResume().

中执行此操作

不确定你为什么会得到那个确切的异常,但你使用片段的方法在它的设计方式上并不是很好,这可能会带来这类问题。所以在这里我给你留下一些在使用片段实现应用程序时对我有用的建议:

  • 不同的职责:Activity 应该处理它的东西,而 Fragment 应该只负责 Fragment 的功能。要实现这一点,您可以使用 Activity 实现所需的方法使您的 Fragment 发布接口,然后仅在 Fragment 中使用它。例如,在您的代码中,您的片段与 Activity 有很强的关系。方法 resetToolbarNavigation 正在与属于 Activity 的视图进行交互,请注意该方法并没有做任何事情,这是 Fragment 的责任,因此整个方法应该在 activity 中实现,然后您可以在中发布一个界面例如你的 BaseFragment:

    //Get the instance of the activity implementation 
    private BaseFragmentActions baseFragmentActions;
    //Publish your interface with the methods your Activity will implement 
    public interface BaseFragmentActions {
        public void resetToolbarNavigation(boolean backNavigationEnabled);
    }
    
    //In your onAttach get the implementation from your activity
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            baseFragmentActions = (BaseFragmentActions)activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement interface BaseFragmentActions");
        }
    }
    

然后在您的 Activity 中实现该方法并在您的片段中使用它,例如 baseFragmentActions.resetToolbarNavigation(true);请注意,这种方式BaseFragment 不关心activity,只要求包含它的activity 必须实现它需要的方法。为此,您也可以使用 EventBus。

  • 片段之间的事务应该总是在包含它的 Activity 中完成。一个Fragment不应该know/cares关于应该在哪个Fragment之后加载。

  • 使用概念"Activity knows it's Fragments but Fragment don't know it's Activity"

你可以这样做,你可以在你的 Fragment 中获得你的 Activity 的信息,但这可能会像这个一样让人头疼。

希望它能帮助你作为未来设计的概念,对不起我的英语