基于Android官方AsyncListUtil优化经典ListView分页加载机制(二)

来源:互联网 发布:网络优化工程师待遇 编辑:程序博客网 时间:2024/06/09 21:05
基于Android官方AsyncListUtil优化经典ListView分页加载机制(二)


我写的附录文章1,介绍了如何使用Android官方的分页加载框架AsyncListUtil优化改进常见的RecyclerView分页加载实现。AsyncListUtil作为一种通用的分页加载框架,不仅可以套用在RecyclerView,也可也适用在经典(传统)ListView中,下面给出一个简单例子,说明如何通过AsyncListUtil调整ListView的分页加载机制。
一个简单的MainActivity适用AsyncListUtil和ListView,展示分页加载:
[java] view plain copy
print?
  1. package zhangphil.app;  
  2.   
  3. import android.app.ListActivity;  
  4. import android.content.Context;  
  5. import android.graphics.Color;  
  6. import android.os.Bundle;  
  7. import android.os.SystemClock;  
  8. import android.support.annotation.NonNull;  
  9. import android.support.annotation.Nullable;  
  10. import android.support.v7.util.AsyncListUtil;  
  11. import android.util.Log;  
  12. import android.view.LayoutInflater;  
  13. import android.view.View;  
  14. import android.view.ViewGroup;  
  15. import android.widget.AbsListView;  
  16. import android.widget.ArrayAdapter;  
  17. import android.widget.ListView;  
  18. import android.widget.TextView;  
  19.   
  20. public class MainActivity extends ListActivity {  
  21.     private final String TAG = “调试”;  
  22.     private final int NULL = -1;  
  23.     private AsyncListUtil<DataItem> mAsyncListUtil;  
  24.     private MyAdapter mAdapter;  
  25.     private int mFirstVisibleItem = NULL, mVisibleItemCount = NULL;  
  26.   
  27.     @Override  
  28.     protected void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.   
  31.         MyDataCallback mDataCallback = new MyDataCallback();  
  32.         MyViewCallback mViewCallback = new MyViewCallback();  
  33.         mAsyncListUtil = new AsyncListUtil(DataItem.class20, mDataCallback, mViewCallback);  
  34.   
  35.         mAdapter = new MyAdapter(this, NULL);  
  36.         setListAdapter(mAdapter);  
  37.   
  38.         getListView().setOnScrollListener(new AbsListView.OnScrollListener() {  
  39.             @Override  
  40.             public void onScrollStateChanged(AbsListView absListView, int scrollState) {  
  41.                 mAsyncListUtil.onRangeChanged();  
  42.             }  
  43.   
  44.             @Override  
  45.             public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
  46.                 mFirstVisibleItem = firstVisibleItem;  
  47.                 mVisibleItemCount = visibleItemCount;  
  48.             }  
  49.         });  
  50.     }  
  51.   
  52.     @Override  
  53.     protected void onListItemClick(ListView l, View v, int position, long id) {  
  54.         mAsyncListUtil.refresh();  
  55.     }  
  56.   
  57.     private class MyDataCallback extends AsyncListUtil.DataCallback<DataItem> {  
  58.   
  59.         @Override  
  60.         public int refreshData() {  
  61.             //更新数据的个数。  
  62.             //假设预先设定更新若干条。  
  63.             return Integer.MAX_VALUE;  
  64.         }  
  65.   
  66.         /** 
  67.          * 在这里完成数据加载的耗时任务。 
  68.          * 
  69.          * @param data 
  70.          * @param startPosition 
  71.          * @param itemCount 
  72.          */  
  73.         @Override  
  74.         public void fillData(DataItem[] data, int startPosition, int itemCount) {  
  75.             Log.d(TAG, ”fillData:” + startPosition + “,” + itemCount);  
  76.   
  77.             for (int i = 0; i < itemCount; i++) {  
  78.                 DataItem dataItem = new DataItem();  
  79.                 dataItem.pos = startPosition + i;  
  80.                 dataItem.content = String.valueOf(System.currentTimeMillis());  
  81.   
  82.                 data[i] = dataItem;  
  83.   
  84.                 //模拟耗时任务,故意休眠一定时延。  
  85.                 SystemClock.sleep(100);  
  86.             }  
  87.         }  
  88.     }  
  89.   
  90.     private class MyViewCallback extends AsyncListUtil.ViewCallback {  
  91.   
  92.         /** 
  93.          * @param outRange 
  94.          */  
  95.         @Override  
  96.         public void getItemRangeInto(int[] outRange) {  
  97.             outRange[0] = mFirstVisibleItem;  
  98.             outRange[1] = mFirstVisibleItem + mVisibleItemCount;  
  99.   
  100.             /** 
  101.              * 如果当前ListView为空,主动为用户加载数据. 
  102.              * 假设预先加载若干条数据 
  103.              * 
  104.              */  
  105.             if (outRange[0] == NULL && outRange[1] == NULL) {  
  106.                 Log.d(TAG, ”当前ListView为空!”);  
  107.                 outRange[0] = 0;  
  108.                 outRange[1] = 9;  
  109.             }  
  110.   
  111.             Log.d(TAG, ”getItemRangeInto,当前可见position: ” + outRange[0] + “ ~ ” + outRange[1]);  
  112.         }  
  113.   
  114.         @Override  
  115.         public void onDataRefresh() {  
  116.             mAdapter.notifyDataSetChanged();  
  117.             Log.d(TAG, ”onDataRefresh”);  
  118.         }  
  119.   
  120.         @Override  
  121.         public void onItemLoaded(int position) {  
  122.             mAdapter.notifyDataSetChanged();  
  123.             Log.d(TAG, ”onItemLoaded:” + position);  
  124.         }  
  125.     }  
  126.   
  127.     private class MyAdapter extends ArrayAdapter {  
  128.         private ViewHolder holder;  
  129.   
  130.         public MyAdapter(@NonNull Context context, int resource) {  
  131.             super(context, resource);  
  132.         }  
  133.   
  134.         @NonNull  
  135.         @Override  
  136.         public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {  
  137.             if (convertView == null) {  
  138.                 convertView = LayoutInflater.from(getApplicationContext()).inflate(android.R.layout.simple_list_item_2, null);  
  139.                 holder = new ViewHolder(convertView);  
  140.                 convertView.setTag(holder);  
  141.             } else {  
  142.                 holder = (ViewHolder) convertView.getTag();  
  143.             }  
  144.   
  145.             holder.setData(getItem(position));  
  146.   
  147.             return convertView;  
  148.         }  
  149.   
  150.         @Override  
  151.         public int getCount() {  
  152.             return mAsyncListUtil.getItemCount();  
  153.         }  
  154.   
  155.         @Nullable  
  156.         @Override  
  157.         public DataItem getItem(int position) {  
  158.             return mAsyncListUtil.getItem(position);  
  159.         }  
  160.     }  
  161.   
  162.     private class ViewHolder {  
  163.         public TextView text1;  
  164.         public TextView text2;  
  165.   
  166.         public ViewHolder(View view) {  
  167.             text1 = view.findViewById(android.R.id.text1);  
  168.             text1.setTextColor(Color.RED);  
  169.             text2 = view.findViewById(android.R.id.text2);  
  170.             text2.setTextColor(Color.BLUE);  
  171.         }  
  172.   
  173.         public void setData(DataItem dataItem) {  
  174.             if (dataItem == null) {  
  175.                 text1.setText(”pos加载中…”);  
  176.                 text2.setText(”content加载中…”);  
  177.             } else {  
  178.                 text1.setText(String.valueOf(dataItem.pos));  
  179.                 text2.setText(dataItem.content);  
  180.             }  
  181.         }  
  182.     }  
  183.   
  184.     private class DataItem {  
  185.         public int pos;  
  186.         public String content;  
  187.     }  
  188. }  
package zhangphil.app;import android.app.ListActivity;import android.content.Context;import android.graphics.Color;import android.os.Bundle;import android.os.SystemClock;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v7.util.AsyncListUtil;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.TextView;public class MainActivity extends ListActivity {    private final String TAG = "调试";    private final int NULL = -1;    private AsyncListUtil<DataItem> mAsyncListUtil;    private MyAdapter mAdapter;    private int mFirstVisibleItem = NULL, mVisibleItemCount = NULL;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        MyDataCallback mDataCallback = new MyDataCallback();        MyViewCallback mViewCallback = new MyViewCallback();        mAsyncListUtil = new AsyncListUtil(DataItem.class, 20, mDataCallback, mViewCallback);        mAdapter = new MyAdapter(this, NULL);        setListAdapter(mAdapter);        getListView().setOnScrollListener(new AbsListView.OnScrollListener() {            @Override            public void onScrollStateChanged(AbsListView absListView, int scrollState) {                mAsyncListUtil.onRangeChanged();            }            @Override            public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {                mFirstVisibleItem = firstVisibleItem;                mVisibleItemCount = visibleItemCount;            }        });    }    @Override    protected void onListItemClick(ListView l, View v, int position, long id) {        mAsyncListUtil.refresh();    }    private class MyDataCallback extends AsyncListUtil.DataCallback<DataItem> {        @Override        public int refreshData() {            //更新数据的个数。            //假设预先设定更新若干条。            return Integer.MAX_VALUE;        }        /**         * 在这里完成数据加载的耗时任务。         *         * @param data         * @param startPosition         * @param itemCount         */        @Override        public void fillData(DataItem[] data, int startPosition, int itemCount) {            Log.d(TAG, "fillData:" + startPosition + "," + itemCount);            for (int i = 0; i < itemCount; i++) {                DataItem dataItem = new DataItem();                dataItem.pos = startPosition + i;                dataItem.content = String.valueOf(System.currentTimeMillis());                data[i] = dataItem;                //模拟耗时任务,故意休眠一定时延。                SystemClock.sleep(100);            }        }    }    private class MyViewCallback extends AsyncListUtil.ViewCallback {        /**         * @param outRange         */        @Override        public void getItemRangeInto(int[] outRange) {            outRange[0] = mFirstVisibleItem;            outRange[1] = mFirstVisibleItem + mVisibleItemCount;            /**             * 如果当前ListView为空,主动为用户加载数据.             * 假设预先加载若干条数据             *             */            if (outRange[0] == NULL && outRange[1] == NULL) {                Log.d(TAG, "当前ListView为空!");                outRange[0] = 0;                outRange[1] = 9;            }            Log.d(TAG, "getItemRangeInto,当前可见position: " + outRange[0] + " ~ " + outRange[1]);        }        @Override        public void onDataRefresh() {            mAdapter.notifyDataSetChanged();            Log.d(TAG, "onDataRefresh");        }        @Override        public void onItemLoaded(int position) {            mAdapter.notifyDataSetChanged();            Log.d(TAG, "onItemLoaded:" + position);        }    }    private class MyAdapter extends ArrayAdapter {        private ViewHolder holder;        public MyAdapter(@NonNull Context context, int resource) {            super(context, resource);        }        @NonNull        @Override        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {            if (convertView == null) {                convertView = LayoutInflater.from(getApplicationContext()).inflate(android.R.layout.simple_list_item_2, null);                holder = new ViewHolder(convertView);                convertView.setTag(holder);            } else {                holder = (ViewHolder) convertView.getTag();            }            holder.setData(getItem(position));            return convertView;        }        @Override        public int getCount() {            return mAsyncListUtil.getItemCount();        }        @Nullable        @Override        public DataItem getItem(int position) {            return mAsyncListUtil.getItem(position);        }    }    private class ViewHolder {        public TextView text1;        public TextView text2;        public ViewHolder(View view) {            text1 = view.findViewById(android.R.id.text1);            text1.setTextColor(Color.RED);            text2 = view.findViewById(android.R.id.text2);            text2.setTextColor(Color.BLUE);        }        public void setData(DataItem dataItem) {            if (dataItem == null) {                text1.setText("pos加载中...");                text2.setText("content加载中...");            } else {                text1.setText(String.valueOf(dataItem.pos));                text2.setText(dataItem.content);            }        }    }    private class DataItem {        public int pos;        public String content;    }}



(一)和RecyclerView一样,我在ListView中同样适用ListView的滚动事件触发AsyncListUtil的onRangeChanged,从而触发分页加载机制开始运作。
(二)作为演示,本例在ListView的普通item点击事件触发一次AsyncListUtil的refresh事件,这种情况模拟当用户长期停留在一个页面需要为用户主动刷新数据的开发场景。
(三)一点儿特别注意:和附录文章1在RecyclerView中的AsyncListUtil.DataCallback不同,在RecyclerView中的DataCallback,加载数据fillData方法的第一个参数data数组,如果作为基本数据类型如String,int等等这类,直接data[i]是没有问题的,data[i]已经被AsyncListUtil创建和初始化完成,但是如果自定义数据类型,比如本例自定义了DataItem,意图装载一些开发者自定义的复杂类型,此时直接取出的data[i]为null!所以,为了解决这个问题,要从两方面入手:
(a)一方面,如果是自定义的数据结构,在fillData中,每一个data[i]为其重新创建new出来一个对象实例,然后赋值给data[i],本例是data[i]=new DataItem()。
(b)另一方面,在最后一关对View进行赋值时候,判断自定义类型是否为null,不会空指针时候才取出自定义数据结构中的数据元素(本例是DataItem中的成员变量)使用。


附录:
1,《基于Android官方AsyncListUtil优化改进RecyclerView分页加载机制(一)》链接:http://blog.csdn.net/zhangphil/article/details/78603499 
2,《基于Android官方Paging Library的RecyclerView分页加载框架》链接:http://blog.csdn.net/zhangphil/article/details/78627332 

转自:http://blog.csdn.net/zhangphil/article/details/78645089

阅读全文
0 0
原创粉丝点击