1、Fragment简介

Fragment是Android开发中一个寄生于Activity的类,它的主要作用是显示界面给用户,可以看做是一个特殊的Activity。为了让界面可以在平板上更好地展示,Android在3.0版本引入了Fragment(碎片)功能,它非常类似于Activity,可以像Activity一样包含布局。

我们说Fragment是寄生于Activity的,所以我们在使用Fragment的时候,通常是嵌套在Activity中使用的。


2、问题描述

类似新浪微博的底部选项栏目,很多app也采用了类似的结构布局。但是我们在使用该种布局的时候,尤其是在网络加载的情况下,会发现一个问题:每次FragmentTabHost切换fragment时会调用onCreateView()重绘UI。

对于很多应用来说,数据都是要从服务器上获取的,如果重绘UI,就表示数据要再次获取和填充,那么有没有什么比较好的解决方案呢?


3、解决方案

解决方案就是缓存UI。

与Adapter中的UI缓存类似,我们也可以在Fragment中缓存UI,达到界面不被系统回收的效果。可能有人会有疑问,手机不能支持这么大的缓存怎么办?额,其实该种方案就是以空间换时间的办法。对于现在的手机系统来说,基本没有小于1G的内存量的,一般来说,你缓存几个页面不是什么大问题。

图片的缓存可能会出现OOM(内存溢出)错误,UI界面一样也可能,但是UI的缓存的消耗是远远小于图片缓存的。现在的手机,一般都能很好的支持这些的。


4、示例代码

下面给出一个在实际应用场合中的示例代码,需要注意一个问题是:缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,要不然会发生这个rootview已经有parent的错误。

代码如下:

private View rootView;// 缓存Fragment view  
  
@Override  
public View onCreateView(LayoutInflater inflater, ViewGroup container,  
        Bundle savedInstanceState)  {   
  
    if (rootView == null)  {  
        rootView = inflater.inflate(R.layout.fragment_1, null);  
    }  
    // 缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,要不然会发生这个rootview已经有parent的错误。  
    ViewGroup parent = (ViewGroup) rootView.getParent();  
    if (parent != null){  
        parent.removeView(rootView);  
    }  
    return rootView;  
}


5、注意问题

如果在手机测试的时候,还是会发生OOM的问题,或者在后台监控的时候,发现市面上的手机依然出现问题,那么可能是我们自己写的缓存代码问题,这里提供一个系统自带的API,大家可以试试看:

mViewPager.setOffscreenPageLimit(2); 
中间的2是参数,不过这个参数不能太大,否则可能导致oom 。一般来说,我们只需要缓存中间页面的左右两边的页面即可,缓存太多就会太占系统资源了,也会影响APP的流畅度。