记录一次解决Fragment问题之旅

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oqzuser1q2w3e4r5t/article/details/81448643

做为一只小小菜鸟,这些日子在学习新技术思想的同时,自己写了一篇仿今日头条APP,想法是简单的,实现却是有些困难,先说说程序中遇到的问题

代码逻辑如图:在MainActivity通过FragmentTabHost对以上4个Fragment进行初始化操作,BaseLazyFragment封装了不周
生命周期Fragment需要进行的操作及初始操作,BaseFragment中定义了一些公共接口,IndexContainerFragment处于可见
状态时会进行数据的加载及布局的填充,Fragment嵌套Fragment+ViewPager+tabLayout来实现,以IndexListFragment实现 
动态的加载。问题出现,IndexListFragment 无法得到BaseLazyFragment中的Context,研究许久,初步了解到了原因。
 

            这是DEBUG状态下得到程序状态截图:

这是我的程序,MVP形式+Retrofit+rxjava, 利用GreenDao存储了部分数据
onActivityCreated方法中做出判断

  

问题在这里,mContext为null

                                                             我得找找context是在哪没的

BaseFragment中值是有哒

                                                    继续找

                         

context已经被置为null

                     一看这架势,我头就开始疼了,不过马上开始给自己充电一下Fragment的执行流程

这个链接

https://blog.csdn.net/guoqifa29/article/details/50588659

让我了解到了Fragment的工作流程,我借用一下这位博主的图图,分析一下,这是动态加载Fragment的工作流程图:

先了解一下以上主类都是干啥用的吧:

Activity 我就不说了

FragmentManagerImpl:处理fragment操作时逻辑

Container for fragments associated with an activity. 与activity进行绑定时,填充的Fragments的容器
这样子好理解多了,fragment的生命周期不需要创建window所以它的生命周期不长,但是fragment的创建,更改,销毁,状态保存应该都是在这个类中做了处理

 BackStackRecord:对Fragment的堆栈进行操作处理,看下图

这下子可以清晰看出来了
FragmentTransition:view在被添加时需要启动事务,它是对BackStackRecord进行的操作

简单了解一下,它的工作流程:

刚才说道,view 的添加或者删除都必须先执行Transaction方法,

第一步:执行FragmentManager中beginTransaction(),然后将事务进行提交,fragment可以进行的所以操作必须commit完成后才可以 

manager调用了一个enqueueAction操作
这是我的出错点,mAddToBackStack 正常应该为true,我的程序它是为false
对事务的提交进行调度
执行mExecCommit

 

对已经提交成功的事务开始相关操作

到头了

           可算完事了,进入这个方法中,onCreate方法即会被调用。

问题原因似乎找到了,可以验证一下,已经提交了一个事务,
1、假设如果该事务未完成状态,这段时间内,再次提交一个事务应该会失败的。
View准备就绪后  才会进行逻辑的相关操作 ,很明显我在View的准备这里出了问题
突然间想到了问题有可以产生的地点是在哪里了。
问题解决啦,开心
解决fragment嵌套fragment +viewpager下,内部Fragmen丢失上下文 问题!

setUserVisibleHint这个方法比onCreated方法执行的还要早。预加载的Fragment就不会执行这个方法,记录一下生命周期,一开始TabHost中IndexContainerFragment执行了前三种方法,因为它是预加载,所以setUserVisibleHint没有被执行

2、当IndexListFragment进行切换,它对setUserVisibleHint进行了调用,如果此值返回true就意味着可以对用户可见

     onCreate1
     onCreateView1
     onViewCreated1
     setUserVisibleHint0
     isVisibleToUserfalse

具体被调用的时间

 处于setOffscreenPageLimit之后,setOffscreenPageLimit主要是用于处于对Fragment实行预加载的

 个数控制,不过setUserVisibleHint 被传了一个false,这意思是它不想给人看的意思呗

行,那我这样控制一下,好歹第一个界面你得让我看见啊

果然,完美了,看一下setUserVisibleHint 被重写后的样子

private boolean isFirstResume = true;
    private boolean isFirstVisible = true;
    private boolean isFirstInvisible = true;
    private boolean isPrepared;

//

 @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        Log.i("v", "------setUserVisibleHint:isVisibleToUser" + isVisibleToUser);
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            // view可见的时候可以加载数据啦
            if (isFirstVisible) {
                isFirstVisible = false;
                initPrepare();
            }
        } else {
            // view不可见的时候可以干点啥呢
            if (isFirstInvisible) {
                isFirstInvisible = false;
           
            }
        }
    }

 被这个小问题折磨了1、5天几乎,但是又学习了很多东西,继续fighting

猜你喜欢

转载自blog.csdn.net/oqzuser1q2w3e4r5t/article/details/81448643