【问题标题】:Fragment A does not pause when Fragment B is called调用 Fragment B 时,Fragment A 不会暂停
【发布时间】:2014-12-22 08:33:58
【问题描述】:

我有两个片段,我们称第一个片段为Fragment A,第二个片段为Fragment BFragment A 包含一个带有 2 个子片段的 ViewPagerFragment B 是一个片段,它将以某种方式从用户那里获取一些数据点。 Fragment A 的子片段之一包含一个RecyclerView,它应该使用来自Fragment B 的数据点更新它的卡片视图。两个片段都被替换为 FrameLayout

问题是notifiyDatasetChanged 永远不会被调用为Fragment As RecyclerView,因为Fragment A is never called。当我从Fragment B 按下返回按钮时,它不会使用新数据更新RecyclerView

当我打开 Fragment B 时,如何让 Fragment A 暂停或调用 onStop?更新RecyclerView 的最佳方式是什么?

片段 A 的交易

// ViewPager fragment
    fm = getSupportFragmentManager();
    ft = fm.beginTransaction();
    ft.replace(R.id.show_fragment, ViewPagerFragment.newInstance());
    ft.commit();

片段 B 的交易

fm = getSupportFragmentManager();
            ft = fm.beginTransaction();
            ft.replace(R.id.show_fragment, SessionFragment.newInstance());
            ft.addToBackStack(null);
            ft.commit();

OnBackPressed

 /*
When a fragment is open allow you to go back to the activity when back button is pressed
 */
@Override
public void onBackPressed() {

    FragmentManager fragmentManager = getSupportFragmentManager();

    if (onBackPressed(fragmentManager)) {
        return;
    } else {
        super.onBackPressed();
        button.setVisibility(View.VISIBLE);
        button.setEnabled(true);
    }

    super.onBackPressed();
}


private boolean onBackPressed(FragmentManager fm) {
    if (fm != null) {
        if (fm.getBackStackEntryCount() > 0) {
            fm.popBackStack();
            button.setVisibility(View.VISIBLE);
            button.setEnabled(true);
            return true;
        }

        List<Fragment> fragList = fm.getFragments();
        if (fragList != null && fragList.size() > 0) {
            for (Fragment frag : fragList) {
                if (frag == null) {
                    continue;
                }
                if (frag.isVisible()) {
                    if (onBackPressed(frag.getChildFragmentManager())) {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

______________________ 日志信息 _____________________

12-22 05:38:00.268  18255-18255/? E/InputEventSender﹕ Exception dispatching finished 

signal.
12-22 05:38:00.268  18255-18255/? E/MessageQueue-JNI﹕ Exception in MessageQueue callback: handleReceiveCallback
12-22 05:38:00.278  18255-18255/? E/MessageQueue-JNI﹕ java.util.NoSuchElementException
            at java.util.Vector.lastElement(Vector.java:621)
            at com.project.ui.MainActivity.onBackPressed(MainActivity.java:267)
            at com.project.ui.MainActivity.onBackPressed(MainActivity.java:251)
            at android.app.Activity.onKeyUp(Activity.java:2453)
            at android.view.KeyEvent.dispatch(KeyEvent.java:2633)
            at android.app.Activity.dispatchKeyEvent(Activity.java:2704)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2221)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:3918)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3880)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3578)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3635)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3611)
            at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3772)
            at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2208)
            at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1849)
            at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1840)
            at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2185)
            at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
            at android.os.MessageQueue.nativePollOnce(Native Method)
            at android.os.MessageQueue.next(MessageQueue.java:143)
            at android.os.Looper.loop(Looper.java:122)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
12-22 05:38:00.278  18255-18255/? D/AndroidRuntime﹕ Shutting down VM
12-22 05:38:00.280  18255-18255/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: example.com.project, PID: 18255
    java.util.NoSuchElementException
            at java.util.Vector.lastElement(Vector.java:621)
            at com.project.ui.MainActivity.onBackPressed(MainActivity.java:267)
            at com.project.ui.MainActivity.onBackPressed(MainActivity.java:251)
            at android.app.Activity.onKeyUp(Activity.java:2453)
            at android.view.KeyEvent.dispatch(KeyEvent.java:2633)
            at android.app.Activity.dispatchKeyEvent(Activity.java:2704)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2221)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:3918)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3880)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3578)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3635)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3611)
            at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3772)
            at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2208)
            at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1849)
            at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1840)
            at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2185)
            at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
            at android.os.MessageQueue.nativePollOnce(Native Method)
            at android.os.MessageQueue.next(MessageQueue.java:143)
            at android.os.Looper.loop(Looper.java:122)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

【问题讨论】:

  • 替换之前需要手动调用fragment的onPause方法
  • 你能给我看一些示例代码吗?以及这方面的最佳做法?
  • 是的,你可以做的是,占用一个堆栈并push第一个片段A..当你需要用B替换A时,那么在这种情况下,替换push新的片段B到stack 并在此之前选择最后一个元素并调用 onPause
  • 我认为替换它会暂停它,调用 ft.replace(...) 我认为如果您使用相同的 FrameLayout 会暂停一个片段。您可以在下面的答案中为此写出一些伪代码吗?如果可行,我会接受你的回答
  • 嘿,你找到解决办法了吗。

标签: android android-activity android-fragments fragment


【解决方案1】:

声明一个栈对象

Stack<Fragment> fragmentStack = new Stack<Fragment>();

第一次替换片段 A 时:

fm = getSupportFragmentManager();
ft = fm.beginTransaction();
mViewPagerFragment = ViewPagerFragment.newInstance();
ft.replace(R.id.show_fragment, mViewPagerFragment);
fragmentStack.push(mViewPagerFragment);
ft.commit();

当您必须用 B 替换 A 时,请执行以下操作:

fm = getSupportFragmentManager();
ft = fm.beginTransaction();
fragmnetStack.lastElement().onPause();
mSessionFragment = SessionFragment.newInstance();
ft.replace(R.id.show_fragment, mSessionFragment );
fragmentStack.push(mSessionFragment );
ft.addToBackStack(null);
ft.commit();

在调用返回按钮时,执行此操作以返回片段 A

fragmentStack.lastElement().onPause();
fragmentStack.pop();
fm = getSupportFragmentManager();
ft = fm.beginTransaction();
mViewPagerFragment = fragmentStack.lastElement();
mViewPagerFragment.onResume();
ft.replace(R.id.show_fragment, mViewPagerFragment);
ft.commit();

编辑:

在添加片段 b 之前,删除片段 A,如下所示:

 fm = getSupportFragmentManager();
 ft = fm.beginTransaction();
 ft.remove(fragmentStack.pop());
 // then add the other code to add fragment B

当你试图从 B -> A 移动时,你也必须这样做

【讨论】:

  • 已检查但没有工作错误是 NoSuchElementException
  • 我猜你必须先删除前一个片段,等待检查编辑
  • 也许是我解释不够清楚的错误。我的viewpager的第二个子片段中有一个recyclerview,它位于片段A中。在同时包含片段A和B的活动中,片段A最初启动,然后有一个按钮来膨胀片段B和.replace,我的问题是片段B中获得的值没有正确存储在片段A的子recyclerview中。我检查了日志语句并且由于某些奇怪的原因没有调用 onResume ??
  • 尝试在添加片段 B 之前删除片段 A,然后在移回时再次添加它。我相信它也可以在您的旧代码中工作..
  • 不幸的是仍然无法正常工作,我的代码如下所示:pastebin.com/LP3pKfQH
猜你喜欢
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 2015-04-30
  • 1970-01-01
相关资源
最近更新 更多