android ViewPager+Fragment之懒加载详解手机开发

说说写这篇博客的背景吧,前两天去面试,问到一个问题说的是:比如我们首页,是有3个fragment构成的,并且要是实现作用可以滑,那么这个最好的选择就是ViewPager+fragment了,但是我们知道ViewPager+fragment是做预加载的,然而这种方法有一个坏处,当前页面和预加载页面都有大量的网络请求,可能就会比较慢,这样就会造成不好打体验。其实我们忽略的一个问题,Android的fragment里面已经帮我们提供了一个方法setUserVisibleHint。setUserVisibleHint()来显示与隐藏Fragment的。

我们看一下系统的代码:

 public void setUserVisibleHint(boolean isVisibleToUser) { 
        if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) { 
            mFragmentManager.performPendingDeferredStart(this); 
        } 
        mUserVisibleHint = isVisibleToUser; 
        mDeferStart = !isVisibleToUser; 
    }

但是
setUserVisibleHint优于onCreate调用,所以当onCreate调用完毕
setUserVisibleHint就不会触发,这时需要在首个显示的fragment调用setUserVisibleHint方法。

所以我们在第一个Fragment创建成功之后,需要设置下下一个页面是否展示

public void onActivityCreated(Bundle savedInstanceState) { 
        // TODO Auto-generated method stub 
        setUserVisibleHint(true); 
        super.onActivityCreated(savedInstanceState); 
    }

为了方便我们使用我们可以继承fragment重写一下setUserVisibleHint方法。

public abstract class BasePageFragment extends Fragment { 
 
    protected boolean isViewInitiated; 
    protected boolean isVisibleToUser; 
    protected boolean isDataInitiated; 
 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
    } 
 
    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
        super.onActivityCreated(savedInstanceState); 
        isViewInitiated = true; 
        prepareFetchData(); 
    } 
 
    @Override 
    public void setUserVisibleHint(boolean isVisibleToUser) { 
        super.setUserVisibleHint(isVisibleToUser); 
        this.isVisibleToUser = isVisibleToUser; 
        prepareFetchData(); 
    } 
 
    public abstract void fetchData(); 
 
    public boolean prepareFetchData() { 
        return prepareFetchData(false); 
    } 
 
    public boolean prepareFetchData(boolean forceUpdate) { 
        if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) { 
            fetchData(); 
            isDataInitiated = true; 
            return true; 
        } 
        return false; 
    } 
 
}

说下这里关于prepareFetchData的判断逻辑:当前UI可见,并且fragment已经初始化完毕,如果网络数据未加载,那么请求数据,或者需要强制刷新页面,那么再去请求页面数据,这样就达到了本文开始需要的要求。

用的话也听方便的:

public class PageFragment extends BasePageFragment { 
 
    public static PageFragment newInstance(String title){ 
        PageFragment fragment = new PageFragment(); 
        Bundle args = new Bundle(); 
        args.putString("key_fragment_title", title); 
        fragment.setArguments(args); 
        return fragment; 
    } 
 
    private String title; 
    private TextView tv; 
 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        title = getArguments().getString("key_fragment_title"); 
        Trace.d(title + ":onCreate"); 
    } 
 
    @Override 
    public void onResume() { 
        super.onResume(); 
        Trace.d(title + ":onResume"); 
    } 
 
 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
        Trace.d(title + ":onCreateView"); 
        tv = new TextView(getActivity()); 
        return tv; 
    } 
 
    @Override 
    public void fetchData() {<pre code_snippet_id="1723966" snippet_file_name="blog_20160621_4_911600" name="code" class="html">    //这里是网络异步请求返回
     tv.setText(title); }}

}

通过setOffscreenPageLimit进行Fragment缓存

public void setOffscreenPageLimit(int limit) { 
        
 if (limit < DEFAULT_OFFSCREEN_PAGES) { 
            Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " + 
                    DEFAULT_OFFSCREEN_PAGES); 
            limit = DEFAULT_OFFSCREEN_PAGES; 
        } 
        if (limit != mOffscreenPageLimit) { 
            mOffscreenPageLimit = limit; 
            populate(); 
        } 
    }

好了,最近面试面到的比较坑的问题还蛮多(比如Intent底层实现,Looper底层算法,Ams等),借此机会好好看下源码,欢迎留言。


原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/5888.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论