android懒加载简书,Android中ViewPager+Fragment懒加载解决方案

文/程序员男神

前言

最近医院上线,我们开发都奔赴医院现场支持,每天加班到很晚。自己也搞的精神不振,还好都把问题解决了。后面的几天轻松了不少。本文就是最近在开发新需求遇到的问题,记录下来以便后面供自己参考。

799e2b4d3b26?tdsourcetag=s_pcqq_aiomsg

aj

问题描述

在android开发中,经常会用到ViewPager+Fragment来实现切换Tab页。但是,由于ViewPager的内部机制,它总会默认至少预加载一个页面。

因为有时候用户希望选择了哪个Tab再去加载哪个Tab的数据,而不是预加载,如果当前页面和预加载页面都需要实时刷新当前Fragment,或者有大量的网络请求,可能就会比较慢。

解决方案1:

ViewPager因为内部机制,有预加载机制。那我们直接把ViewPager的预加载设置为0不就可以了?

vp.setOffscreenPageLimit(0);

查看源码:

/**

* Set the number of pages that should be retained to either side of the

* current page in the view hierarchy in an idle state. Pages beyond this

* limit will be recreated from the adapter when needed.

*

*

This is offered as an optimization. If you know in advance the number

* of pages you will need to support or have lazy-loading mechanisms in place

* on your pages, tweaking this setting can have benefits in perceived smoothness

* of paging animations and interaction. If you have a small number of pages (3-4)

* that you can keep active all at once, less time will be spent in layout for

* newly created view subtrees as the user pages back and forth.

*

*

You should keep this limit low, especially if your pages have complex layouts.

* This setting defaults to 1.

*

* @param limit How many pages will be kept offscreen in an idle state.

*/

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();

}

}

我们分析得知:即使设置为0,也会把limit设置为默认值1。

解决方案2:

package com.winning.rims.tabtest.tst;

import android.os.Bundle;

import android.support.annotation.Nullable;

import android.support.v4.app.Fragment;

import android.text.TextUtils;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.Toast;

/**

* Fragment预加载问题的解决方案:

* 1.可以懒加载的Fragment

* 2.切换到其他页面时停止加载数据(可选)

* Created by dj on 2018-09-10.

* blog :http://blog.csdn.net/linglongxin24/article/details/53205878

*/

public abstract class BaseFragment extends Fragment {

/**

* 视图是否已经初初始化

*/

protected boolean isInit = false;

protected boolean isLoad = false;

protected final String TAG = "BaseFragment";

private View view;

@Nullable

@Override

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

view = inflater.inflate(setContentView(), container, false);

isInit = true;

/**初始化的时候去加载数据**/

isCanLoadData();

return view;

}

/**

* 视图是否已经对用户可见,系统的方法

*/

@Override

public void setUserVisibleHint(boolean isVisibleToUser) {

super.setUserVisibleHint(isVisibleToUser);

isCanLoadData();

}

/**

* 是否可以加载数据

* 可以加载数据的条件:

* 1.视图已经初始化

* 2.视图对用户可见

*/

private void isCanLoadData() {

if (!isInit) {

return;

}

if (getUserVisibleHint()) {

lazyLoad();

isLoad = true;

} else {

if (isLoad) {

stopLoad();

}

}

}

/**

* 视图销毁的时候讲Fragment是否初始化的状态变为false

*/

@Override

public void onDestroyView() {

super.onDestroyView();

isInit = false;

isLoad = false;

}

protected void showToast(String message) {

if (!TextUtils.isEmpty(message)) {

Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();

}

}

/**

* 设置Fragment要显示的布局

*

* @return 布局的layoutId

*/

protected abstract int setContentView();

/**

* 获取设置的布局

*

* @return

*/

protected View getContentView() {

return view;

}

/**

* 找出对应的控件

*

* @param id

* @param

* @return

*/

protected T findViewById(int id) {

return (T) getContentView().findViewById(id);

}

/**

* 当视图初始化并且对用户可见的时候去真正的加载数据

*/

protected abstract void lazyLoad();

/**

* 当视图已经对用户不可见并且加载过数据,如果需要在切换到其他页面时停止加载数据,可以调用此方法

*/

protected void stopLoad() {

}

}

方案2的用法:

(1)、创建新的Fragment类,继承BaseFragment;

(2)、setContentView(),返回该xml布局文件;

(3)、lazyLoad(),在此方法内加载需要的数据;

(4)、stopLoad()方法可选,当视图已经对用户不可见并且加载过数据,如果需要在切换到其他页面时停止加载数据,可以覆写此方法。

package com.winning.rims.tabtest.tst;

import android.util.Log;

import com.winning.rims.tabtest.R;

/**

* 描述: Fragment1

* 作者|时间: djj on 2018/9/11 16:14

* 博客地址: http://www.jianshu.com/u/dfbde65a03fc

*

*/

public class Fragment1 extends BaseFragment {

@Override

public int setContentView() {

return R.layout.fm_layout1;

}

@Override

protected void lazyLoad() {

String message = "Fragment1" + (isInit ? "已经初始并已经显示给用户可以加载数据" : "没有初始化不能加载数据")+">>>>>>>>>>>>>>>>>>>";

showToast(message);

Log.d(TAG, message);

}

@Override

protected void stopLoad() {

Log.d(TAG, "Fragment1" + "已经对用户不可见,可以停止加载数据");

}

}

fm_layout1 xmL布局文件:

android:orientation="vertical" android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="match_parent"

android:gravity="center"

android:textSize="22sp"

android:textColor="@color/colorAccent"

android:text="第一个Fragment" />

其他Fragment一样,不在此多举例子。

activity 中的代码实例:

package com.winning.rims.tabtest.tst;

import android.os.Bundle;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentPagerAdapter;

import android.support.v4.view.ViewPager;

import android.support.v7.app.AppCompatActivity;

import android.widget.RadioGroup;

import com.winning.rims.tabtest.R;

import java.util.ArrayList;

import java.util.List;

public class MainActivity extends AppCompatActivity {

private RadioGroup rg;

private ViewPager vp;

private void assignViews() {

rg = (RadioGroup) findViewById(R.id.rg);

vp = (ViewPager) findViewById(R.id.vp);

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main1);

assignViews();

initData();

}

private void initData() {

final List fragments = new ArrayList<>();

fragments.add(new Fragment1());

fragments.add(new Fragment2());

fragments.add(new Fragment3());

fragments.add(new Fragment4());

vp.setOffscreenPageLimit(0);

vp.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {

@Override

public Fragment getItem(int position) {

return fragments.get(position);

}

@Override

public int getCount() {

return fragments.size();

}

});

rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

@Override

public void onCheckedChanged(RadioGroup radioGroup, int i) {

vp.setCurrentItem(radioGroup.indexOfChild(radioGroup.findViewById(i)));

}

});

}

}

activity_main1 xml布局文件:

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/activity_main"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

tools:context=".tst.MainActivity">

android:id="@+id/rg"

android:layout_width="match_parent"

android:layout_height="50dp"

android:orientation="horizontal">

android:id="@+id/button"

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_marginLeft="1dp"

android:layout_weight="1"

android:background="#FFFFFF"

android:button="@null"

android:gravity="center"

android:text="第一个"

android:textColor="#000000"

android:textSize="18sp" />

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_marginLeft="1dp"

android:layout_weight="1"

android:background="#FFFFFF"

android:button="@null"

android:gravity="center"

android:text="第二个"

android:textColor="#000000"

android:textSize="18sp" />

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_marginLeft="1dp"

android:layout_weight="1"

android:background="#FFFFFF"

android:button="@null"

android:gravity="center"

android:text="第三个"

android:textColor="#000000"

android:textSize="18sp" />

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_marginLeft="1dp"

android:layout_weight="1"

android:background="#FFFFFF"

android:button="@null"

android:gravity="center"

android:text="第四个"

android:textColor="#000000"

android:textSize="18sp" />

android:id="@+id/vp"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

日志

799e2b4d3b26?tdsourcetag=s_pcqq_aiomsg

日志打印

通过查看日志,我们发现,每次切换,都会先走stopLoad(),然后才去调用lazyLoad()方法。

总结:

虽然参考到别人代码,但是自己敲了一遍,还是很有收获的,解决问题,不需要焦头烂额的思考的感觉真好。加油,真好。哈哈哈...

参考代码:https://blog.csdn.net/linglongxin24/article/details/53205878

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值