Skip to content

Commit

Permalink
commit 1.2.0 修改EventLiveData
Browse files Browse the repository at this point in the history
  • Loading branch information
hegaojian committed Nov 26, 2020
1 parent 9a0a1a9 commit e109e78
Show file tree
Hide file tree
Showing 47 changed files with 181 additions and 372 deletions.
27 changes: 14 additions & 13 deletions JetpackMvvm/build.gradle
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.novoda.bintray-release'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.github.panpf.bintray-publish'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 19
versionName "1.1.9"
targetSdkVersion 30
versionCode 20
versionName "1.2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
dataBinding{
enabled = true
buildFeatures {
dataBinding = true
}
buildTypes {
release {
Expand All @@ -36,33 +37,33 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
//kotlin
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.core:core-ktx:1.3.2'
//lifecycle
api 'androidx.lifecycle:lifecycle-runtime:2.2.0'
api 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
api 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
api 'androidx.lifecycle:lifecycle-extensions:2.2.0'
// viewModel
api "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
api "androidx.fragment:fragment-ktx:1.2.5"
// liveData
api "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
api 'com.kunminx.archi:unpeek-livedata:4.4.1-beta1'
//navigation
api 'androidx.navigation:navigation-runtime:2.3.0'
api 'androidx.navigation:navigation-runtime-ktx:2.3.1'
//retrofit
api "com.squareup.retrofit2:retrofit:2.9.0"
api "com.squareup.retrofit2:converter-gson:2.9.0"
api 'com.github.franmontiel:PersistentCookieJar:v1.0.1'
//动态替换BaseUrl库 使用可参考 https://github.com/JessYanCoding/RetrofitUrlManager
api 'me.jessyan:retrofit-url-manager:1.4.0'

}

publish {
userOrg = 'hegaojian'//bintray网站中的用户名,网站链接:https://bintray.com/
repoName = 'cxk'//仓库名字 这个可以随便起,比如我觉得我比较菜,所以我取了个蔡徐坤
groupId = 'me.hegj'//路径 名等于“me.hegj.JetpackMvvm:1.0.0”中的 me.hegj,你也可以写com.xxx
artifactId = 'JetpackMvvm'//项目名 等于“me.hegj.JetpackMvvm:1.0.0”中的 JetpackMvvm
publishVersion = '1.1.9'//版本号 等于“me.hegj.JetpackMvvm:1.0.0”中的 1.0.0
publishVersion = '1.2.0'//版本号 等于“me.hegj.JetpackMvvm:1.0.0”中的 1.0.0
desc = 'An Android Jetpack-MVVM framework,JetpackMvvm is nb?'//说明,不重要的东西,随便写
website = 'https://github.com/hegaojian/JetpackMvvm'//项目主页,用GitHub地址
licences = ['Apache-2.0']//协议
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ abstract class BaseVmActivity<VM : BaseViewModel> : AppCompatActivity() {
*/
private fun registerUiChange() {
//显示弹窗
mViewModel.loadingChange.showDialog.observe(this, Observer {
mViewModel.loadingChange.showDialog.observeInActivity(this, Observer {
showLoading(it)
})
//关闭弹窗
mViewModel.loadingChange.dismissDialog.observe(this, Observer {
mViewModel.loadingChange.dismissDialog.observeInActivity(this, Observer {
dismissLoading()
})
}
Expand All @@ -89,11 +89,11 @@ abstract class BaseVmActivity<VM : BaseViewModel> : AppCompatActivity() {
protected fun addLoadingObserve(vararg viewModels: BaseViewModel){
viewModels.forEach {viewModel ->
//显示弹窗
viewModel.loadingChange.showDialog.observe(this, Observer {
viewModel.loadingChange.showDialog.observeInActivity(this, Observer {
showLoading(it)
})
//关闭弹窗
viewModel.loadingChange.dismissDialog.observe(this, Observer {
viewModel.loadingChange.dismissDialog.observeInActivity(this, Observer {
dismissLoading()
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ abstract class BaseVmFragment<VM : BaseViewModel> : Fragment() {
mViewModel = createViewModel()
initView(savedInstanceState)
createObserver()
onVisible()
registorDefUIChange()
initData()
}
Expand Down Expand Up @@ -96,19 +95,17 @@ abstract class BaseVmFragment<VM : BaseViewModel> : Fragment() {
private fun onVisible() {
if (lifecycle.currentState == Lifecycle.State.STARTED && isFirst) {
//延迟加载0.12秒加载 避免fragment跳转动画和渲染ui同时进行,出现些微的小卡顿
view?.postDelayed({
lazyLoadData()
//在Fragment中,只有懒加载过了才能开启网络变化监听
NetworkStateManager.instance.mNetworkStateCallback.observe(
viewLifecycleOwner,
Observer {
//不是首次订阅时调用方法,防止数据第一次监听错误
if (!isFirst) {
onNetworkStateChanged(it)
}
})
isFirst = false
}, 120)
lazyLoadData()
//在Fragment中,只有懒加载过了才能开启网络变化监听
NetworkStateManager.instance.mNetworkStateCallback.observe(
viewLifecycleOwner,
Observer {
//不是首次订阅时调用方法,防止数据第一次监听错误
if (!isFirst) {
onNetworkStateChanged(it)
}
})
isFirst = false
}
}

Expand All @@ -125,10 +122,10 @@ abstract class BaseVmFragment<VM : BaseViewModel> : Fragment() {
* 注册 UI 事件
*/
private fun registorDefUIChange() {
mViewModel.loadingChange.showDialog.observe(viewLifecycleOwner, Observer {
showLoading()
mViewModel.loadingChange.showDialog.observeInFragment(this, Observer {
showLoading(it)
})
mViewModel.loadingChange.dismissDialog.observe(viewLifecycleOwner, Observer {
mViewModel.loadingChange.dismissDialog.observeInFragment(this, Observer {
dismissLoading()
})
}
Expand All @@ -137,14 +134,14 @@ abstract class BaseVmFragment<VM : BaseViewModel> : Fragment() {
* 将非该Fragment绑定的ViewModel添加 loading回调 防止出现请求时不显示 loading 弹窗bug
* @param viewModels Array<out BaseViewModel>
*/
protected fun addLoadingObserve(vararg viewModels: BaseViewModel){
viewModels.forEach {viewModel ->
protected fun addLoadingObserve(vararg viewModels: BaseViewModel) {
viewModels.forEach { viewModel ->
//显示弹窗
viewModel.loadingChange.showDialog.observe(viewLifecycleOwner, Observer {
viewModel.loadingChange.showDialog.observeInFragment(this, Observer {
showLoading(it)
})
//关闭弹窗
viewModel.loadingChange.dismissDialog.observe(viewLifecycleOwner, Observer {
viewModel.loadingChange.dismissDialog.observeInFragment(this, Observer {
dismissLoading()
})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,134 +1,11 @@
/*
* Copyright 2018-2019 KunMinX
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.hgj.jetpackmvvm.callback.livedata.event

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.util.*
import com.kunminx.architecture.ui.callback.UnPeekLiveData


/**
* TODO:UnPeekLiveData 的存在是为了在 "重回二级页面" 的场景下,解决 "数据倒灌" 的问题。
* 对 "数据倒灌" 的状况不理解的小伙伴,可参考《jetpack MVVM 精讲》的解析
*
*
* https://juejin.im/post/5dafc49b6fb9a04e17209922
*
*
* 本类参考了官方 SingleEventLive 的非入侵设计,
*
*
* TODO:并创新性地引入了 "延迟清空消息" 的设计,
* 如此可确保:
* 1.一条消息能被多个观察者消费
* 2.延迟期结束,不再能够收到旧消息的推送
* 3.并且旧消息在延迟期结束时能从内存中释放,避免内存溢出等问题
* 4.让非入侵设计成为可能,遵循开闭原则
* 用于限制从 Activity/Fragment 推送数据,推送数据务必通过唯一可信源来分发,
* 如果这样说还不理解,详见:
* https://xiaozhuanlan.com/topic/6719328450 和 https://xiaozhuanlan.com/topic/0168753249
*
*
* Create by KunMinX at 19/9/23
* 最新版的发送消息LiveData使用 https://github.com/KunMinX/UnPeek-LiveData 的最新版,因为跟其他类名(UnPeekLiveData)一致 所以继承换了一个名字
* 在Activity中observe 调用observeInActivity 在Fragment中使用调用 observeInFragment
* 具体写法请参考 https://github.com/KunMinX/UnPeek-LiveData的示例
*/
open class EventLiveData<T> : MutableLiveData<T>() {
private var isCleaning = false
private var hasHandled = true
private var isDelaying = false
protected var DELAY_TO_CLEAR_EVENT = 1000
private val mTimer = Timer()
private var mTask: TimerTask? = null
protected var isAllowNullValue = false
protected var isAllowToClear = true
override fun observe(
owner: LifecycleOwner,
observer: Observer<in T>
) {
super.observe(owner, Observer {
if (isCleaning) {
hasHandled = true
isDelaying = false
isCleaning = false
return@Observer
}
if (!hasHandled) {
hasHandled = true
isDelaying = true
observer.onChanged(it)
} else if (isDelaying) {
observer.onChanged(it)
}
})
}

/**
* UnPeekLiveData 主要用于表现层的 页面转场 和 页面间通信 场景下的非粘性消息分发,
* 出于生命周期安全等因素的考虑,不建议使用 observeForever 方法,
*
*
* 对于数据层的工作,如有需要,可结合实际场景使用 MutableLiveData 或 kotlin flow。
*
* @param observer
*/
override fun observeForever(observer: Observer<in T?>) {
throw IllegalArgumentException("Do not use observeForever for communication between pages to avoid lifecycle security issues")
}

/**
* 重写的 setValue 方法,默认不接收 null
* 可通过 Builder 配置允许接收
* 可通过 Builder 配置消息延时清理的时间
*
*
* override setValue, do not receive null by default
* You can configure to allow receiving through Builder
* And also, You can configure the delay time of message clearing through Builder
*
* @param value
*/
override fun setValue(value: T?) {
if (!isCleaning && !isAllowNullValue && value == null) {
return
}
hasHandled = false
isDelaying = false
super.setValue(value)
if (mTask != null) {
mTask!!.cancel()
mTimer.purge()
}
if (value != null) {
mTask = object : TimerTask() {
override fun run() {
clear()
}
}
mTimer.schedule(mTask, DELAY_TO_CLEAR_EVENT.toLong())
}
}

private fun clear() {
if (isAllowToClear) {
isCleaning = true
super.postValue(null)
} else {
hasHandled = true
isDelaying = false
}
}

}
class EventLiveData<T> : UnPeekLiveData<T>()
Loading

0 comments on commit e109e78

Please sign in to comment.