Pagingページングライブラリの基本的な使用
転載はリンクを明記してください:https://blog.csdn.net/feather_wch/article/details/88744255
Android paging libraryはページングライブラリです.は必要に応じてデータをロードして展示し、ネットワークトラフィックとシステム資源の損失 を避ける.
Pagingページングライブラリの基本的な使用
バージョン番号:2019-03-24(1:30)
文書ディレクトリ Pagingページングライブラリの基本使用 概要 依存追加 データベースにデータをロード RxJava形式 placeholders paging configuration invalidate data source type カスタム Consider how content updates work Provide data mapping 参考資料 概要
1、ページングロードの前世今生ページングロードには、2つのモード があります.従来のプルアップロードよりも多くのページング効果 無限スクロールのページング効果 2、無限スクロールのこのような無感知のページング効果は間違いなく最も良い
Paging libraryはこのようなページングライブラリです
1、Paging libraryのコアコンポーネントはは、appに必要なデータ(一部を先にロード) をページ別にロードすることができる.ロードされたデータの変化がある場合、新しい に更新される.
依存関係の追加
1.Pagingの依存追加(build.gradle)
データベースへのデータのロード
1、ActivityでRecyclerViewを使用し、データの傍受を設定する
Activityのレイアウト
2、RecyclerViewのAdapterは、PagedListAdapterから引き継ぐ必要があり、4つの部分の仕事をする必要がある onCreateViewHolder()-ViewHolder を作成 onBindView()-データとUIのバインド
レイアウト
3、GoalViewModel:内部構造
4、Roomデータベース関連:Goal、GoalDao、GoalDabase
GoalDao:データのクエリーを提供します.コアは
Goal:データエンティティ
GoalDatabase:データベース
RxJava形式
1、LiveDataをObservableまたはFlowableに置き換える
RxPagedListBuilderはbuildObservableを呼び出して構築する
使用
placeholders
paging configuration
invalidate
data source type
ツールバーの
Consider how content updates work
Provide data mapping
参考資料 Android公式アーキテクチャコンポーネントPaging:ページングライブラリの設計美学 Paging公式文書 Android JetpackアーキテクチャコンポーネントのPaging(使用、ソース編)
Android paging libraryはページングライブラリです.
Pagingページングライブラリの基本的な使用
バージョン番号:2019-03-24(1:30)
文書ディレクトリ
1、ページングロードの前世今生
Paging libraryはこのようなページングライブラリです
1、Paging libraryのコアコンポーネントは
PagedList
であるPagedlist
はLiveData RxJava2
の依存関係の追加
1.Pagingの依存追加(build.gradle)
/*==========================================
* Paging
*=============================================*/
implementation "android.arch.paging:runtime:1.0.1"
implementation "android.arch.paging:rxjava2:1.0.1" // Paging RxJava2
データベースへのデータのロード
1、ActivityでRecyclerViewを使用し、データの傍受を設定する
public class DailyPlanActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. RecyclerView + Adapter, DataBinding
final GoalListAdapter goalListAdapter = new GoalListAdapter(this);
RecyclerView recyclerView = findViewById(R.id.goal_recyclerview);
// 【LayoutManager!!!!!】
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
// adapter
recyclerView.setAdapter(goalListAdapter);
// 2. ViewModel LiveData, PagedListAdapter submitList
GoalViewModel goalViewModel = ViewModelProviders.of(this, new GoalViewModel.GoalViewModelFactory(this))
.get(GoalViewModel.class);
goalViewModel.getGoalList().observe(this, new Observer<PagedList<Goal>>() {
@Override
public void onChanged(@Nullable PagedList<Goal> goals) {
// submitList
goalListAdapter.submitList(goals);
}
});
}
}
Activityのレイアウト
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DailyPlanActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/goal_recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
android.support.constraint.ConstraintLayout>
2、RecyclerViewのAdapterは、PagedListAdapterから引き継ぐ必要があり、4つの部分の仕事をする必要がある
public static class GoalViewHolder extends RecyclerView.ViewHolder
private static DiffUtil.ItemCallback DIFF_CALLBACK
新旧データの差異比較public class GoalListAdapter extends PagedListAdapter<Goal, GoalListAdapter.GoalViewHolder>{
Context mContext;
public GoalListAdapter(Context context) {
super(DIFF_CALLBACK);
mContext = context;
}
@NonNull
@Override
public GoalViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
GoalItemBinding binding = DataBindingUtil.inflate(inflater, R.layout.recyclerview_goal_item_layout, parent, false);
return new GoalViewHolder(binding.getRoot());
}
@Override
public void onBindViewHolder(@NonNull GoalViewHolder holder, int position) {
/**======================================
* 1、【 】
*===============================================*/
GoalItemBinding binding = DataBindingUtil.getBinding(holder.itemView);
// 1. User
Goal goal = getItem(position);
binding.setGoal(goal);
// 2.
binding.executePendingBindings();
}
public static class GoalViewHolder extends RecyclerView.ViewHolder{
public GoalViewHolder(View itemView) {
super(itemView);
}
}
/**=====================================
* DiffUtil ,
*====================================*/
private static DiffUtil.ItemCallback<Goal> DIFF_CALLBACK =
new DiffUtil.ItemCallback<Goal>() {
@Override
public boolean areItemsTheSame(Goal oldGoal, Goal newGoal) {
return oldGoal.getId() == newGoal.getId();
}
@Override
public boolean areContentsTheSame(Goal oldGoal,
Goal newGoal) {
return oldGoal.equals(newGoal);
}
};
}
レイアウト
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class="com.hao.featherdailyplan.GoalItemBinding">
<variable
name="goal"
type="com.hao.architecture.Goal"/>
data>
<android.support.constraint.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="100dp"
tools:context="com.hao.architecture.DailyPlanActivity">
<ImageView
android:id="@+id/goal_icon_img"
android:layout_width="80dp"
android:layout_height="80dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:src="@drawable/ic_launcher_background"
android:layout_marginLeft="10dp"/>
<ImageView
android:id="@+id/goal_start_img"
android:layout_width="80dp"
android:layout_height="80dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:src="@drawable/ic_launcher_background"
android:layout_marginRight="10dp">
ImageView>
<TextView
android:id="@+id/goal_total_hours_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/goal_today_hours_txt"
app:layout_constraintEnd_toStartOf="@+id/goal_start_img"
tools:text="72.7h"
android:text='@{String.valueOf(goal.goaltime) + "h"}'
app:layout_constraintVertical_chainStyle="packed"
android:layout_marginEnd="10dp"/>
<TextView
android:id="@+id/goal_today_hours_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/goal_total_hours_txt"
tools:text="3.7h"
app:layout_constraintEnd_toStartOf="@+id/goal_today_hours_indivitual_txt"/>
<TextView
android:id="@+id/goal_today_hours_indivitual_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@+id/goal_today_hours_txt"
app:layout_constraintBottom_toBottomOf="@+id/goal_today_hours_txt"
app:layout_constraintEnd_toStartOf="@+id/goal_today_expected_hours_txt"
tools:text="/"/>
<TextView
android:id="@+id/goal_today_expected_hours_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@+id/goal_today_hours_txt"
app:layout_constraintBottom_toBottomOf="@+id/goal_today_hours_txt"
tools:text="7.7h"
app:layout_constraintEnd_toEndOf="@+id/goal_total_hours_txt"/>
<TextView
android:id="@+id/goal_timer_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="00:10:49"
app:layout_constraintStart_toEndOf="@id/goal_icon_img"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/goal_title_txt"
android:layout_marginStart="10dp"/>
<TextView
android:id="@+id/goal_title_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text=" 2019"
app:layout_constraintStart_toStartOf="@+id/goal_timer_txt"
app:layout_constraintTop_toBottomOf="@+id/goal_timer_txt"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@{goal.title}"/>
android.support.constraint.ConstraintLayout>
layout>
3、GoalViewModel:内部構造
LiveData> mGoalList
public class GoalViewModel extends ViewModel{
/**===================================
* 1、 , LiveData>
*====================================*/
private GoalDao mGoalDao;
private LiveData<PagedList<Goal>> mGoalList;
private static final int PAGE_SIZE = 10;
public LiveData<PagedList<Goal>> getGoalList() {
if(mGoalList == null){
mGoalList = new LivePagedListBuilder(mGoalDao.getGoalListFactory(), new PagedList.Config.Builder()
.setPageSize(PAGE_SIZE) //
.setInitialLoadSizeHint(PAGE_SIZE) //
.setPrefetchDistance(PAGE_SIZE)
.setEnablePlaceholders(true)
.build()).build();
}
return mGoalList;
}
/**=============================
* 2、 “ ” ViewModel
*=============================*/
@SuppressLint("StaticFieldLeak")
private Context mContext;
public GoalViewModel(Context context){
this.mContext = context;
this.mGoalDao = GoalDatabase.getInstance(mContext).getGoalDao();
}
public static class GoalViewModelFactory extends ViewModelProvider.NewInstanceFactory{
private Context mContext;
public GoalViewModelFactory(Context context){
mContext = context;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
return (T) new GoalViewModel(mContext);
}
}
}
4、Roomデータベース関連:Goal、GoalDao、GoalDabase
GoalDao:データのクエリーを提供します.コアは
DataSource.Factory
を提供することです.@Dao
public interface GoalDao {
@Query("select * from goal")
Flowable<Goal> queryGoalList();
@Query("select * from goal")
DataSource.Factory<Integer, Goal> getGoalListFactory();
@Insert
void insertGoal(Goal... goals);
@Delete
void deleteGoal(Goal goal);
@Update
void updateGoal(Goal goal);
}
Goal:データエンティティ
@Entity
public class Goal {
@PrimaryKey
private int id;
private int goaltype; // 0: 1:
private int analyticsGoalType; // , 、 、 、
private String title; //
private String description; //
private long goaltime; //
private String goalImgUrl; // url
private int goalImgColor; //
@Embedded(prefix = "begin")
private Date beginDate;
@Embedded(prefix = "bend")
private Date endDate;
public Goal(int id, int goaltype, int analyticsGoalType, String title, String description, long goaltime, String goalImgUrl, int goalImgColor, Date beginDate, Date endDate) {
this.id = id;
this.goaltype = goaltype;
this.analyticsGoalType = analyticsGoalType;
this.title = title;
this.description = description;
this.goaltime = goaltime;
this.goalImgUrl = goalImgUrl;
this.goalImgColor = goalImgColor;
this.beginDate = beginDate;
this.endDate = endDate;
}
// xxx
}
GoalDatabase:データベース
@Database(entities = {Goal.class}, version = 1, exportSchema = false)
// , version
public abstract class GoalDatabase extends RoomDatabase
{
private static GoalDatabase INSTANCE;
private static final Object sLock = new Object();
public abstract GoalDao getGoalDao();
public static GoalDatabase getInstance(Context context) {
synchronized (sLock) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), GoalDatabase.class, "goal.db")
.build();
}
return INSTANCE;
}
}
}
RxJava形式
1、LiveDataをObservableまたはFlowableに置き換える
RxPagedListBuilderはbuildObservableを呼び出して構築する
public class GoalViewModel extends ViewModel{
private Observable<PagedList<Goal>> mGoalList;
public Observable<PagedList<Goal>> getGoalList() {
if(mGoalList == null){
// RxPagedListBuilder
mGoalList = new RxPagedListBuilder(xxx).buildObservable();
}
return mGoalList;
}
}
使用
goalViewModel.getGoalList()
.subscribe(flowableList -> goalListAdapter.submitList(flowableList));
placeholders
paging configuration
invalidate
data source type
ツールバーの
Consider how content updates work
Provide data mapping
参考資料