Android mvvm架构,单一数据源,局部刷新

1、BaseActivity.kt

abstract class BaseActivity<VM : BaseViewModel<*>, VB : ViewBinding> : BaseViewModelActivity<VM, VB>() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        observeViewState()
        observeViewEvent()
    }

    protected abstract fun observeViewState()

    private fun observeViewEvent() {
        viewModel.collectEvent(this) {
            collect {
                when(it) {
                    is ViewEvent.ShowToast -> ToastUtil.showToast(this@BaseActivity, it.msg)
                    else -> onViewEvent(it)
                }
            }
        }
    }

    protected open fun onViewEvent(event: ViewEvent) {

    }
}

2、BaseViewModel.kt

open class BaseViewModel<VS: ViewState>(application: Application) : BaseViewModel(application) {

    private val _viewState = MutableStateFlow(defaultState())
//    val viewState = _viewState.asStateFlow()

    private val _viewEvent = MutableSharedFlow<ViewEvent>()
//    val viewEvent = _viewEvent.asSharedFlow()

    private fun defaultState(): VS {
        val parameterizedType = javaClass.genericSuperclass as ParameterizedType
        val clazz = parameterizedType.actualTypeArguments[0] as Class<VS>
        return clazz.newInstance()
    }

    protected fun setState(newState: VS) {
        _viewState.update {
            newState
        }
    }

    protected fun setState(update: VS.() -> Unit) {
        _viewState.update {
            (it.clone() as VS).apply {
                update()
            }
        }
    }

    protected fun sendEvent(event: ViewEvent) {
        launch {
            _viewEvent.emit(event)
        }
    }

    fun collectState(lifecycleOwner: LifecycleOwner, action: StateCollector<VS>.() -> Unit) {
        _viewState.collectState(lifecycleOwner) {
            action()
        }
    }

    fun collectEvent(lifecycleOwner: LifecycleOwner, action: EventCollector<ViewEvent>.() -> Unit) {
        _viewEvent.collectEvent(lifecycleOwner) {
            action()
        }
    }

    /**
     * 显示错误信息toast
     */
    protected fun showToast(msg: String) {
        sendEvent(ViewEvent.ShowToast(msg))
    }

}

3、StateCollector.kt

fun <T : ViewState> Flow<T>.collectState(
    lifecycleOwner: LifecycleOwner,
    state: Lifecycle.State = Lifecycle.State.STARTED,
    action: StateCollector<T>.() -> Unit
) {
    StateCollector(this, lifecycleOwner, state).action()
}

class StateCollector<T : ViewState>(
    private val flow: Flow<T>,
    private val lifecycleOwner: LifecycleOwner,
    private val state: Lifecycle.State,
) {

    private val prop1Set = mutableSetOf<KProperty1<T, *>>()

    private fun inProp1Set(p: KProperty1<T, *>):Boolean {
        for (prop in prop1Set) {
            if (prop.name == p.name) {
                return true
            }
        }
        return false
    }

    private fun areEquivalentExcludeSingleCollectProp(old: T, new: T): Boolean {
        if (prop1Set.isNotEmpty()) {
            val propList = old.javaClass.kotlin.members.filterIsInstance<KProperty1<T, *>>()
            for (p in propList) {
                if (inProp1Set(p)) continue
                val oldValue = p.get(old)
                val newValue = p.get(new)
                if (oldValue != newValue) {
                    return false
                }
            }
            return true
        }
        return old == new
    }

    fun collect(action: (T) -> Unit) {
        //lifecycleOwner利用开启协程
        lifecycleOwner.lifecycleScope.launch {
            //控制订阅的生命周期
            lifecycleOwner.repeatOnLifecycle(state) {
                //如果单独收集的属性不参与比对,防止ui重复刷新
                flow.distinctUntilChanged(::areEquivalentExcludeSingleCollectProp)
                    //收集元素
                    .collect { state ->
                        action(state)
                    }
            }
        }
    }

    fun <A> collect(
        prop1: KProperty1<T, A>,
        action: (A) -> Unit
    ) {
        prop1Set.add(prop1)
        //lifecycleOwner利用开启协程
        lifecycleOwner.lifecycleScope.launch {
            //控制订阅的生命周期
            lifecycleOwner.repeatOnLifecycle(state) {
                //只关注整个状态流中的某个元素(重点!利用反射机制找出需要的元素)
                flow.map { prop1.get(it) }
                    //防抖,防止其他元素更新导致自身更新
                    .distinctUntilChanged()
                    //收集元素
                    .collect { partialState ->
                        action(partialState)
                    }
            }
        }
    }

}

4、EventCollector.kt

fun <T : ViewEvent> Flow<T>.collectEvent(
    lifecycleOwner: LifecycleOwner,
    state: Lifecycle.State = Lifecycle.State.STARTED,
    action: EventCollector<T>.() -> Unit
) {
    EventCollector(this, lifecycleOwner, state).action()
}

class EventCollector<T : ViewEvent>(
    private val flow: Flow<T>,
    private val lifecycleOwner: LifecycleOwner,
    private val state: Lifecycle.State,
) {

    fun collect(action: (T) -> Unit) {
        //lifecycleOwner利用开启协程
        lifecycleOwner.lifecycleScope.launch {
            //控制订阅的生命周期
            lifecycleOwner.repeatOnLifecycle(state) {
                //收集元素
                flow.collect { event ->
                        action(event)
                    }
            }
        }
    }

}

5、ViewState.kt

interface ViewState: Cloneable {
    public override fun clone(): Any {
        return super.clone()
    }
}

6、ViewEvent.kt

interface ViewEvent {
    class ShowToast(val msg: String): ViewEvent
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值