preface
Kotlin has been very popular in foreign countries, the benefits need not say more, if you do not study, then you can only lag behind, then the chance to marry Bai Fumei will be much less. MVVM+LiveData is also a popular APP architecture mode, it is necessary to learn a wave. Therefore, in line with the attitude of learning, I wrote a basic library, which can be directly relied on when writing new projects. Without further ado, open the code.
Train of thought
First of all, my thinking is that some activities may not need ViewDataBinding, may not need ViewModel, may not need either, so I BaseActivity, just add the most basic code. There ViewDataBinding BaseViewDataBindingActivity, ViewModel, BaseViewModelActivity ViewModel only, both the Activity is inherited from BaseActivity. If there is a need to change, you can modify according to your own requirements.
BaseActivity
Create a singleton ActivityTaskManager, manage the Activity, according to toutiao adaptation solution, add adaptation code, a display load dialog, see the code
package com.example.baselibrary
import android.app.Dialog
import android.os.Bundle
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import com.example.baselibrary.manager.ActivityTaskManager
import com.example.baselibrary.manager.ScreenManager.SCREEN
import com.example.baselibrary.utils.DialogLoadingUtils
/ * * *@name Android BaseLibrary
* @className: com. Example. Baselibrary *@describeActivity base class, because also need to BaseViewDataActivity, BaseViewModelActivity inheritance, which has different implementation setContentView method, *@describeIn BaseActivity, setContentView results in repeated loading, so if you inherit BaseActivity, you need to do setContentView * yourself@authorApes XiaoCai *@time 2020/8/10
* @change
* @chang time
*/
abstract class BaseActivity : AppCompatActivity(a){
private var mLoadingDialog: Dialog? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ActivityTaskManager.instance.put(this)
SCREEN(this)}@get:LayoutRes
protected abstract val layoutId: Int
/** Displays the user waiting box */
protected fun showLoadingDialog(msg: String? = "") {
mLoadingDialog = DialogLoadingUtils.createLoadingDialog(this, msg) mLoadingDialog!! .show() }/** Hide the waiting box */
protected fun dismissLoadingDialog(a) {
if(mLoadingDialog ! =null&& mLoadingDialog!! .isShowing) { mLoadingDialog!! .dismiss() mLoadingDialog =null}}override fun onDestroy(a) {
super.onDestroy()
ActivityTaskManager.instance.remove(this)}}Copy the code
ActivityTaskManager, DialogLoadingUtils, and so on are all in my utility classes, and Kotlin is relatively easy to write utility classes.
BaseViewModelActivity
package com.example.baselibrary
import android.os.Bundle
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.example.baselibrary.lifecycle.BaseViewModel
import com.example.baselibrary.utils.MLog
import java.lang.reflect.ParameterizedType
/ * * *@name Android BaseLibrary
* @className: com. Example. Baselibrary *@classDescribe BaseActivity * with ViewModel@authorApes XiaoCai *@time 2020/8/10
* @change
* @chang time
*/
abstract class BaseViewModelActivity<VModel : BaseViewModel> : BaseActivity(a){
private val TAG = javaClass.simpleName
protected lateinit var mViewModel: VModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(layoutId)
mViewModel = initViewModel()
initObserve()
initData()
}
protected abstract fun initData(a)
private fun initViewModel(a): VModel {
try {
// Get the real type of the model by reflection
val pt =
this.javaClass.genericSuperclass as ParameterizedType? val clazz = pt!! .actualTypeArguments[0] as Class<VModel>
mViewModel = ViewModelProviders.of(this)[clazz]
} catch (e: Exception) {
MLog.e(TAG, e)
}
return mViewModel
}
/** listen for showDialog and error values */ in the current ViewModel
private fun initObserve(a) {
mViewModel.getShowDialog(
this,
Observer { (isShow, msg) ->
if (isShow) {
showLoadingDialog(msg)
} else {
dismissLoadingDialog()
}
})
mViewModel.getError(
this,
Observer { showError(it) })
}
/** The ViewModel layer has an error */
protected abstract fun showError(obj: Any?)
}
Copy the code
The ViewModel object must pass ViewModelProviders. Of (this). The get (BaseViewModel: : class. Java) to create. Some people create it in the current Activity, but I find it cumbersome, so I create it in BaseViewModelActivity with reflection. For a specific use of BaseViewModelActivity, see ViewModuleActivity.
BaseViewDataBindingActivity
package com.example.baselibrary
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.example.baselibrary.lifecycle.BaseViewModel
import com.example.baselibrary.utils.MLog
import java.lang.reflect.ParameterizedType
/ * * *@name Android BaseLibrary
* @className: com. Example. Baselibrary *@classDescribe BaseActivity * with ViewDataBinding and ViewModel@authorApes XiaoCai *@time 2020/8/10
* @change
* @chang time
*/
abstract class BaseViewDataBindingActivity<DBinding : ViewDataBinding.VModel : BaseViewModel> :
BaseActivity(a){
protected lateinit var mDataBinding: DBinding
protected lateinit var mViewModel: VModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mDataBinding = initDataBinding()
initData()
}
private val TAG = javaClass.simpleName
protected abstract fun initData(a)
private fun initViewModel(a): VModel {
try {
// Get the real type of the model by reflection
val pt =
this.javaClass.genericSuperclass as ParameterizedType? val clazz = pt!! .actualTypeArguments[1] as Class<VModel>
mViewModel = ViewModelProviders.of(this)[clazz]
} catch (e: Exception) {
MLog.e(TAG, e.message, e)
}
return mViewModel
}
protected fun initDataBinding(a): DBinding {
mDataBinding = DataBindingUtil.setContentView(this, layoutId)
mViewModel = initViewModel()
initObserve()
return mDataBinding
}
/** listen for showDialog and error values */ in the current ViewModel
private fun initObserve(a) {
mViewModel.getShowDialog(
this,
Observer { (isShow, msg) ->
if (isShow) {
showLoadingDialog(msg)
} else {
dismissLoadingDialog()
}
})
mViewModel.getError(
this,
Observer { showError(it) })
}
/** The ViewModel layer has an error */
protected abstract fun showError(obj: Any?)
}
Copy the code
ViewDataBinding need DataBindingUtil. The setContentView (this, layoutId) to create, the layout of the layoutId is your id. The outermost layer of the layout should be a layout. There’s an example in Demo ViewDataDemoActivity, and the layout activity_viewdata.xml.
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.example.baselibrarydemo.bean.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:text="@{user.name}" />
</LinearLayout>
</layout>
Copy the code
For details, see ViewDataDemoActivity and ViewModuleActivity. Network requests will continue to be added later
BaseLibraryDemo
Refer to the article
TODO – MVVM: AndroidX + ViewModel + LiveData + DataBinding components in JetPack are used, while mainstream frameworks such as ViewPager2 + RxJava2 + Retrofit2 + Glide are used to build
Android-tools-boluomi: common Android tool
Build MVVM Architecture for Android Projects using LiveData and ViewModel (Kotlin)