viewpager中多fragment及时加载
Viewpager是我们经常使用的一个控件,它的使用这里就不多说了,我在这里说一下其中的一个效果,就是我们经常会看到在一些新闻类的 App中,使用viewpager来做各个频道的切换,在切换的时候,我们会发现,这些频道里面的数据,是在此频道为当前页的时候才进行加载,而不是一开始就加载的(这里说明一点,就是viewpager有预加载的功能),同时,当我们切换回来的时候,此页面并没有重新加载,数据还是原来的,就是说当切换回来的时候,数据没有进行再次请求。
对于这个效果,我用了一个比较笨,也是我现在唯一能想到的方法,来处理,在这里,做一个记录,如果你有好的方法,希望留言,大家共同进步。
好了,下面我说一下我的方法:
我们在使用viewpager的时候,最后都要使用一个setAdapter来绑定它的adpter。对于viewpager来说,它的最基本的adapter是pageAdapter。但是还有两个分别是FragmentPagerAdapter与FragmentStatePagerAdapter这两个从名字上就能看出来,主要是用来处理viewpager中如果是多个fragment的情况。它俩的区别在于是否将生成的fragment全放到内存中去。FragmentPagerAdapter是将fragment放到内存中去,而FragmentStatePagerAdapter则只保留当前的fragment。这里我们采用的是继承FragmentStatePagerAdapter来处理,它只需要完成两上方法就OK了,代码如下:
- package com.example.cg.viewpagestatepageradapter;
- import android.support.v4.app.Fragment;
- import android.support.v4.app.FragmentManager;
- import android.support.v4.app.FragmentStatePagerAdapter;
- import java.util.List;
- /**
- * Created by cg on 2016/2/23.
- */
- public class viewAdapter extends FragmentStatePagerAdapter {
- private List<Fragment> list_fragment;
- public viewAdapter(FragmentManager fm, List<Fragment> list_fragment) {
- super(fm);
- this.list_fragment = list_fragment;
- }
- @Override
- public Fragment getItem(int position) {
- return list_fragment.get(position);
- }
- @Override
- public int getCount() {
- return list_fragment.size();
- }
- /**
- * 以触发销毁对象以及重建对象
- * @param object
- * @return
- */
- @Override
- public int getItemPosition(Object object) {
- return POSITION_NONE;
- }
- }
从上面的代码来看,没什么特别之处,就是正常的一个adapter。确实如此,下面我们来看一下,fragment的代码,在这里你会发现有所不同。
- package com.example.cg.viewpagestatepageradapter;
- import android.os.Bundle;
- import android.support.annotation.Nullable;
- import android.support.v4.app.Fragment;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ListView;
- import android.widget.Toast;
- import com.example.cg.viewpagestatepageradapter.models.houseInfos;
- import com.google.gson.Gson;
- import com.google.gson.reflect.TypeToken;
- import com.zhy.http.okhttp.OkHttpUtils;
- import com.zhy.http.okhttp.callback.StringCallback;
- import java.util.ArrayList;
- import java.util.List;
- import okhttp3.Call;
- /**
- * Created by cg on 2016/2/23.
- */
- public class oneFragment extends Fragment {
- private String Tag = "oneFragment";
- private ListView lv_one;
- private List<houseInfos> list_h;
- private myAdatper mAdapter;
- private myDialog dialog;
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- Log.e(Tag,"onCreateView");
- View view = inflater.inflate(R.layout.fragment_one,container,false);
- return view;
- }
- @Override
- public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- Log.e(Tag, "onViewCreated");
- lv_one = (ListView)view.findViewById(R.id.list_one);
- if(list_h!=null)
- {
- initData();
- }
- }
- @Override
- public void setUserVisibleHint(boolean isVisibleToUser) {
- super.setUserVisibleHint(isVisibleToUser);
- Log.e(Tag,"setUserVisibleHint:" + isVisibleToUser);
- if(list_h!=null)
- {
- Log.e(Tag,"list_h=" + list_h.size());
- }
- if(isVisibleToUser && list_h == null)
- {
- initData();
- }
- }
- public void initData()
- {
- dialog = new myDialog();
- dialog.show(getActivity().getFragmentManager(), "加载2");
- list_h = new ArrayList<houseInfos>();
- String url = "http://bank.gxdgroup.com.cn/app/CommunityInfo.ashx";
- OkHttpUtils.get()
- .url(url)
- .addParams("flag","1")
- .addParams("cityId","708")
- .build()
- .execute(new StringCallback() {
- @Override
- public void onError(Call call, Exception e) {
- dialog.dismiss();
- Toast.makeText(getActivity(), "有错误", Toast.LENGTH_SHORT).show();
- }
- @Override
- public void onResponse(String s) {
- list_h = new Gson().fromJson(s, new TypeToken<List<houseInfos>>() {
- }.getType());
- mAdapter = new myAdatper(getActivity(),R.layout.fragment_item,list_h);
- lv_one.setAdapter(mAdapter);
- }
- });
- }
- }
这里大家注意到了,我们加载数据的地方是在setUserVisibleHint方法中,这个方法,是在createView方法之前就运行的。它里面的isVisibleToUser就是用来判断当前的fragment是否被用户可见,就是是否是当前的fragment.在这里,我们判断一下,如果它是可见的,我们才进行数据加载,如果不可见,则不进行加载。这样就解决了只有当前fragment加载数据的问题。
好,我们再看一下主页
- package com.example.cg.viewpagestatepageradapter;
- import android.os.Bundle;
- import android.support.v4.app.Fragment;
- import android.support.v7.app.AppCompatActivity;
- import android.widget.Toast;
- import java.util.ArrayList;
- import java.util.List;
- public class MainActivity extends AppCompatActivity {
- private android.support.v4.view.ViewPager pager;
- private List<Fragment> list_fragment;
- private viewAdapter vAdapter;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initControls();
- }
- /**
- * 初始化数据
- */
- private void initControls() {
- pager = (android.support.v4.view.ViewPager)findViewById(R.id.pager);
- //pager.setOffscreenPageLimit(2);
- list_fragment = new ArrayList<>();
- oneFragment oFragment = new oneFragment();
- twoFragment tFragment = new twoFragment();
- threeFragment eFragment = new threeFragment();
- list_fragment.add(oFragment);
- list_fragment.add(tFragment);
- list_fragment.add(eFragment);
- vAdapter = new viewAdapter(getSupportFragmentManager(),list_fragment);
- if(vAdapter==null)
- {
- Toast.makeText(this,"为什么是空呢!",Toast.LENGTH_SHORT).show();
- }else {
- pager.setAdapter(vAdapter);
- }
- }
- }
- 这页没什么特别的,就是加载一下 viewpager,这里面的三个fragment代码基本上一样,就是取的数据不一样。我们来运行一下,你会发现,确实达到了我们要的效果,只有每页可见的时候才会加载,而且在第三页翻回第二页的时候,第二页的数据没有重新加载,而是保持了原有的状态,这样一看,好像很完美的解决了,我们的需求,可是.........当你从第二页翻向第一页的时候,你会发现第一页,是空白的,数据没有了.这是为什么呢,因为第一页被消除了,因为我们知道,viewpager默认的情况是预加载当前页的前,后各一个页面。所以当你到第三个页的时候,第一个页已经被消除了。
- 这样就不是我们要的结果了,这怎么办,等一下,viewpager是默认加载当前页的前后各一个,如果我让他默认加前后各两个呢。我们来试试,
- pager.setOffscreenPageLimit(2)
- 这句代码,就是设置viewpager会预加载当前页面前后各几个页面的,因为我们一共就三个fragment,所以我就设置它为2,运行一下看一下效果,我们会发现,正好满足了我们的需求,每个页面只有在可见的时候才会加载数据,而且只在第一次加载数据,之后就不再加载数据了。
- 这里你可能会说,这样不是还是在预加载了吗,是的,我们它让进行了预加载了,可是有一个问题是,我们加载的只是页面布局,而没有数据,这种情况下,对资源的占用就很小了。
- 问题:
- 如果fragment很多的话,会产生什么后果,没有试过,但是想一想也会有问题。
- 总是感觉这个方法有点笨,而且适用于fragment数量少的加载数据的时候使用。

浙公网安备 33010602011771号