From f6f580bfb35a6ae4e787d0fbd6afd4e0500c70f6 Mon Sep 17 00:00:00 2001 From: Goooler Date: Wed, 23 Mar 2022 22:47:31 +0800 Subject: [PATCH 1/9] Migrate MainSrlViewModel to use flow --- .../demoapp/main/vm/MainSrlViewModel.kt | 76 +++++++++---------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt index 794341759..3f736a67e 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt @@ -1,28 +1,29 @@ package io.goooler.demoapp.main.vm +import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import io.goooler.demoapp.base.util.MutableBooleanLiveData -import io.goooler.demoapp.base.util.MutableListLiveData -import io.goooler.demoapp.common.base.theme.BaseRxViewModel +import io.goooler.demoapp.common.base.theme.BaseThemeViewModel import io.goooler.demoapp.common.type.CommonConstants import io.goooler.demoapp.main.model.MainCommonVhModel import io.goooler.demoapp.main.repository.MainCommonRepository import java.util.Collections import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch @HiltViewModel class MainSrlViewModel @Inject constructor(private val repository: MainCommonRepository) : - BaseRxViewModel() { + BaseThemeViewModel() { private val _listData = mutableListOf() private var page = 1 - val listData = MutableListLiveData() - val isLoadMoreFinish = MutableBooleanLiveData() - val isRefreshFinish = MutableBooleanLiveData() - val isNoMore = MutableBooleanLiveData() - val isEnableRefresh = MutableBooleanLiveData() - val isEnableLoadMore = MutableBooleanLiveData() + val listData: MutableStateFlow> = MutableStateFlow(_listData) + val isLoadMoreFinish = MutableStateFlow(false) + val isRefreshFinish = MutableStateFlow(false) + val isNoMore = MutableStateFlow(false) + val isEnableRefresh = MutableStateFlow(false) + val isEnableLoadMore = MutableStateFlow(false) init { enableRefreshAndLoadMore(true) @@ -50,39 +51,34 @@ class MainSrlViewModel @Inject constructor(private val repository: MainCommonRep } private fun fetchListData(page: Int) { - repository.getRepoListWithRx("goooler", page) - .doFinally { - isRefreshFinish.postValue(true) - isLoadMoreFinish.postValue(true) + viewModelScope.launch { + try { + repository.getRepoListWithCr("goooler", page) + .map { bean -> + MainCommonVhModel.Repo(bean.owner?.avatarUrl, bean.name, bean.fullName) + }.let { + _listData += it + if (page == 1 && it.isEmpty()) { + _listData += listOf(MainCommonVhModel.Empty()) + } + if (it.size < CommonConstants.DEFAULT_PAGE_SIZE) { + isNoMore.value = true + } + }.let { + listData.value = _listData + } + } catch (_: Exception) { + listData.value = listOf(MainCommonVhModel.Error()) + enableRefreshAndLoadMore(false) + } finally { + isRefreshFinish.value = true + isLoadMoreFinish.value = true } - .map { - it.map { bean -> - MainCommonVhModel.Repo(bean.owner?.avatarUrl, bean.name, bean.fullName) - } - } - .doOnSuccess { - _listData += it - if (page == 1 && it.isEmpty()) { - _listData += listOf(MainCommonVhModel.Empty()) - } - if (it.size < CommonConstants.DEFAULT_PAGE_SIZE) { - isNoMore.postValue(true) - } - } - .subscribe( - { - listData.postValue(_listData) - }, - { - listData.postValue(listOf(MainCommonVhModel.Error())) - enableRefreshAndLoadMore(false) - } - ) - .autoDispose() + } } private fun enableRefreshAndLoadMore(enable: Boolean) { - isEnableRefresh.postValue(enable) - isEnableLoadMore.postValue(enable) + isEnableRefresh.value = enable + isEnableLoadMore.value = enable } } From 32823e55945f9b67d0f0aeeac6f34d764d3e7844 Mon Sep 17 00:00:00 2001 From: Goooler Date: Wed, 23 Mar 2022 23:15:47 +0800 Subject: [PATCH 2/9] Migrate DetailViewModel to use flow --- .../demoapp/detail/ui/RepoDetailActivity.kt | 7 +++---- .../demoapp/detail/vm/DetailViewModel.kt | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt b/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt index e41900d84..df984216f 100644 --- a/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt +++ b/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt @@ -3,8 +3,8 @@ package io.goooler.demoapp.detail.ui import android.os.Bundle import androidx.activity.compose.setContent import androidx.activity.viewModels +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState import io.goooler.demoapp.base.core.BaseActivity import io.goooler.demoapp.detail.vm.DetailViewModel @@ -21,9 +21,8 @@ class RepoDetailActivity : BaseActivity() { } setContent { - val model = vm.repoDetailModel.observeAsState().value - ?: throw IllegalArgumentException("RepoDetailModel has not been initialized") - val isRefreshing by vm.isRefreshing.observeAsState(false) + val model by vm.repoDetailModel.collectAsState() + val isRefreshing by vm.isRefreshing.collectAsState() DetailPageWithSwipeRefresh(isRefreshing, vm::refresh, model, vm::fork) } } diff --git a/detail/src/main/kotlin/io/goooler/demoapp/detail/vm/DetailViewModel.kt b/detail/src/main/kotlin/io/goooler/demoapp/detail/vm/DetailViewModel.kt index 20cbd2d3c..57039077e 100644 --- a/detail/src/main/kotlin/io/goooler/demoapp/detail/vm/DetailViewModel.kt +++ b/detail/src/main/kotlin/io/goooler/demoapp/detail/vm/DetailViewModel.kt @@ -1,28 +1,33 @@ package io.goooler.demoapp.detail.vm -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import io.goooler.demoapp.base.core.BaseViewModel -import io.goooler.demoapp.base.util.MutableBooleanLiveData import io.goooler.demoapp.common.network.RetrofitHelper import io.goooler.demoapp.detail.model.RepoDetailModel import io.goooler.demoapp.detail.repository.DetailRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch class DetailViewModel : BaseViewModel() { private val repository = DetailRepository(RetrofitHelper.create()) private var repoDetail = RepoDetailModel() - private val _repoDetailModel = MutableLiveData(repoDetail) + + private val _repoDetailModel = MutableStateFlow(repoDetail) + private val _isRefreshing = MutableStateFlow(false) lateinit var fullName: String - val repoDetailModel: LiveData = _repoDetailModel - val isRefreshing: MutableBooleanLiveData = MutableBooleanLiveData() + + val repoDetailModel: StateFlow + get() = _repoDetailModel.asStateFlow() + val isRefreshing: StateFlow + get() = _isRefreshing.asStateFlow() fun refresh() { - isRefreshing.value = true viewModelScope.launch { + _isRefreshing.emit(true) repository.getRepoDetail(fullName).let { repoDetail = RepoDetailModel( it.fullName, @@ -34,7 +39,7 @@ class DetailViewModel : BaseViewModel() { ) } _repoDetailModel.value = repoDetail - isRefreshing.value = false + _isRefreshing.emit(false) } } From 4d3f075e5aa36936c9bdea453e6f00ac67b51d99 Mon Sep 17 00:00:00 2001 From: Goooler Date: Wed, 23 Mar 2022 23:45:47 +0800 Subject: [PATCH 3/9] Reset states --- .../io/goooler/demoapp/main/vm/MainSrlViewModel.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt index 3f736a67e..0ca29091d 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt @@ -18,7 +18,7 @@ class MainSrlViewModel @Inject constructor(private val repository: MainCommonRep private val _listData = mutableListOf() private var page = 1 - val listData: MutableStateFlow> = MutableStateFlow(_listData) + val listData: MutableStateFlow> = MutableStateFlow(emptyList()) val isLoadMoreFinish = MutableStateFlow(false) val isRefreshFinish = MutableStateFlow(false) val isNoMore = MutableStateFlow(false) @@ -31,6 +31,7 @@ class MainSrlViewModel @Inject constructor(private val repository: MainCommonRep fun refresh() { page = 1 + isNoMore.value = false _listData.clear() fetchListData(page) } @@ -53,6 +54,7 @@ class MainSrlViewModel @Inject constructor(private val repository: MainCommonRep private fun fetchListData(page: Int) { viewModelScope.launch { try { + finishRefreshAndLoadMore(false) repository.getRepoListWithCr("goooler", page) .map { bean -> MainCommonVhModel.Repo(bean.owner?.avatarUrl, bean.name, bean.fullName) @@ -65,18 +67,22 @@ class MainSrlViewModel @Inject constructor(private val repository: MainCommonRep isNoMore.value = true } }.let { - listData.value = _listData + listData.value = _listData.toList() } } catch (_: Exception) { listData.value = listOf(MainCommonVhModel.Error()) enableRefreshAndLoadMore(false) } finally { - isRefreshFinish.value = true - isLoadMoreFinish.value = true + finishRefreshAndLoadMore(true) } } } + private fun finishRefreshAndLoadMore(finish: Boolean) { + isRefreshFinish.value = finish + isLoadMoreFinish.value = finish + } + private fun enableRefreshAndLoadMore(enable: Boolean) { isEnableRefresh.value = enable isEnableLoadMore.value = enable From 6fae401d950f78ff15908b9aa8a2ab41ef804b70 Mon Sep 17 00:00:00 2001 From: Goooler Date: Mon, 4 Apr 2022 16:30:52 +0800 Subject: [PATCH 4/9] Remove livedata deps --- .../demoapp/base/util/BaseExtensions.kt | 32 ------------------- build.gradle.kts | 3 -- .../common/base/theme/BaseThemeViewModel.kt | 4 +-- gradle/libs.versions.toml | 4 --- 4 files changed, 2 insertions(+), 41 deletions(-) diff --git a/base/src/main/kotlin/io/goooler/demoapp/base/util/BaseExtensions.kt b/base/src/main/kotlin/io/goooler/demoapp/base/util/BaseExtensions.kt index 473d65eb8..ba64cc335 100644 --- a/base/src/main/kotlin/io/goooler/demoapp/base/util/BaseExtensions.kt +++ b/base/src/main/kotlin/io/goooler/demoapp/base/util/BaseExtensions.kt @@ -40,8 +40,6 @@ import androidx.fragment.app.commit import androidx.fragment.app.findFragment import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleCoroutineScope -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.coroutineScope import androidx.lifecycle.findViewTreeLifecycleOwner import java.io.File @@ -62,34 +60,6 @@ import kotlinx.coroutines.withContext // ---------------------Types-------------------------------// -typealias BooleanLiveData = LiveData - -typealias IntLiveData = LiveData - -typealias LongLiveData = LiveData - -typealias DoubleLiveData = LiveData - -typealias FloatLiveData = LiveData - -typealias StringLiveData = LiveData - -typealias ListLiveData = LiveData> - -typealias MutableBooleanLiveData = MutableLiveData - -typealias MutableIntLiveData = MutableLiveData - -typealias MutableLongLiveData = MutableLiveData - -typealias MutableDoubleLiveData = MutableLiveData - -typealias MutableFloatLiveData = MutableLiveData - -typealias MutableStringLiveData = MutableLiveData - -typealias MutableListLiveData = MutableLiveData> - typealias ParamMap = HashMap // ---------------------Any-------------------------------// @@ -105,8 +75,6 @@ inline val isMainThread: Boolean get() = Looper.getMainLooper() == Looper.myLoop fun unsafeLazy(initializer: () -> T): Lazy = lazy(LazyThreadSafetyMode.NONE, initializer) -fun MutableLiveData.asLiveData(): LiveData = this - // ---------------------CharSequence-------------------------------// operator fun String.times(@IntRange(from = 0) num: Int): String { diff --git a/build.gradle.kts b/build.gradle.kts index 0308b6b2c..c1bcb1c65 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,9 +33,6 @@ allprojects { libs.androidX.collection.get().module.group -> useVersion(libs.versions.androidX.collection.get()) libs.androidX.core.get().module.group -> useVersion(libs.versions.androidX.core.get()) libs.androidX.fragment.get().module.group -> useVersion(libs.versions.androidX.fragment.get()) - libs.androidX.lifecycle.liveData.get().module.group -> { - if (requested.name != "lifecycle-extensions") useVersion(libs.versions.androidX.lifecycle.get()) - } libs.gradlePlugin.kotlin.get().module.group -> useVersion(libs.versions.kotlin.get()) libs.square.okHttp.logInterceptor.get().module.group -> useVersion(libs.versions.square.okHttp.get()) else -> when { diff --git a/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseThemeViewModel.kt b/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseThemeViewModel.kt index 414db27fe..515b7046c 100644 --- a/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseThemeViewModel.kt +++ b/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseThemeViewModel.kt @@ -1,12 +1,12 @@ package io.goooler.demoapp.common.base.theme import androidx.annotation.AnyThread +import androidx.lifecycle.MutableLiveData import io.goooler.demoapp.base.core.BaseViewModel -import io.goooler.demoapp.base.util.MutableBooleanLiveData abstract class BaseThemeViewModel : BaseViewModel(), ITheme { - val loading = MutableBooleanLiveData() + val loading = MutableLiveData() @AnyThread override fun showLoading() { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 455b07bdd..c5658010a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -42,7 +42,6 @@ androidX-compose-tooling = { module = "androidx.compose.ui:ui-tooling", version. androidX-compose-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "androidX-compose" } androidX-compose-material = { module = "androidx.compose.material:material", version.ref = "androidX-compose" } androidX-compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "androidX-compose" } -androidX-compose-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "androidX-compose" } androidX-compose-icons-core = { module = "androidx.compose.material:material-icons-core", version.ref = "androidX-compose" } androidX-compose-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "androidX-compose" } @@ -59,7 +58,6 @@ androidX-core = { module = "androidx.core:core-ktx", version.ref = "androidX-cor androidX-fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "androidX-fragment" } androidX-hilt = { module = "com.google.dagger:hilt-android", version.ref = "androidX-hilt" } androidX-hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "androidX-hilt" } -androidX-lifecycle-liveData = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "androidX-lifecycle" } androidX-lifecycle-service = { module = "androidx.lifecycle:lifecycle-service", version.ref = "androidX-lifecycle" } androidX-lifecycle-viewModel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidX-lifecycle" } androidX-paging = "androidx.paging:paging-runtime:3.1.1" @@ -109,13 +107,11 @@ androidX-compose = [ "androidX-compose-tooling-preview", "androidX-compose-material", "androidX-compose-foundation", - "androidX-compose-livedata", "androidX-compose-icons-core", "androidX-compose-icons-extended" ] androidX-lifecycle = [ "androidX-lifecycle-viewModel", - "androidX-lifecycle-liveData", "androidX-lifecycle-service" ] androidX-room = [ From b25216c1de093f89d0aebe634915cc31660c0e1b Mon Sep 17 00:00:00 2001 From: Goooler Date: Mon, 4 Apr 2022 16:41:44 +0800 Subject: [PATCH 5/9] Replace livedata in BaseThemeViewModel --- .../demoapp/common/base/theme/BaseThemeViewModel.kt | 10 ++++++---- .../io/goooler/demoapp/common/util/CommonExtensions.kt | 9 +++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseThemeViewModel.kt b/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseThemeViewModel.kt index 515b7046c..b5de37b76 100644 --- a/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseThemeViewModel.kt +++ b/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseThemeViewModel.kt @@ -1,20 +1,22 @@ package io.goooler.demoapp.common.base.theme import androidx.annotation.AnyThread -import androidx.lifecycle.MutableLiveData import io.goooler.demoapp.base.core.BaseViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow abstract class BaseThemeViewModel : BaseViewModel(), ITheme { - val loading = MutableLiveData() + private val _loading = MutableStateFlow(false) + val loading: StateFlow get() = _loading @AnyThread override fun showLoading() { - loading.postValue(true) + _loading.value = true } @AnyThread override fun hideLoading() { - loading.postValue(false) + _loading.value = false } } diff --git a/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt b/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt index 3c4a3d0cb..c72e5abda 100644 --- a/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt +++ b/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt @@ -24,6 +24,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelStoreOwner +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.AsyncDifferConfig import androidx.recyclerview.widget.DiffUtil import androidx.viewbinding.ViewBinding @@ -53,6 +54,8 @@ import java.util.Date import kotlin.math.absoluteValue import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch typealias DimensionUtil = SizeUtils typealias SpHelper = SPUtils @@ -276,8 +279,10 @@ inline fun V.getThemeViewModel(): L where V : LifecycleOwner, V : ViewModelStoreOwner, V : ITheme = lazy(LazyThreadSafetyMode.NONE) { ViewModelProvider(this)[VM::class.java].also { lifecycle.addObserver(it) - it.loading.observe(this) { show -> - if (show) showLoading() else hideLoading() + lifecycleScope.launch { + it.loading.collectLatest { show -> + if (show) showLoading() else hideLoading() + } } } } From 03d6947be220713484f640e9f1aa9c76c0defd40 Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 5 Apr 2022 23:37:06 +0800 Subject: [PATCH 6/9] Remove rxjava from app --- common/build.gradle.kts | 3 -- .../common/base/theme/BaseRxViewModel.kt | 20 ------------ .../demoapp/common/network/RetrofitHelper.kt | 7 ---- .../demoapp/common/util/CommonExtensions.kt | 21 ------------ gradle/libs.versions.toml | 1 - gradle/proguard-rules.pro | 2 -- .../goooler/demoapp/main/api/MainCommonApi.kt | 9 ------ .../main/repository/MainCommonRepository.kt | 7 ---- .../demoapp/main/vm/MainHomeViewModel.kt | 4 +-- obsolete/build.gradle.kts | 2 ++ .../obsolete/util/ObsoleteExtensions.kt | 32 +++++++++++++++++++ .../demoapp/obsolete/util/TestExtensions.kt | 11 ------- 12 files changed, 36 insertions(+), 83 deletions(-) delete mode 100644 common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseRxViewModel.kt create mode 100644 obsolete/src/main/kotlin/io/goooler/demoapp/obsolete/util/ObsoleteExtensions.kt delete mode 100644 obsolete/src/main/kotlin/io/goooler/demoapp/obsolete/util/TestExtensions.kt diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 287e223c7..e809ad404 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -36,8 +36,6 @@ dependencies { api(libs.androidX.collection) api(libs.utils) - api(libs.rxJava3.java) - api(libs.rxJava3.android) implementation(libs.bundles.androidX.room) kapt(libs.androidX.room.compiler) @@ -45,7 +43,6 @@ dependencies { implementation(libs.bundles.coil) implementation(libs.square.moshi) implementation(libs.square.retrofit.moshi) - implementation(libs.square.retrofit.rxJava3) debugImplementation(libs.chucker.debug) releaseImplementation(libs.chucker.release) diff --git a/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseRxViewModel.kt b/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseRxViewModel.kt deleted file mode 100644 index cf822f29a..000000000 --- a/common/src/main/kotlin/io/goooler/demoapp/common/base/theme/BaseRxViewModel.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.goooler.demoapp.common.base.theme - -import androidx.annotation.CallSuper -import androidx.lifecycle.LifecycleOwner -import io.reactivex.rxjava3.disposables.CompositeDisposable -import io.reactivex.rxjava3.disposables.Disposable - -abstract class BaseRxViewModel : BaseThemeViewModel() { - - private val compositeDisposable = CompositeDisposable() - - @CallSuper - override fun onDestroy(owner: LifecycleOwner) { - compositeDisposable.clear() - } - - protected fun Disposable.autoDispose() { - compositeDisposable.add(this) - } -} diff --git a/common/src/main/kotlin/io/goooler/demoapp/common/network/RetrofitHelper.kt b/common/src/main/kotlin/io/goooler/demoapp/common/network/RetrofitHelper.kt index 3c3b2f301..cfc778e75 100644 --- a/common/src/main/kotlin/io/goooler/demoapp/common/network/RetrofitHelper.kt +++ b/common/src/main/kotlin/io/goooler/demoapp/common/network/RetrofitHelper.kt @@ -13,8 +13,6 @@ import io.goooler.demoapp.common.util.AppUserInfoManager import io.goooler.demoapp.common.util.JsonUtil import okhttp3.OkHttpClient import retrofit2.Converter -import retrofit2.Retrofit -import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory import retrofit2.converter.moshi.MoshiConverterFactory @SuppressLint("StaticFieldLeak") @@ -31,11 +29,6 @@ object RetrofitHelper : BaseRetrofitHelper() { RouterManager.goLogin(CommonApplication.app, true) } - override fun Retrofit.Builder.addCallAdapterFactories(): Retrofit.Builder { - addCallAdapterFactory(RxJava3CallAdapterFactory.create()) - return this - } - override fun OkHttpClient.Builder.addInterceptors(): OkHttpClient.Builder { addInterceptor(HeaderInterceptor) addNetworkInterceptor(ChuckerInterceptor.Builder(context).build()) diff --git a/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt b/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt index c72e5abda..f4cfe87a3 100644 --- a/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt +++ b/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt @@ -43,10 +43,6 @@ import io.goooler.demoapp.common.CommonApplication import io.goooler.demoapp.common.base.theme.BaseThemeViewModel import io.goooler.demoapp.common.base.theme.ITheme import io.goooler.demoapp.common.type.SpKeys -import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers -import io.reactivex.rxjava3.core.Observable -import io.reactivex.rxjava3.core.Single -import io.reactivex.rxjava3.schedulers.Schedulers import java.lang.reflect.ParameterizedType import java.math.BigDecimal import java.util.Calendar @@ -185,23 +181,6 @@ fun Number.formatMoney(isYuan: Boolean = false, trans2W: Boolean = false, scale: } } -// ---------------------Rx-------------------------------// - -fun Single.subscribeOnIoThread(): Single = subscribeOn(Schedulers.io()) - -fun Single.observeOnMainThread(): Single = observeOn(AndroidSchedulers.mainThread()) - -fun Single.subscribeAndObserve(): Single = - subscribeOnIoThread().observeOnMainThread() - -fun Observable.subscribeOnIoThread(): Observable = subscribeOn(Schedulers.io()) - -fun Observable.observeOnMainThread(): Observable = - observeOn(AndroidSchedulers.mainThread()) - -fun Observable.subscribeAndObserve(): Observable = - subscribeOnIoThread().observeOnMainThread() - // ---------------------Res-------------------------------// fun @receiver:DrawableRes Int.getDrawable(): Drawable? = try { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c5658010a..aa9148f90 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -75,7 +75,6 @@ square-okHttp-LogInterceptor = { module = "com.squareup.okhttp3:logging-intercep square-retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "square-retrofit" } square-retrofit-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "square-retrofit" } square-retrofit-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "square-retrofit" } -square-retrofit-rxJava3 = { module = "com.squareup.retrofit2:adapter-rxjava3", version.ref = "square-retrofit" } google-accompanist-swipeRefresh = { module = "com.google.accompanist:accompanist-swiperefresh", version.ref = "accompanist" } google-accompanist-systemUiController = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" } diff --git a/gradle/proguard-rules.pro b/gradle/proguard-rules.pro index 925e19724..c937a7311 100644 --- a/gradle/proguard-rules.pro +++ b/gradle/proguard-rules.pro @@ -81,8 +81,6 @@ # Extra rules for R8 fullMode -keep,allowobfuscation,allowshrinking class io.goooler.demoapp.common.base.binding.BaseBindingActivity -keep,allowobfuscation,allowshrinking class * extends io.goooler.demoapp.common.base.binding.BaseBindingActivity --keep,allowobfuscation,allowshrinking class io.reactivex.rxjava3.core.Single --keep,allowobfuscation,allowshrinking class io.reactivex.rxjava3.core.Observable # TODO: Waiting for new retrofit release to remove these rules -keep,allowobfuscation,allowshrinking interface retrofit2.Call -keep,allowobfuscation,allowshrinking class retrofit2.Response diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt b/main/src/main/kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt index 3206d3645..b34e92066 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt @@ -2,21 +2,12 @@ package io.goooler.demoapp.main.api import io.goooler.demoapp.base.util.ParamMap import io.goooler.demoapp.main.bean.MainRepoListBean -import io.reactivex.rxjava3.core.Single import retrofit2.http.GET import retrofit2.http.Path -import retrofit2.http.Query import retrofit2.http.QueryMap interface MainCommonApi { - @GET("users/{user}/repos") - fun getRepoListWithRx( - @Path("user") user: String, - @Query("page") page: Int, - @Query("per_page") pageSize: Int - ): Single> - @GET("users/{user}/repos") suspend fun getRepoListWithCr( @Path("user") user: String, diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/repository/MainCommonRepository.kt b/main/src/main/kotlin/io/goooler/demoapp/main/repository/MainCommonRepository.kt index 2c609f05c..5c0eeac69 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/repository/MainCommonRepository.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/repository/MainCommonRepository.kt @@ -6,7 +6,6 @@ import io.goooler.demoapp.common.type.CommonConstants import io.goooler.demoapp.main.api.MainCommonApi import io.goooler.demoapp.main.bean.MainRepoListBean import io.goooler.demoapp.main.db.MainCommonDao -import io.reactivex.rxjava3.core.Single import javax.inject.Inject class MainCommonRepository @Inject constructor( @@ -26,12 +25,6 @@ class MainCommonRepository @Inject constructor( return api.getRepoListWithCr(user, params) } - fun getRepoListWithRx( - user: String, - @IntRange(from = 1) page: Int = 1, - @IntRange(from = 1) pageSize: Int = CommonConstants.DEFAULT_PAGE_SIZE - ): Single> = api.getRepoListWithRx(user, page, pageSize) - suspend fun getRepoListFromDb(ownerName: String): List = dao.getRepoList(ownerName) diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt index b61500348..cee078be5 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt @@ -3,7 +3,7 @@ package io.goooler.demoapp.main.vm import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import io.goooler.demoapp.base.util.defaultAsync -import io.goooler.demoapp.common.base.theme.BaseRxViewModel +import io.goooler.demoapp.common.base.theme.BaseThemeViewModel import io.goooler.demoapp.common.util.showToast import io.goooler.demoapp.main.bean.MainRepoListBean import io.goooler.demoapp.main.repository.MainCommonRepository @@ -25,7 +25,7 @@ import kotlinx.coroutines.launch @HiltViewModel class MainHomeViewModel @Inject constructor(private val repository: MainCommonRepository) : - BaseRxViewModel() { + BaseThemeViewModel() { private val _title = MutableStateFlow("") val title: StateFlow = _title diff --git a/obsolete/build.gradle.kts b/obsolete/build.gradle.kts index 11b98d605..381933e0f 100644 --- a/obsolete/build.gradle.kts +++ b/obsolete/build.gradle.kts @@ -13,4 +13,6 @@ dependencies { implementation(libs.fastjson) implementation(libs.google.gson) implementation(libs.bundles.glide) + implementation(libs.rxJava3.java) + implementation(libs.rxJava3.android) } diff --git a/obsolete/src/main/kotlin/io/goooler/demoapp/obsolete/util/ObsoleteExtensions.kt b/obsolete/src/main/kotlin/io/goooler/demoapp/obsolete/util/ObsoleteExtensions.kt new file mode 100644 index 000000000..e2d447815 --- /dev/null +++ b/obsolete/src/main/kotlin/io/goooler/demoapp/obsolete/util/ObsoleteExtensions.kt @@ -0,0 +1,32 @@ +package io.goooler.demoapp.obsolete.util + +import io.goooler.demoapp.common.network.HttpResponse +import io.goooler.demoapp.obsolete.network.exception.ResponseException +import io.goooler.demoapp.obsolete.network.exception.toResponseException +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.core.Observable +import io.reactivex.rxjava3.core.Single +import io.reactivex.rxjava3.schedulers.Schedulers + +@Throws(ResponseException::class) +fun HttpResponse.checkCodeWithException(): T? { + if (code != 200) throw (message ?: code.toString()).toResponseException() + return entry +} + +// ---------------------Rx-------------------------------// + +fun Single.subscribeOnIoThread(): Single = subscribeOn(Schedulers.io()) + +fun Single.observeOnMainThread(): Single = observeOn(AndroidSchedulers.mainThread()) + +fun Single.subscribeAndObserve(): Single = + subscribeOnIoThread().observeOnMainThread() + +fun Observable.subscribeOnIoThread(): Observable = subscribeOn(Schedulers.io()) + +fun Observable.observeOnMainThread(): Observable = + observeOn(AndroidSchedulers.mainThread()) + +fun Observable.subscribeAndObserve(): Observable = + subscribeOnIoThread().observeOnMainThread() diff --git a/obsolete/src/main/kotlin/io/goooler/demoapp/obsolete/util/TestExtensions.kt b/obsolete/src/main/kotlin/io/goooler/demoapp/obsolete/util/TestExtensions.kt deleted file mode 100644 index 96b3bf7f7..000000000 --- a/obsolete/src/main/kotlin/io/goooler/demoapp/obsolete/util/TestExtensions.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.goooler.demoapp.obsolete.util - -import io.goooler.demoapp.common.network.HttpResponse -import io.goooler.demoapp.obsolete.network.exception.ResponseException -import io.goooler.demoapp.obsolete.network.exception.toResponseException - -@Throws(ResponseException::class) -fun HttpResponse.checkCodeWithException(): T? { - if (code != 200) throw (message ?: code.toString()).toResponseException() - return entry -} From 863de9e239f4b14303c2d365bf20861a0aff0559 Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 5 Apr 2022 23:39:29 +0800 Subject: [PATCH 7/9] Rename functions --- .../kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt | 2 +- .../demoapp/main/repository/MainCommonRepository.kt | 4 ++-- .../io/goooler/demoapp/main/vm/MainHomeViewModel.kt | 8 ++++---- .../io/goooler/demoapp/main/vm/MainPagingViewModel.kt | 2 +- .../kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt b/main/src/main/kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt index b34e92066..d6d4901ac 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/api/MainCommonApi.kt @@ -9,7 +9,7 @@ import retrofit2.http.QueryMap interface MainCommonApi { @GET("users/{user}/repos") - suspend fun getRepoListWithCr( + suspend fun getRepoList( @Path("user") user: String, @QueryMap params: ParamMap ): List diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/repository/MainCommonRepository.kt b/main/src/main/kotlin/io/goooler/demoapp/main/repository/MainCommonRepository.kt index 5c0eeac69..73cd421bf 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/repository/MainCommonRepository.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/repository/MainCommonRepository.kt @@ -13,7 +13,7 @@ class MainCommonRepository @Inject constructor( private val dao: MainCommonDao ) { - suspend fun getRepoListWithCr( + suspend fun getRepoListFromApi( user: String, @IntRange(from = 1) page: Int = 1, @IntRange(from = 1) pageSize: Int = CommonConstants.DEFAULT_PAGE_SIZE @@ -22,7 +22,7 @@ class MainCommonRepository @Inject constructor( "page" to page, "per_page" to pageSize ) - return api.getRepoListWithCr(user, params) + return api.getRepoList(user, params) } suspend fun getRepoListFromDb(ownerName: String): List = diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt index cee078be5..cffd737ff 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt @@ -33,7 +33,7 @@ class MainHomeViewModel @Inject constructor(private val repository: MainCommonRe private var countdownJob: Job? = null fun initData() { - requestWithCr() + fetchRepoLists() } fun countDown() { @@ -71,7 +71,7 @@ class MainHomeViewModel @Inject constructor(private val repository: MainCommonRe } } - private fun requestWithCr() { + private fun fetchRepoLists() { viewModelScope.launch(Dispatchers.IO) { try { val google = defaultAsync { repository.getRepoListFromDb("google") } @@ -82,8 +82,8 @@ class MainHomeViewModel @Inject constructor(private val repository: MainCommonRe } try { - val google = defaultAsync { repository.getRepoListWithCr("google") } - val microsoft = defaultAsync { repository.getRepoListWithCr("microsoft") } + val google = defaultAsync { repository.getRepoListFromApi("google") } + val microsoft = defaultAsync { repository.getRepoListFromApi("microsoft") } processList(google.await(), microsoft.await()).collect(_title::emit) diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainPagingViewModel.kt b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainPagingViewModel.kt index f3141b86e..93b75e4a4 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainPagingViewModel.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainPagingViewModel.kt @@ -39,7 +39,7 @@ class MainPagingViewModel @Inject constructor(private val repository: MainCommon private inner class DataSource : BasePagingSource() { override suspend fun fetchListData(page: Int): List { - return repository.getRepoListWithCr("google", page, 30) + return repository.getRepoListFromApi("google", page, 30) .map { MainCommonVhModel.Repo(it.owner?.avatarUrl, it.name) } } } diff --git a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt index 0ca29091d..acc2a6765 100644 --- a/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt +++ b/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainSrlViewModel.kt @@ -55,7 +55,7 @@ class MainSrlViewModel @Inject constructor(private val repository: MainCommonRep viewModelScope.launch { try { finishRefreshAndLoadMore(false) - repository.getRepoListWithCr("goooler", page) + repository.getRepoListFromApi("goooler", page) .map { bean -> MainCommonVhModel.Repo(bean.owner?.avatarUrl, bean.name, bean.fullName) }.let { From ed201e5f63e3660d8bf2b1441190a7b65b34300b Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 5 Apr 2022 23:39:29 +0800 Subject: [PATCH 8/9] BaseViewModel no longer to extends DefaultLifecycleObserver --- .../kotlin/io/goooler/demoapp/base/core/BaseViewModel.kt | 3 +-- .../io/goooler/demoapp/common/util/CommonExtensions.kt | 8 -------- .../io/goooler/demoapp/detail/ui/RepoDetailActivity.kt | 4 ++-- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/base/src/main/kotlin/io/goooler/demoapp/base/core/BaseViewModel.kt b/base/src/main/kotlin/io/goooler/demoapp/base/core/BaseViewModel.kt index bb7d37edc..314a0a711 100644 --- a/base/src/main/kotlin/io/goooler/demoapp/base/core/BaseViewModel.kt +++ b/base/src/main/kotlin/io/goooler/demoapp/base/core/BaseViewModel.kt @@ -1,6 +1,5 @@ package io.goooler.demoapp.base.core -import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.ViewModel -abstract class BaseViewModel : ViewModel(), DefaultLifecycleObserver +abstract class BaseViewModel : ViewModel() diff --git a/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt b/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt index d523b6640..32c9cff4f 100644 --- a/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt +++ b/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt @@ -35,7 +35,6 @@ import com.blankj.utilcode.util.StringUtils import com.blankj.utilcode.util.TimeUtils import com.google.android.material.textfield.TextInputLayout import com.scwang.smart.refresh.layout.SmartRefreshLayout -import io.goooler.demoapp.base.core.BaseViewModel import io.goooler.demoapp.base.util.ToastUtil import io.goooler.demoapp.common.BuildConfig import io.goooler.demoapp.common.CommonApplication @@ -249,17 +248,10 @@ inline fun DiffUtil.ItemCallback.asConfig(): AsyncDifferConfig // ---------------------Fragment-------------------------------// -@MainThread -inline fun V.baseViewModels(): Lazy - where V : LifecycleOwner, V : ViewModelStoreOwner = lazy(LazyThreadSafetyMode.NONE) { - ViewModelProvider(this)[VM::class.java].apply(lifecycle::addObserver) -} - @MainThread inline fun V.themeViewModels(): Lazy where V : LifecycleOwner, V : ViewModelStoreOwner, V : ITheme = lazy(LazyThreadSafetyMode.NONE) { ViewModelProvider(this)[VM::class.java].also { - lifecycle.addObserver(it) lifecycleScope.launch { it.loading.collectLatest { show -> if (show) showLoading() else hideLoading() diff --git a/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt b/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt index 95bd3d216..df984216f 100644 --- a/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt +++ b/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt @@ -2,15 +2,15 @@ package io.goooler.demoapp.detail.ui import android.os.Bundle import androidx.activity.compose.setContent +import androidx.activity.viewModels import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import io.goooler.demoapp.base.core.BaseActivity -import io.goooler.demoapp.common.util.baseViewModels import io.goooler.demoapp.detail.vm.DetailViewModel class RepoDetailActivity : BaseActivity() { - private val vm: DetailViewModel by baseViewModels() + private val vm: DetailViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) From 822ef6c7b9d9573b656cfb9b6267bd6f6bac46e6 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 9 Apr 2022 01:39:38 +0800 Subject: [PATCH 9/9] Import SizeUtils --- .../kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt b/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt index d972dfdbb..e6c8a7346 100644 --- a/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt +++ b/common/src/main/kotlin/io/goooler/demoapp/common/util/CommonExtensions.kt @@ -29,6 +29,7 @@ import com.blankj.utilcode.util.ColorUtils import com.blankj.utilcode.util.ImageUtils import com.blankj.utilcode.util.ResourceUtils import com.blankj.utilcode.util.SPUtils +import com.blankj.utilcode.util.SizeUtils import com.blankj.utilcode.util.StringUtils import com.google.android.material.textfield.TextInputLayout import com.scwang.smart.refresh.layout.SmartRefreshLayout