被另一个片段覆盖的Android片段仍然是已显示而不是onPause

时间:2016-01-09 10:42:24

标签: android android-fragments android-lifecycle

在我的应用中,我在onBackPressed中抓取MainActivity并向片段发送广播。用

打开或关闭每个片段中的接收器
@Override
public void onPause() {
    super.onPause();
    getActivity().unregisterReceiver(receiver);

    Bundle args = getArguments();
    int tab = args.getInt("Tab");
    Log.d(log, String.format("Tab1Fragment %d onPause", tab));

}

@Override
public void onResume() {
    super.onResume();
    IntentFilter filter = new IntentFilter("de.foo.BackPressed");
    receiver = new MyReceiver();
    getContext().registerReceiver(receiver, filter);

    Bundle args = getArguments();
    int tab = args.getInt("Tab");
    Log.d(log, String.format("Tab1Fragment %d onResume", tab));

}

此外,在广播接收器中,我检查片段的可见性以确保,只有可见片段才能处理BackPressed事件:

if (intent.getAction().equals("de.foo.BackPressed")) {
    if (getView() != null && getView().isShown()) {
        ...
    }
}

当我用另一个片段替换现有的和可见的片段时,未在被替换的片段上调用onPause()。它的广播接收器仍然启用。也是新片段中的接收器。两个片段都为getView().isShown()提供了真实,但事实并非如此:只有最后一个片段可见。

如何实现只有可见片段的反应?

编辑:第一个片段加载到我的标签栏的标签0中。我得到日志“Tab1Fragment 0 onResume”并启用广播接收器。 在此片段中,用户点击列表条目以显示html页面。我使用以下代码执行此操作:

            HTML_Fragment newFragment = new HTML_Fragment();
            newFragment.setArguments(extras);
            FragmentManager fm = getFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();
            ft.replace(R.id.content, newFragment);
            ft.addToBackStack(null);
            ft.commit();

HTML_Fragment现在在同一个空间开始,我看到日志“HTMLFragment 0 onResume”。现在只能看到HTML_Fragment,但我没有得到日志“Tab1Fragment 0 onPause”。两个片段的广播接收器现在都是活动的。那是我的问题。

3 个答案:

答案 0 :(得分:0)

从上面的代码中,我可以猜测,问题的根本原因是什么,但我有一个想法:

  • 请确保 替换 旧片段,而不是 添加 新片段一个在旧的之上:

     // to show the root fragment
     getSupportFragmentManager().beginTransaction().
                    replace(R.id.container, new FragmentA()).
                    commit();
     ....
     // to show subfragment (i.e. fragment which is replacing the root fragment)
     getSupportFragmentManager().beginTransaction().
                    replace(R.id.container, new FragmentB()).addToBackStack(null).
                    commit();
    

    在此代码段中,onPause()的{​​{1}}将在FragmentA onResume()之前调用(当您点击后退时,FragmentB { {1}} - &{onPause() FragmentB}。

replace() - 与使用相同的containerViewId添加的所有当前添加的片段调用onResume()相同,然后使用相同的参数添加FragmentA。虽然add() - 只是将一个片段添加到活动状态。

如果您只是remove(Fragment)新片段(或者同时添加两个片段,然后只需按add(int, Fragment, String) / add()切换它们) - 一些生命周期方法就会从您身上溜走。

如果有帮助,请告诉我。

答案 1 :(得分:0)

没有。片段中的onResume和onPause表示活动的onResume和onPause。

您可以通过转到另一个活动然后返回来检查这一点。您将在调用Pause时找到,然后调用onResume。

您可以使用Fragment.isVisible()来检查片段是否在前面。

尝试在替换之前添加删除并继续检查接收器中的isVisible()。

        HTML_Fragment newFragment = new HTML_Fragment();
        newFragment.setArguments(extras);
        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

        // you can add a tag when add fragment ,and findByTag() to find the fragment.
        ft.remove(mTab1Fragment);

        ft.replace(R.id.content, newFragment);
        //ft.addToBackStack(null);
        ft.commit();

答案 2 :(得分:0)

问题没有解决。我通过一个参数系统确保只有当前可见的片段处理广播。