【问题标题】:Android fragment overlaid by another fragment still isShown and not onPause由另一个片段覆盖的 Android 片段仍然是显示而不是 onPause
【发布时间】:2016-01-09 10:42:23
【问题描述】:

在我的应用程序中,我在MainActivity 中捕获onBackPressed 并向片段发送广播。每个片段中的接收器通过

打开或关闭
@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”。两个片段的广播接收器现在都处于活动状态。那是我的问题。

【问题讨论】:

  • 请描述您尝试通过接收者处理的任务,也许我会帮助您解决问题。
  • 根据片段的种类有不同的任务。覆盖的必须更改列表内容。第二个必须以覆盖之前的状态重新激活第一个。
  • 尝试使用删除和添加。

标签: android android-fragments android-lifecycle


【解决方案1】:

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

  • 确保您用新片段替换旧片段,而不是在顶部添加新片段旧的:

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

    在此代码中-sn-p - FragmentAonPause() 将在 FragmentBonResume() 之前调用(当您单击返回时 - FragmentBonPause() -> onResume()FragmentA)。

replace() - 与调用 remove(Fragment) 的所有当前添加的片段相同,这些片段使用相同的 containerViewId 添加,然后使用相同的参数添加add(int, Fragment, String)。而add() - 只是向活动状态添加一个片段。

如果您只是 add() 新片段(或添加两者,然后通过 show()/hide() 切换它们) - 一些生命周期方法会从您身边溜走。

如果有帮助,请告诉我。

【讨论】:

  • 第一个片段(Tab1Fragment)放在我的标签栏的标签0中。它在应用程序启动时加载,向我显示日志“Tab1Fragment 0 onResume”。
  • 正如您在我编辑的问题中看到的那样,我按照您的建议进行操作。但是没有调用 Tab1Fragment onPause。
  • @thpitsch 即你有一个带有ViewPagerTabLayout 的根片段,ViewPager 的每个页面都是一个Fragment(根片段的子片段),一旦你点击 ListItem - 它会打开 不同 片段,它用最新的片段替换根片段,对吧?
  • 不,我不使用 ViewPager。在 ViewPager 中,即使禁用了滑动,相邻选项卡中总是有两个片段处于活动状态。我只使用 FragmentTabHost 并使用 Tab1Fragment 初始化每个选项卡。单击 ListItem 可以在 ListView 中加载另一个列表或将 Tab1Fragment 替换为另一个 Fragment - 在本例中为 HTML_Frgament。事实上,我在所有四个选项卡上都使用 Tab1Fragment 不是问题。我只用一个选项卡和一个 Tab1Fragment 测试它。还是一样:Tab1Fragment 被 HTML_Fragment 替换,但仍然存在。
【解决方案2】:

没有。 Fragment中的onResume和onPause是指Activity的onResume和onPause。

您可以通过转向另一个Activity并返回来检查这一点。您会发现调用了Pause,然后调用了onResume。

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

尝试在replace之前添加remove并继续检查receiver中的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();

【讨论】:

  • 我在我的广播接收器中改变了这个: if (getView() != null && Tab1Fragment.this.isVisible()) { ... } 但是当 Tab1Fragment 被 HTML_Fragment 替换时 isVisible 返回 true . Tab1Fragment 目前不可见。
  • 你能检查出哪个片段正在接收广播吗?
  • 两个片段。首先是 Tab1Fragment,其次是 HTML_Fragment。当我在 Tab1Fragment 手动禁用接收器时,应用程序会按需要运行。
  • 尝试删除 ft.addToBackStack(null);如果你不需要的话。
  • 第一个片段没有被推回栈。现在我已经删除了第二个片段的 addToBackStack。它对我的问题没有任何改变。第一个片段中的广播仍然被接收。为什么第一个片段还活着?它被替换为第二个,而不是添加。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多