最近有接到分页的需求, 想当然准备使用监听onScroll然后分段加载, 看到谷歌爸爸出品了Jetpack系列文章有Paging Lib于是点开看了下, 介绍的太复杂了有木有!!! room什么鬼, ViewModel云云, 抽丝剥茧
简单Demo入门, 记录如下
新建Activity, 我使用的Fragment+ViewModel的方式, 很方便

####1.导入依赖
1 2 3 4 5
| implementation 'android.arch.lifecycle:extensions:1.1.1' implementation 'android.arch.paging:runtime:1.0.0' implementation 'com.android.support:recyclerview-v7:27.0.2'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
版本不同方法可能有差异, 建议初学使用我这的版本, 方便跟着后面走
首先照着后面的代码复制一遍, 大概知道有哪些东西
####2.新建实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| class Concert {
public int id; private String name;
public Concert(int id, String name) { this.id = id; this.name = name; }
@Override public String toString() { return "Concert{" + "id=" + id + ", name='" + name + '\'' + '}'; }
@Override public int hashCode() { return id + name.hashCode(); }
@Override public boolean equals( Object obj) { if (obj instanceof Concert){ boolean b = ((Concert) obj).id == id && ((Concert) obj).name.equals(name); return b; }else { return false; } } }
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/pagedlist" android:layout_width="match_parent" android:layout_height="match_parent" >
<android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="0dp" android:layout_height="256dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/name" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginBottom="8dp" android:text="TextView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
|
####3.新建DataSource实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import android.arch.paging.PositionalDataSource; import android.support.annotation.NonNull; import android.util.Log;
import java.util.ArrayList; import java.util.List;
public class PositionPageDataSource extends PositionalDataSource<Concert> {
@Override public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<Concert> callback) { int requestedLoadSize = params.requestedLoadSize; Log.d("ldo","PositionPageDataSource loadInitial "+requestedLoadSize); List<Concert> subList = getSubList(0, requestedLoadSize); callback.onResult(subList,0,40); }
@Override public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<Concert> callback) { Log.d("ldo","PositionPageDataSource loadRange"); callback.onResult(getSubList(params.startPosition,params.loadSize)); }
public List<Concert> getSubList(int start, int end) { Log.d("ldo", "getSubList"); ArrayList<Concert> strings = new ArrayList<>(); for (int i = 0; i < end; i++) { strings.add(new Concert(start, "" + i)); } return strings; } }
import android.arch.paging.DataSource;
public class DataSourceFactorty extends DataSource.Factory<Integer,Concert> {
@Override public DataSource<Integer,Concert> create() { return new PositionPageDataSource(); } }
|
####4.新建Adapter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| import android.arch.paging.PagedListAdapter; import android.support.annotation.NonNull; import android.support.v7.util.DiffUtil; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView;
public class ConcertAdapter extends PagedListAdapter<Concert, ConcertAdapter.ViewHolder> {
ConcertAdapter() { super(showDiffCallBack); }
static DiffUtil.ItemCallback<Concert> showDiffCallBack = new DiffUtil.ItemCallback<Concert>() {
@Override public boolean areItemsTheSame(@NonNull Concert oldItem, @NonNull Concert newItem) { return (oldItem).id == (newItem).id; }
@Override public boolean areContentsTheSame(@NonNull Concert oldItem, @NonNull Concert newItem) { return oldItem.equals(newItem);
} };
@NonNull @Override public ConcertAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_concert_list, null)); }
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Concert concert = getItem(position); holder.v.setText(concert.getId()+""); }
public class ViewHolder extends RecyclerView.ViewHolder { TextView v;
public ViewHolder(@NonNull View itemView) { super(itemView); this.v = itemView.findViewById(R.id.textView); }
} }
|
####5.新建Fragment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| import android.arch.lifecycle.LiveData; import android.arch.lifecycle.Observer; import android.arch.paging.LivePagedListBuilder; import android.arch.paging.PagedList; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView;
import com.example.android.displayingbitmaps.R;
public class PagedListFragment extends Fragment {
private RecyclerView recyclerView; public static final int INITIALLOADSIZE = 40; public static final int RELOADSIZE = 20; private LiveData<PagedList<Concert>> data; private ConcertAdapter adapter;
public static PagedListFragment newInstance() {
return new PagedListFragment(); }
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.paged_list_fragment, container, false); recyclerView = inflate.findViewById(R.id.recyclerView); return inflate; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); PagedList.Config config = new PagedList.Config.Builder() .setPageSize(INITIALLOADSIZE / 2) .setEnablePlaceholders(false) .setInitialLoadSizeHint(INITIALLOADSIZE)
.build(); data = new LivePagedListBuilder(new DataSourceFactorty(), config).build(); data.observe(this, new Observer<PagedList<Concert>>() { @Override public void onChanged(@Nullable PagedList<Concert> concerts) { Log.d("ldo","onChanged "+concerts.size()); adapter.submitList(concerts); } }); adapter = new ConcertAdapter(); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); recyclerView.setAdapter(adapter); }
}
|
有一个大概认知之后简单介绍一下各个部分
- DataSource
数据处理核心, 最终回调到PagedList
- LivePagedListBuilder
关联DataSource和观察数据
- PagedList
可以理解为存储数据的集合容器, 不需要我们过多关注
- PagedListAdapter
配合recycleview使用
需要注意的是adapter.submitList(concerts)使用父类的方法设置集合, 采取自己设置list然后notifyDataChaged的方式, PositionPageDataSource里面的方法不会回调
####不同DataSource实现类的区别
目前有三种DataSource实现方式, 上面使用的是PositionalDataSource, 想必你已经看到效果了
- PositionalDataSource
适用于上拉加载更多的场景, 如京东商城列表浏览, 知乎等
- ItemKeyedDataSource
适用于下一part内容依赖当前某个key来获取, 如获得下一part的专辑列表, 需要传入当前歌手来获取
- PageKeyedDataSource
适用于有明显上下页的场景, 如支持上一章,下一章跳转可以使用此种方式