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数量少的加载数据的时候使用。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值