From bb4a820c3159e2dc5537d143ab3bbe48a07d6858 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 28 Oct 2021 19:19:59 +0200 Subject: [PATCH] Flow migration: update after PR reviews --- docs/rx_flow_migration.md | 41 +++++++++++++++++++ .../matrix/android/sdk/flow/FlowSession.kt | 7 ++-- .../java/im/vector/app/VectorApplication.kt | 3 -- .../java/im/vector/app/core/rx/RxConfig.kt | 28 ------------- .../app/features/home/HomeDetailViewModel.kt | 4 +- .../app/features/home/ShortcutsHandler.kt | 5 +-- .../home/UnreadMessagesSharedViewModel.kt | 6 +-- .../quads/SharedSecureStorageViewModelTest.kt | 4 -- .../java/im/vector/app/test/InstantRxRule.kt | 32 --------------- 9 files changed, 52 insertions(+), 78 deletions(-) create mode 100644 docs/rx_flow_migration.md delete mode 100644 vector/src/main/java/im/vector/app/core/rx/RxConfig.kt delete mode 100644 vector/src/test/java/im/vector/app/test/InstantRxRule.kt diff --git a/docs/rx_flow_migration.md b/docs/rx_flow_migration.md new file mode 100644 index 0000000000..a438b0f6fb --- /dev/null +++ b/docs/rx_flow_migration.md @@ -0,0 +1,41 @@ +Useful links: +- https://github.com/ReactiveCircus/FlowBinding +- https://ivanisidrowu.github.io/kotlin/2020/08/09/Kotlin-Flow-Migration-And-Testing.html + + +Rx is now completely removed from Element dependencies. +Some examples of the changes: + +``` + sharedActionViewModel + .observe() + .subscribe { handleQuickActions(it) } + .disposeOnDestroyView() + ``` + +became + + ``` + sharedActionViewModel + .stream() + .onEach { handleQuickActions(it) } + .launchIn(viewLifecycleOwner.lifecycleScope) + +``` + +Inside fragment use +``` +launchIn(viewLifecycleOwner.lifecycleScope) +``` +Inside activity use +``` +launchIn(lifecycleScope) +``` +Inside viewModel use +``` +launchIn(viewModelScope) +``` + +Also be aware that when using these scopes the coroutine is launched on Dispatchers.Main by default. + + diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt index 13fd097bcd..2a0abd3d24 100644 --- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt +++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt @@ -27,6 +27,7 @@ import org.matrix.android.sdk.api.session.group.GroupSummaryQueryParams import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.pushers.Pusher +import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState @@ -44,10 +45,10 @@ import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo class FlowSession(private val session: Session) { - fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Flow> { - return session.getRoomSummariesLive(queryParams).asFlow() + fun liveRoomSummaries(queryParams: RoomSummaryQueryParams, sortOrder: RoomSortOrder = RoomSortOrder.NONE): Flow> { + return session.getRoomSummariesLive(queryParams, sortOrder).asFlow() .startWith(session.coroutineDispatchers.io) { - session.getRoomSummaries(queryParams) + session.getRoomSummaries(queryParams, sortOrder) } } diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index d9027231da..80b397231b 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -43,7 +43,6 @@ import dagger.hilt.android.HiltAndroidApp import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.extensions.startSyncing -import im.vector.app.core.rx.RxConfig import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.configuration.VectorConfiguration import im.vector.app.features.disclaimer.doNotShowDisclaimerDialog @@ -93,7 +92,6 @@ class VectorApplication : @Inject lateinit var versionProvider: VersionProvider @Inject lateinit var notificationUtils: NotificationUtils @Inject lateinit var appStateHandler: AppStateHandler - @Inject lateinit var rxConfig: RxConfig @Inject lateinit var popupAlertManager: PopupAlertManager @Inject lateinit var pinLocker: PinLocker @Inject lateinit var callManager: WebRtcCallManager @@ -118,7 +116,6 @@ class VectorApplication : appContext = this invitesAcceptor.initialize() vectorUncaughtExceptionHandler.activate(this) - rxConfig.setupRxPlugin() // Remove Log handler statically added by Jitsi Timber.forest() diff --git a/vector/src/main/java/im/vector/app/core/rx/RxConfig.kt b/vector/src/main/java/im/vector/app/core/rx/RxConfig.kt deleted file mode 100644 index 066839319e..0000000000 --- a/vector/src/main/java/im/vector/app/core/rx/RxConfig.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2019 New Vector Ltd - * - * 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 im.vector.app.core.rx - -import javax.inject.Inject - -class RxConfig @Inject constructor() { - - /** - * Make sure unhandled Rx error does not crash the app in production - */ - fun setupRxPlugin() { - } -} diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt index b110005c31..1c1d012cc8 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt @@ -27,6 +27,7 @@ import im.vector.app.RoomGroupingMethod import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.extensions.singletonEntryPoint +import im.vector.app.core.flow.throttleFirst import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.call.dialpad.DialPadLookup import im.vector.app.features.call.lookup.CallProtocolsChecker @@ -43,7 +44,6 @@ import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.sample import kotlinx.coroutines.launch import org.matrix.android.sdk.api.query.ActiveSpaceFilter import org.matrix.android.sdk.api.query.RoomCategoryFilter @@ -214,7 +214,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho sortOrder = RoomSortOrder.NONE ).asFlow() } - .sample(300) + .throttleFirst(300) .onEach { when (val groupingMethod = appStateHandler.getCurrentRoomGroupingMethod()) { is RoomGroupingMethod.ByLegacyGroup -> { diff --git a/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt index a1848cad31..a84a721a31 100644 --- a/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt +++ b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt @@ -21,7 +21,6 @@ import android.content.pm.ShortcutManager import android.os.Build import androidx.core.content.getSystemService import androidx.core.content.pm.ShortcutManagerCompat -import androidx.lifecycle.asFlow import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.features.pin.PinCodeStore @@ -37,6 +36,7 @@ import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams +import org.matrix.android.sdk.flow.flow import timber.log.Timber import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject @@ -61,13 +61,12 @@ class ShortcutsHandler @Inject constructor( } hasPinCode.set(pinCodeStore.getEncodedPin() != null) val session = activeSessionHolder.getSafeActiveSession() ?: return Job() - return session.getRoomSummariesLive( + return session.flow().liveRoomSummaries( roomSummaryQueryParams { memberships = listOf(Membership.JOIN) }, sortOrder = RoomSortOrder.PRIORITY_AND_ACTIVITY ) - .asFlow() .onStart { pinCodeStore.addListener(this@ShortcutsHandler) } .onCompletion { pinCodeStore.removeListener(this@ShortcutsHandler) } .onEach { rooms -> diff --git a/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt index 7091dc3f00..6c0ae71cfa 100644 --- a/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt @@ -26,6 +26,7 @@ import im.vector.app.AppStateHandler import im.vector.app.RoomGroupingMethod import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory +import im.vector.app.core.flow.throttleFirst import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -36,7 +37,6 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.sample import org.matrix.android.sdk.api.query.ActiveSpaceFilter import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.room.RoomSortOrder @@ -79,7 +79,7 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initia this.activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(null) }, sortOrder = RoomSortOrder.NONE ).asFlow() - .sample(300) + .throttleFirst(300) .execute { val counts = session.getNotificationCountForRooms( roomSummaryQueryParams { @@ -114,7 +114,7 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initia this.memberships = Membership.activeMemberships() }, sortOrder = RoomSortOrder.NONE ).asFlow() - .sample(300) + .throttleFirst(300) } ) { groupingMethod, _ -> when (groupingMethod.orNull()) { diff --git a/vector/src/test/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModelTest.kt b/vector/src/test/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModelTest.kt index 00828acbb8..ea9335aaff 100644 --- a/vector/src/test/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModelTest.kt @@ -18,7 +18,6 @@ package im.vector.app.features.crypto.quads import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.test.MvRxTestRule -import im.vector.app.test.InstantRxRule import im.vector.app.test.fakes.FakeSession import im.vector.app.test.fakes.FakeStringProvider import im.vector.app.test.test @@ -40,9 +39,6 @@ private val KEY_INFO_WITHOUT_PASSPHRASE = KeyInfo(id = "id", content = SecretSto class SharedSecureStorageViewModelTest { - @get:Rule - val instantRx = InstantRxRule() - @get:Rule val mvrxTestRule = MvRxTestRule() diff --git a/vector/src/test/java/im/vector/app/test/InstantRxRule.kt b/vector/src/test/java/im/vector/app/test/InstantRxRule.kt deleted file mode 100644 index 1145cb7dd1..0000000000 --- a/vector/src/test/java/im/vector/app/test/InstantRxRule.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2021 New Vector Ltd - * - * 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 im.vector.app.test - -import io.reactivex.android.plugins.RxAndroidPlugins -import io.reactivex.plugins.RxJavaPlugins -import io.reactivex.schedulers.Schedulers -import org.junit.rules.TestRule -import org.junit.runner.Description -import org.junit.runners.model.Statement - -class InstantRxRule : TestRule { - override fun apply(base: Statement, description: Description?): Statement { - RxJavaPlugins.setInitNewThreadSchedulerHandler { Schedulers.trampoline() } - RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() } - return base - } -}