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

简介: 基于Android官方AsyncListUtil优化经典ListView分页加载机制(二)我写的附录文章1,介绍了如何使用Android官方的分页加载框架AsyncListUtil优化改进常见的RecyclerView分页加载实现。
基于Android官方AsyncListUtil优化经典ListView分页加载机制(二)


我写的附录文章1,介绍了如何使用Android官方的分页加载框架AsyncListUtil优化改进常见的RecyclerView分页加载实现。AsyncListUtil作为一种通用的分页加载框架,不仅可以套用在RecyclerView,也可也适用在经典(传统)ListView中,下面给出一个简单例子,说明如何通过AsyncListUtil调整ListView的分页加载机制。
一个简单的MainActivity适用AsyncListUtil和ListView,展示分页加载:
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 

相关文章
|
13天前
|
Java 数据库 Android开发
【专栏】Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
|
17天前
|
缓存 监控 Android开发
构建高效Android应用:从优化用户体验到提升性能表现
【4月更文挑战第23天】 在竞争激烈的移动市场中,一个高效的Android应用是吸引并保留用户的关键。本文将探讨如何通过一系列技术手段和最佳实践来优化Android应用的用户体验和性能表现。我们将深入分析响应式UI设计、内存管理、多线程处理以及最新的Android框架特性,揭示它们如何共同作用以减少应用延迟,提高响应速度,并最终提升整体用户满意度。
|
1天前
|
XML Java Android开发
如何美化android程序:自定义ListView背景
如何美化android程序:自定义ListView背景
|
10天前
|
缓存 监控 API
Android应用性能优化实践
【4月更文挑战第30天】 随着智能手机的普及,用户对移动应用的性能要求越来越高。对于Android开发者而言,提升应用的性能是吸引和保留用户的关键因素之一。本文将深入探讨影响Android应用性能的主要因素,并提供一系列的优化策略,旨在帮助开发者构建更加流畅和高效的应用体验。
|
10天前
|
移动开发 调度 Android开发
构建高效Android应用:Kotlin协程的实践与优化
【4月更文挑战第30天】在移动开发领域,性能和响应性是衡量应用质量的关键指标。对于Android平台而言,Kotlin协程作为一种新兴的异步编程解决方案,提供了更为简洁和高效的处理并发任务的能力。本文将深入探讨Kotlin协程的核心原理,以及如何通过它们来提升Android应用的性能。我们将从基础概念出发,逐步介绍协程的创建、管理以及与Android UI线程的交互,并最终展示如何优化现有代码以利用协程的优势。
|
11天前
|
移动开发 数据库 Android开发
构建高效Android应用:探究Kotlin协程的优化实践
【4月更文挑战第29天】在移动开发领域,尤其是Android平台上,性能优化一直是开发者关注的重点。近年来,Kotlin语言凭借其简洁性和功能性成为Android开发的热门选择。其中,Kotlin协程作为一种轻量级的并发处理机制,为编写异步代码、网络请求和数据库操作提供了极大的便利。本文将深入探讨Kotlin协程在Android应用中的性能优化技巧,帮助开发者构建更加高效的应用程序。
|
12天前
|
移动开发 API Android开发
Android应用性能优化实战
【4月更文挑战第28天】在移动开发领域,一个流畅的用户体验是至关重要的。对于Android开发者而言,应用的性能优化是一项既挑战性也极其重要的工作。本文将深入探讨Android应用性能优化的多个方面,包括内存管理、UI渲染、多线程处理以及电池效率等,旨在为开发者提供实用的性能提升策略和具体的实施步骤。通过分析常见的性能瓶颈,并结合最新的Android系统特性和工具,我们的目标是帮助读者打造更加高效、响应迅速的Android应用。
|
13天前
|
缓存 监控 Android开发
Android 应用性能优化实战
【4月更文挑战第27天】 在竞争激烈的移动应用市场中,性能优越的应用更能吸引和保留用户。针对Android平台,本文将深入探讨影响应用性能的关键因素,并提供一系列实用的优化策略。我们将从内存管理、UI渲染、多线程处理以及电池使用效率等方面入手,通过具体案例分析如何诊断常见问题,并给出相应的解决方案。文中所提技巧旨在帮助开发者构建更加流畅、高效的Android应用。
24 2
|
16天前
|
移动开发 Java Android开发
构建高效Android应用:采用Kotlin协程优化网络请求
【4月更文挑战第24天】 在移动开发领域,尤其是对于Android平台而言,网络请求是一个不可或缺的功能。然而,随着用户对应用响应速度和稳定性要求的不断提高,传统的异步处理方式如回调地狱和RxJava已逐渐显示出局限性。本文将探讨如何利用Kotlin协程来简化异步代码,提升网络请求的效率和可读性。我们将深入分析协程的原理,并通过一个实际案例展示如何在Android应用中集成和优化网络请求。
|
18天前
|
Java 数据库 Android开发
构建高效Android应用:探究Kotlin协程的优化实践
【4月更文挑战第22天】 随着移动开发技术的不断进步,Android平台上的性能优化已成为开发者们关注的焦点。在众多优化手段中,Kotlin协程以其轻量级线程管理和异步编程的优势,为提高应用性能和响应性提供了新的思路。本文将深入探讨Kotlin协程在Android开发中的具体应用,通过实例演示如何利用协程进行网络请求、数据库操作和UI线程的非阻塞更新,以期达到提升应用性能的目的。
16 2