基于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 

相关文章
|
24天前
|
缓存 监控 Java
构建高效Android应用:从优化用户体验到提升性能
在竞争激烈的移动应用市场中,为用户提供流畅和高效的体验是至关重要的。本文深入探讨了如何通过多种技术手段来优化Android应用的性能,包括UI响应性、内存管理和多线程处理。同时,我们还将讨论如何利用最新的Android框架和工具来诊断和解决性能瓶颈。通过实例分析和最佳实践,读者将能够理解并实施必要的优化策略,以确保他们的应用在保持响应迅速的同时,还能够有效地利用系统资源。
|
30天前
|
调度 数据库 Android开发
构建高效Android应用:Kotlin协程的实践与优化
在Android开发领域,Kotlin以其简洁的语法和平台友好性成为了开发的首选语言。其中,Kotlin协程作为处理异步任务的强大工具,它通过提供轻量级的线程管理机制,使得开发者能够在不阻塞主线程的情况下执行后台任务,从而提升应用性能和用户体验。本文将深入探讨Kotlin协程的核心概念,并通过实例演示如何在实际的Android应用中有效地使用协程进行网络请求、数据库操作以及UI的流畅更新。同时,我们还将讨论协程的调试技巧和常见问题的解决方法,以帮助开发者避免常见的陷阱,构建更加健壮和高效的Android应用。
36 4
|
1月前
|
数据库 Android开发 开发者
构建高效Android应用:采用Kotlin协程优化网络请求处理
【2月更文挑战第30天】 在移动应用开发领域,网络请求的处理是影响用户体验的关键环节。针对Android平台,利用Kotlin协程能够极大提升异步任务处理的效率和简洁性。本文将探讨如何通过Kotlin协程优化Android应用中的网络请求处理流程,包括协程的基本概念、网络请求的异步执行以及错误处理等方面,旨在帮助开发者构建更加流畅和响应迅速的Android应用。
|
22天前
|
Java Android开发 开发者
构建高效Android应用:Kotlin协程的实践与优化
在响应式编程范式日益盛行的今天,Kotlin协程作为一种轻量级的线程管理解决方案,为Android开发带来了性能和效率的双重提升。本文旨在探讨Kotlin协程的核心概念、实践方法及其在Android应用中的优化策略,帮助开发者构建更加流畅和高效的应用程序。通过深入分析协程的原理与应用场景,结合实际案例,本文将指导读者如何优雅地解决异步任务处理,避免阻塞UI线程,从而优化用户体验。
|
5天前
|
缓存 移动开发 Android开发
构建高效Android应用:从优化用户体验到提升性能表现
【4月更文挑战第18天】 在移动开发的世界中,打造一个既快速又流畅的Android应用并非易事。本文深入探讨了如何通过一系列创新的技术策略来提升应用性能和用户体验。我们将从用户界面(UI)设计的简约性原则出发,探索响应式布局和Material Design的实践,再深入剖析后台任务处理、内存管理和电池寿命优化的技巧。此外,文中还将讨论最新的Android Jetpack组件如何帮助开发者更高效地构建高质量的应用。此内容不仅适合经验丰富的开发者深化理解,也适合初学者构建起对Android高效开发的基础认识。
2 0
|
11天前
|
存储 数据库 Android开发
构建高效安卓应用:采用Jetpack架构组件优化用户体验
【4月更文挑战第12天】 在当今快速发展的数字时代,Android 应用程序的流畅性与响应速度对用户满意度至关重要。为提高应用性能并降低维护成本,开发者需寻求先进的技术解决方案。本文将探讨如何利用 Android Jetpack 中的架构组件 — 如 LiveData、ViewModel 和 Room — 来构建高质量的安卓应用。通过具体实施案例分析,我们将展示这些组件如何协同工作以实现数据持久化、界面与逻辑分离,以及确保数据的即时更新,从而优化用户体验并提升应用的可维护性和可测试性。
|
15天前
|
XML 开发工具 Android开发
构建高效的安卓应用:使用Jetpack Compose优化UI开发
【4月更文挑战第7天】 随着Android开发不断进化,开发者面临着提高应用性能与简化UI构建流程的双重挑战。本文将探讨如何使用Jetpack Compose这一现代UI工具包来优化安卓应用的开发流程,并提升用户界面的流畅性与一致性。通过介绍Jetpack Compose的核心概念、与传统方法的区别以及实际集成步骤,我们旨在提供一种高效且可靠的解决方案,以帮助开发者构建响应迅速且用户体验优良的安卓应用。
|
30天前
|
缓存 前端开发 Android开发
构建高效Android应用:从设计原则到性能优化
随着移动设备成为我们日常生活不可或缺的一部分,开发一个流畅且响应迅速的Android应用变得至关重要。本文将探讨如何通过遵循Android设计原则和实施细致的性能优化策略来构建高效的Android应用程序。我们将深入分析应用架构的选择、内存管理的要点以及UI设计的优化,旨在为开发人员提供一套实用的指导方针,帮助他们提升应用的整体性能和用户体验。
|
1月前
|
监控 Java Android开发
构建高效Android应用:从内存管理到性能优化
【2月更文挑战第30天】 在移动开发领域,打造一个流畅且响应迅速的Android应用是每个开发者追求的目标。本文将深入探讨如何通过有效的内存管理和细致的性能调优来提升应用效率。我们将从分析内存泄露的根本原因出发,讨论垃圾回收机制,并探索多种内存优化策略。接着,文中将介绍多线程编程的最佳实践和UI渲染的关键技巧。最后,我们将通过一系列实用的性能测试工具和方法,帮助开发者监控、定位并解决性能瓶颈。这些技术的综合运用,将指导读者构建出更快速、更稳定、用户体验更佳的Android应用。
|
1月前
|
JSON Android开发 数据格式
android 使用GSON 序列化对象出现字段被优化问题解决方案
android 使用GSON 序列化对象出现字段被优化问题解决方案