PreView

Room + ViewModel + LiveData is a component in JetPack, which is one of the most important technology updates for Android 2019. Using JetPack can help us quickly build stable and agile apps.

Coroutine is the streaming programming style that Kotlin supports and supports thread scheduling, which is slowly replacing RxJava.

1, Room

1) What is Room?

Room is a database component, mainly Sqlite operations to do a layer of packaging, through annotations for easy use.Copy the code

2) How to use it?

Room mainly consists of three parts; @database Database @DAO table (define add, delete, change, query) @Entity data fieldCopy the code

@Database(entities = [VideoInfo::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
 abstract fun videoInfoDao(): VideoInfoDao
 abstract fun screenShotInfoDao(): ScreenShotInfoDao]
}
Copy the code
@Dao
interface VideoInfoDao {

 @Query("SELECT * from VideoInfo")
 fun getAll(): LiveData<List<VideoInfo>>

 @Insert
 suspend fun insert(item: VideoInfo)

 @Insert
 suspend fun insertAll(items: List<VideoInfo>)

 @Delete
 suspend fun delete(item: VideoInfo): Int

 @Update(onConflict = OnConflictStrategy.REPLACE)
 suspend fun update(item: VideoInfo): Int

}
Copy the code
@Entity
class VideoInfo {
 @PrimaryKey(autoGenerate = true)
 var id: Long = 0
 @NonNull
 lateinit var title: String
 @NonNull
 lateinit var filePath: String
 @NonNull
 var width: Int = 0
 @NonNull
 var height: Int = 0
 @NonNull
 var fileSize: Long = 0
 @NonNull
 var dateAdded: Long = 0
 @NonNull
 var duration: Long = 0
 var coverImagePath: String? = null
 var albumVideoId: Int = 0
}
Copy the code

3) principle

Q: At this point we can't help but ask, with three annotations, how to implement the operation on the database? @Database @Dao @EntityCopy the code

R: Take @database as an example: @target (elementtype.type) @Retention(retentionPolicy.class) public @interface Database {"androidx.room:room-compiler:$room_version"The main effect is to have the interface annotated by these three annotations generate the corresponding code implementation at compile time. AppDataBase generates AppDatabase_Impl public Final Class AppDatabase_Impl extends AppDataBase {private volatile VideoInfoDao _videoInfoDao; private volatile ScreenShotInfoDao _screenShotInfoDao; } AppDatabase_Impl does two things: 1) initialize the database, support LiveData, and 2) create DAO operationsCopy the code

4) Advantages & Disadvantages

Advantages: 1. Easy access and use, clear code, easier to use than GreenDao. You can add the configuration file to build to generate THE JSON information created by data. nice javaCompileOptions { annotationProcessorOptions { arguments = [ "room.schemaLocation":"$projectDir/schemas".toString(), "room.incremental":"true", "Room. expandProjection":"true"]}} 3Copy the code

Disadvantages: Dao_Impl Dao_Impl Dao_Impl Dao_Impl Dao_Impl Dao_Impl Dao_Impl Dao_Impl Dao_Impl Dao_Impl Suspend Fun getAll(): LiveData<List<VideoInfo>>Copy the code

2, the ViewModel

1) What is a ViewModel?

At present, the most popular android technical framework is MVP & MVVM, in which ViewModel is the VM, MVVM design mode can be very good Model and View layer isolation, they use ViewModel as the bridge to achieve data assembly, and then throw to the View layer to do display.Copy the code

2) How to use ViewModel?

ViewModelProvider (fragments). Get (VideoInfoViewModel: : Java class) if need to pass the cords will be ViewModelProvider to Factory. The create ()Copy the code

3) ViewModel principle

The ViewModel life cycle follows the owner, or if the owner is Fragment/Activity, until death. Q1: How to implement the owner lifecycle binding? R1: Such as ViewModelProvider (fragments). Get (VideoInfoViewModel: : Java class) create a mViewModelStore in fragments, Create a ViewModel in the ViewProvider and store the ViewModel in the mViewModelStore. In fragment onDestory, empty ViewModel in mViewModelStore; This allows life to follow fragments until they die together on onDestroy. @callsuper public void onDestroy() {mCalled = true; @callsuper public void onDestroy() {mCalled = true; FragmentActivity activity = getActivity(); boolean isChangingConfigurations = activity ! = null && activity.isChangingConfigurations(); if (mViewModelStore ! = null && ! isChangingConfigurations) { mViewModelStore.clear(); Q2: The ViewModel life is still strong after the Activity is rebuilt. How to switch between horizontal and vertical screens without destroying the ViewModel? R2: Corresponding to each activity has a mViewModelStore under androidx to hold the ViewModel, somehow the screen switch will call ComponentActivity: : onRetainNonConfigurationInstance Keep mViewModelStore in NonConfigurationInstances, completed in somehow the screen switch, FragmentActivity calls onCreate, From getLastNonConfigurationInstance back again.Copy the code

4) ViewModel advantages & disadvantages

Advantages: 2) Attach the lifecycle of the ViewModel to the fragment/activity, so you don't have to maintain the lifecycle of the ViewModel. Fragment /activity destruction following destruction, effectively prevent the Model layer CallBack memory leak. 3) Fragments under the same Activity can communicate directly with data. Disadvantages: 1) There is no way to communicate data between activities, involving cross-process. 2) It is a little strange to use. There are two ways to write.... if you need to pass parameters and if you do not need to pass parameters Depressed can be unified into ViewModelProvider (fragments). The create (VideoInfoViewModel: : Java. Class) with (... parmas)Copy the code

LiveData

1) LiveData is what?

Real-time data by the name. Real-time data? This means that after the Model layer updates the data, the View layer receives the updated data.Copy the code

2) How to use LiveData?

liveData.observe(fragment, androidx.lifecycle.Observer { result -> videoListAdapter!! .data = result refresh()} liveData directly set the observe listener.Copy the code

3) LiveData principle

LiveData has two main features: 1. It is bound to the life cycle of the owner (Fragment/Activity). If the owner destroys LiveData, it will be automatically deactivated and will not update the data. 2, the model layer updated data, timely to the view layer. We look at the following code below process liveData. Observe (fragments, androidx. Lifecycle. The Observer {result - > videoListAdapter!! .data = result refresh()}) 1) Wrap observer as wrapper = LifecycleBoundObserver(owner, observer); Lifecycle adds an observer, owner.getLifecycle().addobserver (wrapper); Lifecycle changes to the fragment lifecycle are fed back to Lifecycle, which in turn feeds back to LifecycleBoundObserver, calling onStateChanged to pass data; If Lifecycle ::onDestroy is done, liveData will remove the Observer itself to prevent memory leaks due to external fragments being called inside the Observer. public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return; } activeStateChanged(shouldBeActive()); } 3) How does livedata.setValue(mValue) notify the View layer of updated data? Through livedata: : dispatchingValue distributed the data updates to the observer: : onChanged (mValue)Copy the code

4) LiveData advantages

Advantages: 1) Binding fragment/activity life cycle, we do not need to maintain the life cycle, effectively prevent memory leaks, it is said that using this memory leaks reduced by 43% 2) decoupling, view & Model decoupling. 3) PostValue can update data in child threads and then switch data to the main thread.Copy the code

Total: Room+ViewModel+LiveData collocation, good MVVM mode architecture, clear code logic. LiveData is not supported by the kotlin coroutine and LiveData. It would be nice if the ViewModel could unify the pass-through and non-pass-through entries to make it more usable.