android--使用RecyclerView及相关架构组件实现列表数据展示

参考资料

安卓开发官方文档:

IDE

AndroidStudio

相关组件概述

LiveData

LiveData是一种可观察的数据存储器类。具有生命周期感知能力,它遵循其他应用组件(如Activity、Fragment或Service)的生命周期。这种感知能力可确保LiveData仅更新处于活跃生命周期状态(STARTED/RESUMED)的应用组件观察者。更加高效与准确。具体特性与使用场景请参考官方文档中的内容。

ViewModel

ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel类让数据可在发生屏幕旋转的配置更改后继续留存
ViewModel的存在是为了从Activity和Fragment之类的界面控制器逻辑中分离出视图数据的所有权,实现界面显示与数据准备工作的分离。用于辅助界面控制器,负责为界面准备数据。并且可以避免视图控制器被销毁或者重新创建,设备发生配置更改(如屏幕旋转)等情况下,视图数据丢失的问题。具体特性与使用场景请参考官方文档中的内容。

分页库

通过分页库功能可以一次加载和显示一小块数据。按需载入部分数据会减少网络带宽和系统资源的使用。
官方文档示例中,分页库显示数据主要用到以下组件:

PagedList

分页库的关键组件是PagedList类,用于加载应用数据块或者页面。随着所需数据的增多,系统会将其分页到现有的PagedList对象中。如果任何已加载的数据发生更改,会从LiveData或基于Rxjava2的对象向可观察数据存储器发出一个新的PagedList实例。随着PagedList对象的生成,应用界面会呈现其内容,同时还会考虑界面控件的生命周期。

数据源(DataSource)

DataSource对象可以为PagedList提供数据来源,通过该对象加载应用数据的最新快照,包括从远程服务器获取数据或者从本地数据库获取数据。数据源的对象可以通过一个自定义的数据源工厂(DataSourceFactory)提供

RecyclerView

PagedList类使用PagedListAdapter适配器将数据逐项加载到RecyclerView。这些类共同作用,在内容加载时抓取和显示内容,预取不在界面可视范围内的内容以及针对内容更改添加动画

声明依赖项

使用以上架构组件的功能之前,需要在项目中添加其引用声明。包括生命周期组件、Paging组件,如果数据来源为数据库还可以添加Room组件。具体参考官方文档–声明依赖项

搭建列表显示模块代码框架

创建列表项的视图布局文件

创建一个Fragment视图作为列表项的Layout布局资源,并在RecyclerView中声明其为列表项布局文件。

     <androidx.recyclerview.widget.RecyclerView
     	   android:id="@+id/myRecyclerview"
     	   <!--其他属性-->
           tools:listitem="@layout/fragment_list_item" />

构建适配器PagedListAdapter

首先需要以PagedListAdapter为基类,自定义列表数据显示的适配器类。并重写以下方法:

  • onCreateViewHolder----以列表项fragment_list_item为模板,返回列表项的一个新的视图对象
  • onBindViewHolder—为列表中每一个视图对象绑定数据并显示

并自定义一个扩展自RecyclerView.ViewHolder的ViewHolder类,该类是与列表项布局fragment_list_item对应的。在ViewHolder中对列表项中的每一个视图控件做出声明并获取控件对象。
另外每一个ViewHolder中的视图组件的数据来自于一个自定义数据对象ItemInfo

public class ItemInfo
{
    //字符串,用于在textView中显示
	public String str;
	//图片链接,用于显示图片
	public String imgUrl;
	//一个唯一标识,可以作为列表项的键
	public String key;
}

整体代码大致如下:

public class MyListAdapter extends PagedListAdapter<ItemInfo,MyListAdapter.ViewHolder> {
    public MyListAdapter()
   {
       super(DIFF_CALLBACK);
   }

    private static DiffUtil.ItemCallback<ItemInfo> DIFF_CALLBACK =
            new DiffUtil.ItemCallback<ItemInfo>() {

                @Override
                public boolean areItemsTheSame(@NonNull ItemInfo oldItem, @NonNull ItemInfo newItem) {
                    // The ID property identifies when items are the same.
                    return oldItem.key == newItem.key;
                }

                @Override
                public boolean areContentsTheSame(@NonNull ItemInfo oldItem, @NonNull ItemInfo newItem) {
                    // Don't use the "==" operator here. Either implement and use .equals(),
                    // or write custom data comparison logic here.
                    return oldItem.key.equals(newItem.key);
                }
            };

    @NonNull
    @Override
    public MyListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_list_item,parent,false);
        
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyListAdapter.ViewHolder holder, int position) {
        try {
            ItemInfo _itemInfo=getItem(position);
            holder._textView.setText(_itemInfo.str);
            Glide.with(holder.mView).load(_itemInfo.imgUrl).into(holder._imageView);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
     }

    public class ViewHolder extends RecyclerView.ViewHolder
    {
        public final ImageView _imageView;
        public final TextView _textView;
  

        public final View mView;
        public ViewHolder(@NonNull View itemView)
        {
            super(itemView);
            _textView=(TextView)itemView.findViewById(R.id.idOfTextView);
            _imageView=(ImageView)itemView.findViewById(R.id.idOfImageView);

            mView=itemView;
        }
    }
}

通过以上代码,可以构建一个自定义的RecyclerView的适配器类,将列表视图的每一项进行数据适配

构建数据源DataSource

DataSource类是提供分页数据快照功能的一个基类。它的子类有以下三个

关于以上三种子类的详细区分可以查看链接内容。

下面以ItemKeyedDataSource为基类扩展一个自定义数据源类MyDataSource。

public class MyDataSource extends ItemKeyedDataSource<String, ItemInfo> {

	private int pageIndex=1;
	
	@Override
    public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull LoadInitialCallback<ItemInfo> callback) {
        fetchItems(params.requestedInitialKey,params.requestedLoadSize,pageIndex,callback);
    }

    private void fetchItems(String requestedInitialKey, int requestedLoadSize,int pageIndex,LoadCallback<ItemInfo> callback)
    {
        try
        {
            //在此处写入获取当前页列表数据的代码,可以从数据库中获取,或者从后端服务器API获取
            //List<ItemInfo> itemInfoList=*******
            //callback.onResult(itemInfoList);//通过回调返回列表数据
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void loadAfter(@NonNull LoadParams<String> params, @NonNull LoadCallback<ItemInfo> callback) {
        try {
            pageIndex=pageIndex+1;
            fetchItems(params.key, params.requestedLoadSize,pageIndex,callback);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<ItemInfo> callback) {

    }

    @NonNull
    @Override
    public String getKey(@NonNull ItemInfo item) {
        return item.key;
    }
}

通过以上代码可以构建一个自定义的数据源类,用于获取某一页的数据快照。

创建完MyDataSource之后,可以进一步创建一个工厂类MyDataSourceFactory,通过工厂类获得MyDataSource的对象。

public class MyDataSourceFactory extends MyDataSource.Factory<String, ItemInfo> {
    private MutableLiveData<MyDataSource> sourceLiveData=new MutableLiveData<>();
    private MyDataSource myDataSource;

    @NonNull
    @Override
    public DataSource<String, ItemInfo> create() {
        myDataSource=new MyDataSource();
        sourceLiveData.postValue(myDataSource);
        return myDataSource;
    }
}

构建ViewModel

自定义一个MyViewModel类,扩展自ViewModel基类。

public class MyViewModel extends ViewModel {
    public final LiveData currentItemInfoList;
    public MyViewModel()
    {
        PagedList.Config config=new PagedList.Config.Builder().setPageSize(20).setInitialLoadSizeHint(20).setPrefetchDistance(5).build();
        currentItemInfoList=new LivePagedListBuilder(new MyDataSourceFactory(),config).build();
    }
}

可以进一步创建一个ViewModel工厂,用于提供MyViewModel对象。


public class MyViewModelFactory implements ViewModelProvider.Factory {

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
         T t = (T) new MyViewModel();
        return t;
    }
}

组装以上模块

完成以上模块的构建之后,就可以在界面控制器中应用这些模块,实现完整的包括列表数据获取、适配与显示等功能。以一个Activity控制器为例:

public class MyActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;
    private MyListAdapter adapter=new MyListAdapter();
    private MyViewModel viewModel;
    private MyViewModelFactory viewModelFactory;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        viewModelFactory=new MyViewModelFactory();
        try {
             recyclerView=(RecyclerView)findViewById(R.id.myRecyclerview);
             layoutManager=new LinearLayoutManager(this);
             recyclerView.setLayoutManager(layoutManager);
             recyclerView.setAdapter(adapter);
             viewModel=new ViewModelProvider(this,viewModelFactory).get(MyViewModel.class);

             Observer<PagedList<ItemInfo>> listObserver= itemList->submitListForAdapter(itemList);
             viewModel.currentItemInfoList.observe(this,listObserver);
         }
         catch (Exception e)
         {

         }
    }
    
   public void submitListForAdapter(PagedList<ItemInfo> itemList)
    {
        adapter.submitList((PagedList<ItemInfo>) itemList);
        //其他自定义逻辑
    }
}

通过以上的工作,可以实现使用RecyclerView及相关架构组件实现列表数据展示的这一目标。当然只是实现基本的功能与流程。对于具体的业务需求和不同的使用场景。可以视情况,在自定义的DataSource,Adapter和界面控制器中添加更多的业务逻辑代码。实现更丰富的数据展示和更复杂更完善的功能

额外说明

以上的内容中可能会用到一些组件、框架。
另外还有一些未明确解释的概念。
具体情况可以查看以下相关资料深入了解。

  • 获取服务器API数据组件—Retrofit
  • 对于SQLite的一个抽象层组件库—Room
  • 图片加载–Glide
  • 组件生命周期–lifecycle
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值