Android GridView横向滚动,分页加载数据

转载请注明出处,谢谢http://blog.csdn.net/harryweasley/article/details/51007348

始终觉得讲ui效果要先放上效果图,要不让其他人好不容易看完了,发现并不是他想要的效果,那岂不是坑了苦逼的程序员,程序员何苦为难程序员。效果图如下所示:
这里写图片描述

此应用,是viewPager结合fragment,fragment里又是一个gridView来实现的,实现向右滑动,分页加载数据的功能

文章末尾,有该应用的下载资源。

先说下该应用的功能吧,打开该应用,初始加载两个页面,第0页和第1页,当到达最后一页的时候,就会加载后一页的数据,如此一直加载下去。每个页面是一个gridView,Activity和fragment进行数据的传递。

项目的java目录如下所示:

这里写图片描述

你可能会想,这样一直加载页面出来,会不会造成oom,答案是不会。因为FragmentPagerAdapter只会保留当前页面,前一个页面和后一个页面的实例到内存,其他的都将删除。

关于Activity和fragment数据传递,因为我想要传递对象,所以我用到了bundle.putParcelableArrayList(“”,”“);这个方法,关于这个方法更多的介绍,可以查看http://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html

所以我的arrayList里传递的类实现了Parcelable接口,如下所示:

package com.example.viewpagerdemo;

import android.os.Parcel;
import android.os.Parcelable;

public class Model implements Parcelable {

    private String index;
    private String name;

    public Model(String index, String name) {
        this.index = index;
        this.name = name;
    }

    // 重写describeContents方法,内容接口描述,默认返回0就可以,基本不用
    @Override
    public int describeContents() {
        return 0;
    }

    // 重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从
    // Parcel容器获取数据
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(index);
        dest.writeString(name);
    }

    /**
     * 其中public static
     * final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。需重写本接口中的两个方法:createFromParcel
     * (Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,newArray(int size)
     * 创建一个类型为T,长度为size的数组,仅一句话即可(return new T[size]),供外部类反序列化本类数组使用。
     */
    public static final Parcelable.Creator<Model> CREATOR = new Parcelable.Creator<Model>() {

        @Override
        public Model createFromParcel(Parcel source) {
            return new Model(source.readString(), source.readString());
        }

        @Override
        public Model[] newArray(int size) {
            return new Model[size];
        }

    };

    public String getIndex() {
        return index;
    }

    public void setIndex(String index) {
        this.index = index;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

里面已经写了注释,这里就不用再解释更多了。

MainActivity的内容,如下所示:

package com.example.viewpagerdemo;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;

public class MainActivity extends FragmentActivity {

    private ViewPager vp;
    private List<Fragment> fragments;
    private SimplePageAdapter pageAdapter;
    /**
     * 传递的数据
     */
    private ArrayList<Model> modelList;

    /**
     * 一共有多少页
     */
    private int pageCount;
    private int totalCount = 18;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        vp = (ViewPager) findViewById(R.id.viewpager);
        fragments = new ArrayList<Fragment>();

        initDatas();
        int size = modelList.size();
        if (size % 9 == 0) {
            pageCount = size / 9;
        } else {
            pageCount = size / 9 + 1;
        }
        for (int i = 0; i < pageCount; i++) {
            //初始化每一个fragment
            GridFragment gf = GridFragment.newInstance(i, modelList);

            fragments.add(gf);
        }

        //初始化pageAdapter
        pageAdapter = new SimplePageAdapter(getSupportFragmentManager(),
                fragments);

        vp.setAdapter(pageAdapter);

        vp.addOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int arg0) {
                if (arg0 == pageCount - 1) {
                    // 在最后一页,开始加载后一页的数据
                    for (int i = totalCount; i < totalCount + 9; i++) {
                        Model model = new Model(i + "", i + "name");
                        modelList.add(model);
                    }
                    totalCount += 9;
                    pageAdapter.addFragment(pageCount++, modelList);
                    pageAdapter.notifyDataSetChanged();

                }

            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {

            }

            @Override
            public void onPageScrollStateChanged(int arg0) {

            }
        });

    }

    /**
     * 初始化数据,刚开始有18个
     */
    private void initDatas() {
        modelList = new ArrayList<Model>();
        for (int i = 0; i < totalCount; i++) {
            Model model = new Model(i + "", i + "name");
            modelList.add(model);
        }
    }

}

37行到41行,是确定刚开始,有几个页面。
44行是初始化GridFragment,在这里,将数据通过bundle进行了传递。
50行进行了初始化pageAdapter,同时在66行,有调用addFragment这个方法。接下来看下SimplePageAdapter里面都写了什么。

下面是SimplePageAdapter里面的内容:

package com.example.viewpagerdemo;

import java.util.ArrayList;
import java.util.List;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

public class SimplePageAdapter extends FragmentStatePagerAdapter {

    private List<Fragment> fragments;

    public SimplePageAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

    @Override
    public Fragment getItem(int arg0) {
        return fragments.get(arg0);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }

    public void addFragment(int i,ArrayList<Model> modelList){
        GridFragment  gf=GridFragment.newInstance(i,modelList);
        fragments.add(gf);
    }




}

第29行是增加新的fragment,即增加新的页面。

最后看下GridFragment里面的内容。

package com.example.viewpagerdemo;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.Toast;

public class GridFragment extends Fragment {

    private View view;
    private GridView gv;
    private int index = -1;
    private FragmentActivity context;
    private List<Model> modelList;
    private TextView no;

    public static GridFragment newInstance(int index, ArrayList<Model> modelList) {
        GridFragment gf = new GridFragment();
        Bundle bundle = new Bundle();
        bundle.putInt("index", index);
        bundle.putParcelableArrayList("model", modelList);
        gf.setArguments(bundle);
        return gf;
    }

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

        if (view == null) {
            //防止重复加载布局
            context = getActivity();

            Bundle bundle = getArguments();
            index = bundle.getInt("index");
            modelList = bundle.getParcelableArrayList("model");
            List<Model> newModels;
            int last = 9 * index + 9;
            if (last >= modelList.size()) {
                newModels = modelList.subList((9 * index), (modelList.size()));

            } else {
                newModels = modelList.subList((9 * index), (last));
            }

            Log.i("tag", "当前页数是" + index + "view是null哦");
            view = LayoutInflater.from(context).inflate(R.layout.fragment_grid,
                    container, false);
            gv = (GridView) view.findViewById(R.id.gridview);
            no = (TextView) view.findViewById(R.id.no);
            no.setText("这个是第" + (index + 1) + "页");

            // 这里重新开辟一个地址空间,来保存list,否则会报ConcurrentModificationException错误
            final ArrayList<Model> text = new ArrayList<Model>();
            text.addAll(newModels);
            gv.setAdapter(new GridBaseAdapter(getActivity(), text));

            gv.setOnItemClickListener(new OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                        int position, long id) {

                    Toast.makeText(context,
                            "点击的item是" + text.get(position).getIndex(),
                            Toast.LENGTH_SHORT).show();
                }
            });

        } else {
            Log.i("tag", "当前页数是" + index + "view不不不是null哦");
            ViewGroup root = (ViewGroup) view.getParent();
            if (root != null) {
                root.removeView(view);
            }
        }

        Log.i("tag", "当前页数是" + index);

        return view;
    }

}

关于第49行到第56行,这里进行一些解释:Activity和fragment之间的数据传递,我是将所有页面的list全部保存在内存中,所以这里会根据index来确定每个页面的数据内容。

第46行的那个注释,和他下面的内容,是我目前解决ConcurrentModificationException的方法。

我想你可能对第41行的判断,81行到87行的内容有疑惑,你可以看这篇文章,http://blog.csdn.net/harryweasley/article/details/50999802

之后就是GridBaseAdapter里的内容了,这个很简单,没有很多复杂的功能,我直接贴出来,就不解释了。

package com.example.viewpagerdemo;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class GridBaseAdapter extends BaseAdapter {

    private List<Model> modelList;
    private Context context;

    public GridBaseAdapter(Context context, List<Model> modelList) {
        this.modelList = modelList;
        this.context = context;
    }

    @Override
    public int getCount() {
        return modelList.size();
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(
                    R.layout.item_grid, parent, false);
            holder.tv = (TextView) convertView.findViewById(R.id.textview);
            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.tv.setText(modelList.get(position).getIndex());
        return convertView;
    }

    static class ViewHolder {
        TextView tv;
    }
}

其他的xml布局,我这里就不粘贴了,你可以直接下载源码查看。

参考文章:

如何更新及替换ViewPager中的Fragment,这篇文章将FragmentPagerAdapter和FragmentStatePagerAdapter的区别讲解的非常好,推荐大家去看:https://segmentfault.com/a/1190000003742057

fragment的陷阱,这篇文章说了,fragment为什么使用if (view == null) {}判断
http://blog.csdn.net/harryweasley/article/details/50999802

源码下载:
http://download.csdn.net/detail/harryweasley/9479123

展开阅读全文

没有更多推荐了,返回首页