Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onLazyInitView 和onSupportVisible方法不回调 #586

Closed
nuli1228588792 opened this issue Sep 30, 2017 · 25 comments
Closed

onLazyInitView 和onSupportVisible方法不回调 #586

nuli1228588792 opened this issue Sep 30, 2017 · 25 comments

Comments

@nuli1228588792
Copy link

我用 loadMultipleRootFragment 方法在mainActivity加载四个fragment,homePageFragmnet、categoryFragment、discoverFragment、userinfoFragment,进入mainActivity后显示homePageFragmnet,然后直接跳转到其他的activity,再跳转回mainActivity(mainActivity 启动模式是 singleTask),直接显示userinfoFragment,这时userinfoFragment 的onLazyInitView 和onSupportVisible方法都不回调,楼主帮忙看一下呗。
我查了一下loadMultipleRootFragment 方法,是先add 所有的fragment,再hide 不是showPosition的fragment,感觉这么写有点不太合理,这样写导致mainActivity调用loadMultipleRootFragment 方法时,所有的fragment的onResume 方法都会回调,不管这个fragment是不是当前要显示的fragment,我感觉在showPosition时,应该先判断相应的fragment是否为空,为空时add,不为空再show。

@YoKeyword
Copy link
Owner

1、

userinfoFragmentonLazyInitViewonSupportVisible方法都不回调

何时 showHideFragment(userinfoFragment, homePageFragmnet)的?
因为执行事务时,要确保MainActivity是可见的,所以一般我们会在onResumeshowHideFragment(),这样我相信 onLazyInitViewonSupportVisible均会正常回调

2、

loadMultipleRootFragment的机制确实是一次性加载所有Fragment,你说的不合理应该是指内存和资源会有浪费

先判断相应的fragment是否为空,为空时add,不为空再show

你描述的是 “懒加载”模式的loadMultipleRootFragment()目前该 懒方法 在后续的TODO计划中

大部分情况下,该loadMultipleRootFragment配合onLazyInitView() 所产生的资源占用是完全可以接收的,当然"懒加载"模式的loadMultipleRootFragment在很多情况会是更好的选择

@nuli1228588792
Copy link
Author

不是用的 showHideFragment(userinfoFragment, homePageFragmnet) 方法回调的,直接用的Android的原生的show和hide fragment的方法;loadMultipleRootFragment的机制确实一次性加载所有Fragment,这样所有的fragment的onresume 方法都会一次执行完毕,我说的不合理就是这个所有的fragment的onresume方法一次性执行。

@YoKeyword
Copy link
Owner

YoKeyword commented Oct 12, 2017

你描述的场景无法复现问题,可否贴gist 或者demo工程

跳转回mainActivity(mainActivity 启动模式是 singleTask),直接显示userinfoFragment

或者贴下 调用show hide部分的代码, 描述下 调用时机

因为执行事务时,要确保MainActivity是可见的,所以一般我们会在onResume中showHideFragment(),这样我相信 onLazyInitView和onSupportVisible均会正常回调

@shercold
Copy link

shercold commented Nov 6, 2017

我也有一样的问题,loadMultipleRootFragment()之后就是所有fragment的onSupportVisible()都调用了一遍,onSupportVisible不是只有等fragment可见时才调用吗,加载的时候一次性把所有的fragment的onSupportVisible()都调用了,那这个onSupportVisible()有什么意义。

@beilo
Copy link
Contributor

beilo commented Nov 6, 2017

@shercold 可以提供下你的版本信息和gist 或者demo工程,我使用的时候没有这种情况

@shercold
Copy link

shercold commented Nov 6, 2017

版本号1.1.8 mFragments[FIRST] = DataDailyFragment.newInstance();
mFragments[SECOND] = DataTeamFragment.newInstance();
mFragments[THIRD] = DataPlayerFragment.newInstance();
loadMultipleRootFragment(R.id.fl_container, FIRST,mFragments);
刚刚描述错了,应该是我调用了loadMultipleRootFragment之后,mFragments[FIRST]的onLazyInitView 和onSupportVisible方法都调用了,但这个fragment还没点开,是不可见。

@beilo
Copy link
Contributor

beilo commented Nov 6, 2017

@shercold emmmmm..刚刚吓到我了.
是的,现在是有这种情况loadMultipleRootFragment的第一个fg会走onLazyInitView,原因如上
目前该 懒加载方法 在后续的TODO计划中

@shercold
Copy link

shercold commented Nov 6, 2017

补充一下,我调用loadMultipleRootFragment的这个fragment的的 父fragment也是loadMultipleRootFragment()中的一个子fragment,但这个父fragment的onLazyInitView没有调用,也就是说父fragment的onLazyInitView还没调用,子fragment的onLazyInitView已经调用了

@YoKeyword
Copy link
Owner

@shercold

...
loadMultipleRootFragment(R.id.fl_container, FIRST,mFragments);
刚刚描述错了,应该是我调用了loadMultipleRootFragment之后,mFragments[FIRST]的onLazyInitView 和onSupportVisible方法都调用了,但这个fragment还没点开,是不可见。

loadMultipleRootFragment(.., FIRST,..) 自然mFragments[FIRST]的onLazyInitViewonSupportVisible会被调用,因为load后FIRST fragment可见了

此外:

loadMultipleRootFragment()之后就是所有fragment的onSupportVisible(),onLazyInitView() 都调用了一遍

这个我这边无法复现,嵌套load场景我试了下也没问题

@shercold
Copy link

loadMultipleRootFragment()里面有三个子fragment1,fragment2,fragment3,
然后这里面的第三个fragment3又loadMultipleRootFragment()添加了三个子fragmentA,fragmentB,fragmentC,现在的问题是fragment3的onLazyInitView()还没被调用,fragmentC的onLazyInitView()已经被调用了,也就是说父容器的onLazyInitView()还没被调用还不可见,子fragment的onLazyInitView()已经被调用

@YoKeyword
Copy link
Owner

@shercold 是的,源码中是先分发了 子Fragment的onLazyInitView(),再执行自身的onLazyInitView(), 这个执行顺序带了什么不便吗?

 private void dispatchSupportVisible(boolean visible) {
       ...

        if (!mNeedDispatch) {
            mNeedDispatch = true;
        } else {
            if (checkAddState()) return;
            FragmentManager fragmentManager = mFragment.getChildFragmentManager();
            if (fragmentManager != null) {
                List<Fragment> childFragments = FragmentationHack.getActiveFragments(fragmentManager);
                if (childFragments != null) {
                    for (Fragment child : childFragments) {
                        if (child instanceof ISupportFragment && !child.isHidden() && child.getUserVisibleHint()) {
                            ((ISupportFragment) child).getSupportDelegate().getVisibleDelegate().dispatchSupportVisible(visible);
                        }
                    }
                }
            }
        }

       ...
       mSupportF.onLazyInitView(mSaveInstanceState);
    }

@SjAndy88
Copy link

SjAndy88 commented Nov 27, 2017

我也出现了同样的问题

@YoKeyword
Copy link
Owner

@flztsj 描述下场景, 上面同学的问题是回调,但是回调顺序有疑问

@shercold
Copy link

我描述的不是回调顺序的问题哦,你说的是 “源码中是先分发了 子Fragment的onLazyInitView(),再执行自身的onLazyInitView(), 这个执行顺序带了什么不便吗?” ;但我的问题自身还处于不可见状态还不需要调用onLazyInitView()呢,子Fragment的onLazyInitView()就已经调用了,不是顺序问题,而是此时就不应该调用子fragment的onLazyInitView()

@shercold
Copy link

现在造成的问题就是“子fragment的onLazyInitView()没有达到lazy懒加载的效果,而是一初始化就调用了,没有做到 第一次可见才调用 ”

@beilo
Copy link
Contributor

beilo commented Nov 27, 2017

@shercold 你方便做个demo传上来么,按照你的场景

@shercold
Copy link

shercold commented Dec 6, 2017

@LonelyMushroom 就是
在我的MainActivity里面
`SupportFragment[] mFragments = new SupportFragment[3];

        mFragments[0] = Fragment1.newInstance();
        mFragments[1] = Fragment2.newInstance();
        mFragments[2] = Fragment3.newInstance();
        loadMultipleRootFragment(R.id.fl_container, 0, mFragments);`

然后Fragment2里面又
`SupportFragment[] mFragments = new SupportFragment[3];

        mFragments[0] = FragmentA.newInstance();
        mFragments[1] = FragmentB.newInstance();
        mFragments[2] = FragmentC.newInstance();
        loadMultipleRootFragment(R.id.fl_container, 0, mFragments);`

现在的问题就是我一打开app Fragment2的onLazyInitView( )还没调用,
FragmentA的onLazyInitView( )已经被调用

@SjAndy88
Copy link

@YoKeyword 我这边解决了,出现这个的原因是生命周期的问题,加入了300ms延迟就OK了,深入的没有深究,后面有空再看看原因

beilo added a commit to beilo/GroceriesRoom that referenced this issue Dec 11, 2017
@beilo
Copy link
Contributor

beilo commented Dec 11, 2017

@shercold 我模拟了你的场景,下面贴下我的log日志

D/onLazyInitView: Fragment1: 
D/onLazyInitView: FragmentA: 
D/onLazyInitView: Fragment2: 
D/onLazyInitView: Fragment3: 

现在的问题就是我一打开app Fragment2的onLazyInitView( )还没调用,
FragmentA的onLazyInitView( )已经被调用

现在是了这个现象,请问是顺序有什么问题么?
我贴下我的demo地址,你可以看下
demo

@beilo
Copy link
Contributor

beilo commented Dec 11, 2017

@flztsj 你好,方便说明下你发生问题的场景,以及如何解决的么?
想知道下是哪个地方出问题了,方便排查。谢谢~

@ljf1172361058
Copy link

我也碰到这个致命问题了,A页面viewpage加载了多个fragment,在A页面来回切换,onSupportVisible和onLazyInitView调用正常,然后跳转到B界面,手动控制A界面的viewpage切换到哪个Fragment,关闭B界面,然后切换的Fragment不调用onSupportVisible和onLazyInitView

@YoKeyword
Copy link
Owner

@ljf1172361058
我模拟了该场景: A下ViewPager加载多个子Fragment,然后B控制A切换到其它Fragment,此时直接回调切换过去的Fragment的onLazyInitView()(提前调用了),导致后面关闭B时没有再回调

终于理解场景了... 稍后修复该问题 :)

@YoKeyword
Copy link
Owner

@ljf1172361058 @shercold @flztsj @nuli1228588792 发布了v1.2.5,解决了调用顺序异常的问题 🍺

@ljf1172361058
Copy link

感谢作者,辛苦了,不过更新到1.2.5好像还是一样o(╥﹏╥)o

@YoKeyword
Copy link
Owner

YoKeyword commented Jan 23, 2018

@ljf1172361058 根据描述的场景模拟了,应该是没问题的, 我推上了一个测试分支 test586,对应测试的提交是9bcdc70

可以看下 WechatSecondTabFragmentNewFeatureFragment

描述:前者是ViewPager,即你场景中的A, 后者是B,在B中点击按钮会给A发送事件,让A切换到第3个子Fragment

结果:在B关闭时,会回调第三个子Fragment的onLazyInitView()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants