Lifecycle
- 添加依赖
def lifecycle_version = "2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
- 管理fragment和activity的生命周期
OnLifecycleEvent注解表示监听哪个生命周期 - 使用
class LifecycleObserver : LifecycleObserver {
private val TAG = LifecycleObserver::class.simpleName
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun create() {
Log.e(TAG, "LifecycleObserver->onCreate")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start(){
Log.e(TAG, "LifecycleObserver->onStart")
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun resume(){
Log.e(TAG, "LifecycleObserver->onResume")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop(){
Log.e(TAG, "LifecycleObserver->onStop")
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun destory(){
Log.e(TAG, "LifecycleObserver->onDestory")
}
}
activity中使用
class MainActivity : AppCompatActivity(){
protected override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val observer=LifecycleObserver()
lifecycle.addObserver(observer)
}
}
使用很简单,实际就是用一个类统一管理了activity或者fragment的生命周期
LifecycleService解耦Service组件
- LocationServer
class LocationServer : LifecycleService() {
init {
val observer=LocationObserver(this)
lifecycle.addObserver(observer)
}
}
- LocationObserver
class LocationObserver(var mContext: Context) : LifecycleObserver {
private lateinit var locationListener: MyLocationListener
private lateinit var localManager: LocationManager
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun startLocation() {
localManager = mContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return
}
locationListener = MyLocationListener()
localManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1f, locationListener)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop() {
localManager.removeUpdates(locationListener)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun destory() {
Log.e("TAG", "LifecycleObserver->onDestory")
}
class MyLocationListener : LocationListener {
override fun onLocationChanged(location: Location?) {
}
override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
}
override fun onProviderEnabled(provider: String?) {
}
override fun onProviderDisabled(provider: String?) {
}
}
}
ProcessLifecycleOwner
- 针对整个应用程序的监听,与Activity的数量无关
- Lifecycle.Event.ON_CREATE只会被调用一次,Lifecycle.Event.ON_DESTROY永远不会被调用
class App : Application() {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(ApplicationObserver())
}
}
class ApplicationObserver :LifecycleObserver{
private val TAG = LifecycleObserver::class.simpleName
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun create() {
Log.e(TAG, "LifecycleObserver->onCreate")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start(){
Log.e(TAG, "LifecycleObserver->onStart")
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun resume(){
Log.e(TAG, "LifecycleObserver->onResume")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop(){
Log.e(TAG, "LifecycleObserver->onStop")
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun destory(){
Log.e(TAG, "LifecycleObserver->onDestory")
}
}
ViewModel
- ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据
- 使用
class MainViewModel : ViewModel() {
var number = 0
}
activity的代码
lateinit var mainViewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainViewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
value.text= mainViewModel.number.toString()
button1.setOnClickListener {
mainViewModel.number++
value.text = mainViewModel.number.toString()
}
button2.setOnClickListener{
mainViewModel.number--
value.text = mainViewModel.number.toString()
}
}
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="0"
android:textSize="18sp" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:text="加" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:text="减" />
</LinearLayout>
LiveData
- 在底层数据库更改时通知视图(实际是观察者和被观察者)
- 使用
class MainViewModel : ViewModel() {
private var numbers: MutableLiveData<Int>? = null
fun getNumber(): MutableLiveData<Int>? {
if (numbers == null) {
numbers = MutableLiveData()
numbers!!.value = 0
}
return numbers
}
fun addNumber(data: Int) {
numbers?.value = numbers?.value?.plus(data)
}
}
lateinit var mainViewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainViewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
mainViewModel.getNumber()?.observe(this, Observer {
value.text = it.toString()
})
button1.setOnClickListener {
mainViewModel.addNumber(1)
}
button2.setOnClickListener {
mainViewModel.addNumber(-1)
}
}
DataBinding
- 关于dataBinding详细使用可以看我以前写的博客数据绑定技术DataBinding
需要在build.gradle中的 defaultConfig添加以下代码
dataBinding {
enabled true
}
修改布局
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="data"
type="com.peakmain.jetpack.MainViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@{String.valueOf(data.number)}"
android:textSize="18sp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:onClick="@{()->data.addNumber(1)}"
android:text="加" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:onClick="@{()->data.addNumber(-1)}"
android:text="减" />
</LinearLayout>
</layout>
MainViewModel管理界面中的数据
class MainViewModel : ViewModel() {
private var number: MutableLiveData<Int>? = null
fun getNumber(): MutableLiveData<Int> {
if (number == null) {
number = MutableLiveData()
number!!.value = 0
}
return number!!
}
fun addNumber(data: Int) {
number!!.value = number!!.value!! + data
}
}
activity的使用
lateinit var binding: ActivityMainBinding
private lateinit var mainViewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
mainViewModel=ViewModelProviders.of(this).get(MainViewModel::class.java)//创建mainViewModel
binding.data = mainViewModel
binding.lifecycleOwner = this
}
ViewModelSavedState
即使进程在后台被系统杀死数据也存活
修改MainViewModel
class MainViewModel(state: SavedStateHandle) : ViewModel() {
private val handle: SavedStateHandle = state
companion object {
const val KEY_NUMBER = "key_number"
}
fun getNumber(): MutableLiveData<Int> {
if (!handle.contains(KEY_NUMBER)) {
handle.set(KEY_NUMBER, 0)
}
return handle.getLiveData(KEY_NUMBER)
}
fun addNumber(data: Int) {
getNumber().value = getNumber().value!!.plus(data)
}
}
activity中修改mainViewModel
mainViewModel = ViewModelProvider(this, SavedStateViewModelFactory(this.application, this)).get(MainViewModel::class.java)
AndroidViewModel
方便传context
修改mainViewModel
class MainViewModel(application: Application,state: SavedStateHandle) : AndroidViewModel(application) {
private val handle: SavedStateHandle = state
private val context: Application = application
companion object {
const val KEY_NUMBER = "key_number"
}
fun getNumber(): MutableLiveData<Int> {
if (!handle.contains(KEY_NUMBER)) {
handle.set(KEY_NUMBER, 0)
}
return handle.getLiveData(KEY_NUMBER)
}
fun addNumber(data: Int) {
getNumber().value = getNumber().value!!.plus(data)
}
fun startActivity() {
val intent=Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
}
}
Room
- 持久性库在 SQLite 的基础上提供了一个抽象层
- 添加依赖
apply plugin: 'kotlin-kapt'
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
// Test helpers
testImplementation "androidx.room:room-testing:$room_version"
Entity、Dao、Database
1.Entity:实体类,对应的是数据库的一张表结构
2.Dao:包含访问一系列访问数据库的方法
3.DataBase:数据持有者,作为与应用持久化相关数据的底层连接的主要接入点。
使用 @Database
注释的类应满足以下条件:
- 是扩展
RoomDatabase
的抽象类。 - 在注释中添加与数据库关联的实体列表。
- 包含具有 0 个参数且返回使用
@Dao
注释的类的抽象方法。
Entity表示数据库中的表,Dao包含用于访问数据库的方法
@Entity
class Word() {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
@ColumnInfo(name = "english_word")
var word: String = ""
@ColumnInfo(name = "chinese_mean")
var chineseMean: String = ""
constructor(word: String, chineseMean: String) : this() {
this.word = word
this.chineseMean=chineseMean
}
}
- Dao包含用于访问数据库的方法
@Dao
interface WordDao {
@Insert
fun insertWord(vararg words: Word?)
@Update
fun updateWord(vararg words: Word?)
@Delete
fun deleteWord(vararg words: Word?)
@Query("DELETE FROM WORD")
fun deleteAllWords()
@Query("SELECT *FROM WORD ORDER BY ID DESC ")
fun getAllWords():List<Word>
}
- Database
@Database(entities = [Word::class], version = 1, exportSchema = false)
abstract class WordDatabase : RoomDatabase() {
abstract fun getWordDao(): WordDao
}
activity的使用
class MainActivity : AppCompatActivity() {
lateinit var wordDatabase: WordDatabase
lateinit var wordDao: WordDao
lateinit var binding: ActivityMainBinding
private lateinit var mainViewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
mainViewModel = ViewModelProvider(this, SavedStateViewModelFactory(this.application, this)).get(MainViewModel::class.java)
binding.data = mainViewModel
binding.lifecycleOwner = this
wordDatabase = Room.databaseBuilder(this, WordDatabase::class.java, "word_database")
.allowMainThreadQueries()
.build()
wordDao = wordDatabase.getWordDao()
updateView()
}
//更新view
fun updateView() {
val list = wordDao.getAllWords()
var test = ""
for (word in list) {
test = test + word.id + ":" + word.word + "=" + word.chineseMean + "\n"
}
value.text = test
}
//添加数据
fun add(view: View) {
val word = Word("peakmain", "皮克曼")
val word1 = Word("body", "宝宝")
wordDao.insertWord(word, word1)
updateView()
}
//更新
fun update(view: View) {
val word = Word("Treasure", "喜")
word.id = 1
wordDao.updateWord(word)
updateView()
}
}
代码修改一
问题:1、会存在多个对象的实体类
2、mainviewmodel实际应该只是管理数据而不负责创建数据和删除数据等功能
- WordDatabase单例
@Database(entities = [Word::class], version = 1, exportSchema = false)
abstract class WordDatabase : RoomDatabase() {
companion object {
private var INSTANCE: WordDatabase? = null
fun getInstance(context: Context): WordDatabase {
if (INSTANCE == null) {
synchronized(this) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.applicationContext
, WordDatabase::class.java, "word_database")
.build()
}
}
}
return INSTANCE!!
}
}
abstract fun getWordDao(): WordDao
}
- 修改wordDao里面获取数据
@Query("SELECT *FROM WORD ORDER BY ID DESC ")
fun getAllWords():LiveData<List<Word>>
- 建立仓库
我们会发现一个问题:ViewModel的作用是和管理界面相关的数据,所以插入数据、更新数据和获取数据我们应该放到一个仓库里面
class WordRepository(context: Context) {
val wordDatabase: WordDatabase = WordDatabase.getInstance(context.applicationContext)
val wordDao = wordDatabase.getWordDao()
val allWordsLive: LiveData<List<Word>> = wordDao.getAllWords()
fun insertWords(vararg word: Word) {
InsertAsyncTask(wordDao).execute(*word)
}
fun updateWord(vararg word: Word) {
UpdateAsyncTask(wordDao).execute(*word)
}
class InsertAsyncTask(private val wordDao: WordDao) : AsyncTask<Word, Void, Void>() {
override fun doInBackground(vararg p0: Word): Void? {
wordDao.insertWord(*p0)
return null
}
}
class UpdateAsyncTask(private val wordDao: WordDao) : AsyncTask<Word, Void, Void>() {
override fun doInBackground(vararg p0: Word): Void? {
wordDao.updateWord(*p0)
return null
}
}
}
- MainViewModel代码修改
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val context: Application = application
var wordRepository: WordRepository = WordRepository(application)
fun getAllWordsLive(): LiveData<List<Word>> {
return wordRepository.allWordsLive
}
fun insertWords(vararg word: Word) {
wordRepository.insertWords(*word)
}
fun updateWord(vararg word: Word) {
wordRepository.updateWord(*word)
}
fun startActivity() {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
}
}
- mainActivity代码修改
class MainActivity : AppCompatActivity() {
lateinit var wordDao: WordDao
lateinit var binding: ActivityMainBinding
private lateinit var mainViewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
mainViewModel =
ViewModelProvider(this, SavedStateViewModelFactory(this.application, this))
.get(MainViewModel::class.java)
binding.data = mainViewModel
binding.lifecycleOwner = this
mainViewModel.getAllWordsLive().observe(this, Observer<List<Word>> { t ->
var test = ""
for (word in t) {
test = test + word.id + ":" + word.word + "=" + word.chineseMean + "\n"
}
value.text = test
})
}
//添加数据
fun add(view: View) {
val word1 = Word("peakmain", "皮克曼")
val word2 = Word("body", "宝宝")
mainViewModel.insertWords(word1,word2)
}
//更新
fun update(view: View) {
val word = Word("Treasure", "喜")
word.id = 3
mainViewModel.updateWord(word)
}
}
迁移表结构
- word修改
@ColumnInfo(name = "showChinese")
var showChinese: Boolean = false
- WordDatabase
@Database(entities = [Word::class], version = 2, exportSchema = false)
abstract class WordDatabase : RoomDatabase() {
companion object {
private var INSTANCE: WordDatabase? = null
fun getInstance(context: Context): WordDatabase {
if (INSTANCE == null) {
synchronized(this) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.applicationContext
, WordDatabase::class.java, "word_database")
.addMigrations(migration1_2)
.build()
}
}
}
return INSTANCE!!
}
}
abstract fun getWordDao(): WordDao
}
object migration1_2 : Migration(1,2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE word ADD COLUMN showChinese INTEGER NOT NULL DEFAULT 1")
}
}
删除数据库中某个字段
删除数据库中某个字段步骤
- 1、创建新表
- 2、从新表中插入数据
- 3、删除旧表
- 4、修改表名为旧表表名
object migration2_3 : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.run {
execSQL("CREATE TABLE word_tmp (id INTEGER PRIMARY KEY NOT NULL,english_word TEXT," +
"chinese_mean TEXT)")
execSQL("INSERT INTO word_tmp (id,english_word,chinese_mean) " +
"SELECT id,english_word,chinese_mean from word")
execSQL("DROP TABLE word")
execSQL("ALTER TABLE word_tmp RENAME to word")
}
}
}
schema文件
- Room在每次数据库升级过程中,都会导出一个Schema的文件,这是一个json文件,其中包含了数据库的基本信息,有了该文件,开发者能清除知道数据库历次变更情况。极大方便开发者排查问题
javaCompileOptions {
annotationProcessorOptions {
//指定schema文件的位置
arguments = ["room.schemaLocation":"$projectDir/schemas".toString()]
}
}
WorkManager
- WorkManager为 应用程序中那些不需要及时完成的任务提供了统一的解决方案,以便在设备电量和用户体验之间达到一个比较好的平衡,如:发送日志
- workManager能保证任务一定被执行,即使应用程序当前不再运行过程中,甚至在设备重启之后,任务依然会在适当的时刻执行,这是因为WorkManager有自己的数据库,有关任务的所有信息都保存在该数据库中。
-
兼容性广
def work_version = "2.3.4"
// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"
// optional - GCMNetworkManager support
implementation "androidx.work:work-gcm:$work_version"
// optional - Test helpers
androidTestImplementation "androidx.work:work-testing:$work_version"
class MyWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters)
: Worker(context, workerParams) {
override fun doWork(): Result {
val value = inputData.getString("in_key")
Log.e("TAG", "value = $value")
Log.e("TAG", "开始睡眠")
Thread.sleep(3000)
Log.e("TAG", "结束睡眠")
return Result.success(workDataOf("out_key" to "$value result"))
}
}
val constraints = Constraints.Builder()
//NetworkType.NOT_REQUIRED:对网络没有要求
//NetworkType.CONNECTED:网络的时候执行
//NetworkType.UNMETERED:不计费的网络比如Wi-Fi
//NetworkType.NOT_ROAMING:非漫游网络
//NetworkType.METERED:计费网络比如3g,4g下执行
//注意:不代表恢复网络,就立马执行
.setRequiredNetworkType(NetworkType.METERED)//👈设置条件为网络连接情况
.build()
val workReuest =
//PeriodicWorkRequest:周期性任务
OneTimeWorkRequestBuilder<MyWork>()//👈一次性任务
//.setConstraints(constraints)//👈设置条件
.setInputData(workDataOf("in_key" to "Peakmain"))//👈输入简单数据
.setInitialDelay(5L,TimeUnit.SECONDS)//设置5s延迟执行
.addTag("peakmain")
.build()
workManager.enqueue(workReuest)
//监听数据变化
workManager.getWorkInfoByIdLiveData(workReuest.id)
.observe(this, Observer {
Log.e("TAG", "onCreate:" + it.state)
if (it.state == WorkInfo.State.SUCCEEDED) {
Log.e("TAG", "onCreate" + it.outputData.getString("out_key"))
}
})
//取消任务
workManager.cancelWorkById(workRequest.getId());
- 任务链和任务组合
-
责任链
-
WorkManager.getInstance(this)
.beginWith(A)
.then(B).enqueue()
-
AB,CD先执行最后执行E
var workManager1: WorkContinuation=WorkManager.getInstance(this)
.beginWith(A)
.then(B).enqueue()
var workManager2: WorkContinuation=WorkManager.getInstance(this)
.beginWith(A)
.then(B).enqueue()
var takeList = ArrayList<WorkContinuation>()
takeList.add(workManager1)
takeList.add(workManager2)
var workManager: WorkContinuation = WorkContinuation.combine(takeList)
.then(E)
.enqeue()
paging
- paging实际就是分页加载,它把几种常见的分页机制提供了统一的解决方案
- paging支持的架构类型
- 网络数据
分页机制所设计的API接口不一样,但是总体可以分为3种,因此paging提供了3种不同的解决方案,分别是:PositionDataSource、PageKeyedDataSource、ItemKeyedDataSource - 数据库
替换数据源
- 网络数据
-
工作原理
- 3个核心类
- pagedListAdapter
- 如果需要使用paging组件,适配器需要继承pagedListAdapter
- pagedList
- pagedList负责通知DataSource何时和如何获取数据,从DataSource获取的数据将存储在pagedList中
- DataSource
- 执行具体的数据载入工作,数据可以来自网络,也可以来自本地数据、数据库数据,根据分页机制不同,paging提供了3种DataSource
- 数据的载入需要再工作线程中进行
- pagedListAdapter
PositionDataSource
- 适用于可通过任意位置加载数据,且目标数据源数量固定的情况。
- 比如:从数据库的第100条数据开始加载20条数据
- DataSource创建
public class StudentDataSource extends PositionalDataSource<Student> {
/**
* 加载第一页数据的时候执行
*
* @param params
* @param callback
*/
@Override
public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<Student> callback) {
/**
* position:位置
* totalCount:总的大小
*/
callback.onResult(getStudents(0, 20), 0,1000);
}
/**
* 有了初始化数据之后,滑动的时候如果需要加载数据的话,会调用此方法
*
* @param params
* @param callback
*/
@Override
public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<Student> callback) {
callback.onResult(getStudents(params.startPosition, params.loadSize));
}
/**
* 假的数据源
*/
private List<Student> getStudents(int startPosition, int pageSize) {
List<Student> students = new ArrayList<>();
for (int i = startPosition; i < startPosition + pageSize; i++) {
Student student = new Student("Id是:" + i, "名字:" + i);
students.add(student);
}
return students;
}
}
- 数据工厂
/**
* author :Peakmain
* createTime:2021/11/5
* mail:2726449200@qq.com
* describe:PositionalDataSource对应的Key是Integer
*/
public class StudentDataSourceFactory extends DataSource.Factory<Integer,Student> {
@NonNull
@Override
public DataSource<Integer, Student> create() {
return new StudentDataSource();
}
}
- pageList的创建
public class StudentViewModel extends ViewModel {
private final LiveData<PagedList<Student>> listLiveData;
public StudentViewModel() {
StudentDataSourceFactory factory = new StudentDataSourceFactory();
this.listLiveData = new LivePagedListBuilder<>(factory, 20).build();
}
public LiveData<PagedList<Student>> getListLiveData() {
return listLiveData;
}
}
- PagedListAdapter的创建
public class StudentAdapter extends PagedListAdapter<Student, StudentAdapter.CommonRecyclerViewHolder> {
private static DiffUtil.ItemCallback<Student> DIFF_STUDENT = new DiffUtil.ItemCallback<Student>() {
//一般比较的是唯一内容:id
@Override
public boolean areItemsTheSame(@NonNull Student oldItem, @NonNull Student newItem) {
return oldItem.getId().equals(newItem.getId());
}
//对象本身的比较
@Override
public boolean areContentsTheSame(@NonNull Student oldItem, @NonNull Student newItem) {
return oldItem.equals(newItem);
}
};
public StudentAdapter() {
//diffCallback比较的行为
super(DIFF_STUDENT);
}
@NonNull
@Override
public CommonRecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.bean_recycler_view, null);
return new CommonRecyclerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull CommonRecyclerViewHolder holder, int position) {
Student student = getItem(position);
holder.mTvName.setText(student.getName());
holder.mTvId.setText(student.getId());
}
public static class CommonRecyclerViewHolder extends RecyclerView.ViewHolder {
private TextView mTvId, mTvName;
public CommonRecyclerViewHolder(@NonNull View itemView) {
super(itemView);
mTvId = itemView.findViewById(R.id.tv_id);
mTvName = itemView.findViewById(R.id.tv_name);
}
}
}
ItemKeyedDataSource<T>
- 适用于目标数据的加载依赖特定的item的信息,即key字段包含的是item中的信息
- 如:根据第N项的信息加载第n+1项的数据,传参中需要传入第N项的ID时
- 场景:论坛应用评论信息的请求
PageKeyedDataSource
- 如果页面需要实现上一页、下一页,需要将请求的Token传递到下一步时使用