Fragment 懒加载 与 getActivity()返回null的问题

最近实现了一个界面功能,其实很简单就是一个Tab,下面三个可滑动的view。使用TabLayout+ViewPager可以实现这样的效果。一开始ViewPager中我放入的是一个view,但是功能实现完了之后,感觉界面滑动不太顺畅,生命周期什么的都不好控制,后来直接索性就换了Fragment 加载布局。但是ViewPager有预加载机制,即是设置了预加载页数为0,这个方法是不失效的。因为在该方法中做了判断,至少会加载一页。那么在这个activity刚创建的时候就变成需要初始化大量资源。所以采用懒加载的方式来处理。

重点Fragment里的setUserVisibleHint这个方法

官方api 介绍

Set a hint to the system about whether this fragment's UI is currently visible to the user. This hint defaults to true and is persistent across fragment instance state save and restore.
An app may set this to false to indicate that the fragment's UI is scrolled out of visibility or is otherwise not directly visible to the user. This may be used by the system to prioritize operations such as fragment lifecycle updates or loader ordering behavior.
Parameters

大概意思是这样的:有道~~~

设置一个系统提示是否这个片段的UI是目前用户可见的。这提示默认为正确并持续在片段实例保存和恢复状态。
应用程序可以设置为false,以表明片段的UI是滚动的可见性或另有用户不能直接看到。这可能是使用的系统优化操作,比如片段的生命周期更新或加载程序命令的行为。
参数
isVisibleToUser真实如果这个片段的UI目前可见的用户(默认),如果它不是空的。

代码 Fragment V4包下的
public class abstract  BaseFragment extends Fragment {
    /*
    * 当前界面是否呈现给用户的状态标志
    */
    protected boolean isVisible;
    /**
     * 重写Fragment父类生命周期方法,在onCreate之前调用该方法,实现Fragment数据的缓加载.
     * @param isVisibleToUser 当前是否已将界面显示给用户的状态
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }
    /**
     * 当界面呈现给用户,即设置可见时执行,进行加载数据的方法
     * 在用户可见时加载数据,而不在用户不可见的时候加载数据,是为了防止控件对象出现空指针异常
     */
    protected void onVisible(){
        setlazyLoad();
    }
    /**
     * 当界面还没呈现给用户,即设置不可见时执行
     */
    protected void onInvisible(){
    }
    /**
     * 加载数据方法,必须由子类实现。
     */
    protected abstract  void setlazyLoad();
}
子类实现
public class OpenResultFragment extends BaseFragment {
    // 标志位,标志已经初始化完成。
    private boolean isPrepared;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(LOG_TAG, "onCreateView");
        View view = inflater.inflate(R.layout.fragment_open_result, container, false);
        
        .........XXX初始化view的各控件

        isPrepared = true;    // 对标识符进行赋值动作
        lazyLoad();
        return view;
    }
    @Override
    protected void lazyLoad() {
        if(!isPrepared || !isVisible) {
            return;
        }
        //填充各控件的数据,请求网络数据 
    }
}

子类中增加了一个标志位isPrepared,用于标志是否初始化完成。然后在我们所需要的初始化操作完成之后调用,如上面的例子当中,在初始化view之后,设置 isPrepared为true,同时调用lazyLoad()方法。而在lazyLoad()当中,判断isPrepared和isVisible只要有一个不为true就不往下执行。也就是仅当初始化完成,并且可见的时候才继续加载,这样的避免了未初始化完成就使用而带来的问题。

Fragment中调用getActivity为null的问题

今天在测试的时候,也发现了一个问题,Fragment基于Activity上,快速切换界面,或者什么情况下,会导致Activity销毁,这种情况下,在Fragment中getActivity获取上下文,这样后果就是应用程序直接崩掉了,并且报空指针。因为,Activity不存在了,获取一个不存在的东西,肯定是报error的。
度娘了一把~~~~

解决方式1

查阅一下Fragment的生命周期:

在onAttach() 与 onDetach()方法之间 getActivity方法是存在,反之为null,因此,如果我正在做某些操作联网,在等待过程中点击Back键返回,使得这个Fragment被销毁了,这时Fragment就会和Activity解除附着(onDetach),当再试图弹出Toast的时候,再次通过getActivity方法获取上下文,就报null了。

解决方式2

创建变量,保存实例。
在Fragment附着在Activity上时用一个变量保存引用,即:

@Override
public void onAttach(Activity activity){
    this.mContext = activity;
}
解决方式3

获取全局上下文,因为全局上下文的是和应用程序的生命周期一致的,不必担心为null
Android程序中Application、Service和Activity都实现了Context,但只有Application才能保证在程序运行期间一直存在并且具有唯一性,因此在程序中可以使用Application来获得Context而不用担心空指针。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,386评论 25 707
  • Android Studio JNI流程首先在java代码声明本地方法 用到native关键字 本地方法不用去实现...
    MigrationUK阅读 11,836评论 7 123
  • 片段 Fragment表示 Activity中的行为或用户界面部分。您可以将多个片段组合在一个 Activity ...
    岳小川阅读 787评论 0 3
  • 雅思作文学习20160507 一、介绍 Task 1 作文 20分钟 分值占三分之一 字数at least 150...
    小醇仔阅读 598评论 0 0
  • 从定制公交上下来,前面是一个袅娜的背影。深栗色的头发低低地扎成一束,发尾有些小卷,自然地洒在背上。背挺得笔直的,一...
    离晓晓阅读 573评论 4 2