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)