From ffc0528605019fafe1faced38d19144cd1c7899f Mon Sep 17 00:00:00 2001 From: ardevd Date: Fri, 1 Nov 2024 14:50:48 +0000 Subject: [PATCH 1/2] refactor(ui): coroutine based user status retrieval. Replaced ancient async task with a coroutine based alternative. This comes with numerous advantages. - Improved performance due to the nature of coroutines and the reduced overhead associated with AsyncTasks and threads. Approx a %50 performance increase was measured during testing. - Passing references to fragment lifecycle context to an AsyncTask is generally a bad idea. --- .../ui/ChooseAccountDialogFragment.kt | 18 +++++- .../java/com/nextcloud/ui/RetrieveStatus.kt | 38 +++++++++++ .../asynctasks/RetrieveStatusAsyncTask.java | 63 ------------------- 3 files changed, 54 insertions(+), 65 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt delete mode 100644 app/src/main/java/com/owncloud/android/ui/asynctasks/RetrieveStatusAsyncTask.java diff --git a/app/src/main/java/com/nextcloud/ui/ChooseAccountDialogFragment.kt b/app/src/main/java/com/nextcloud/ui/ChooseAccountDialogFragment.kt index 27e3fc4276..422af471ad 100644 --- a/app/src/main/java/com/nextcloud/ui/ChooseAccountDialogFragment.kt +++ b/app/src/main/java/com/nextcloud/ui/ChooseAccountDialogFragment.kt @@ -18,6 +18,7 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.client.account.User import com.nextcloud.client.account.UserAccountManager @@ -33,10 +34,12 @@ import com.owncloud.android.ui.activity.BaseActivity import com.owncloud.android.ui.activity.DrawerActivity import com.owncloud.android.ui.adapter.UserListAdapter import com.owncloud.android.ui.adapter.UserListItem -import com.owncloud.android.ui.asynctasks.RetrieveStatusAsyncTask import com.owncloud.android.utils.DisplayUtils import com.owncloud.android.utils.DisplayUtils.AvatarGenerationListener import com.owncloud.android.utils.theme.ViewThemeUtils +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import javax.inject.Inject private const val ARG_CURRENT_USER_PARAM = "currentUser" @@ -151,12 +154,23 @@ class ChooseAccountDialogFragment : binding.statusView.visibility = View.VISIBLE } - RetrieveStatusAsyncTask(user, this, clientFactory).execute() + loadAndSetUserStatus(user) } themeViews() } + private fun loadAndSetUserStatus(user: User) { + viewLifecycleOwner.lifecycleScope.launch { + val status = retrieveUserStatus(user, clientFactory) + + if (isAdded && !isDetached) { + val context = requireContext() + setStatus(status, context) + } + } + } + private fun themeViews() { viewThemeUtils.platform.themeDialogDivider(binding.separatorLine) viewThemeUtils.platform.themeDialog(binding.root) diff --git a/app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt b/app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt new file mode 100644 index 0000000000..f02d8d632a --- /dev/null +++ b/app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt @@ -0,0 +1,38 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Edvard Holst + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.ui + +import com.nextcloud.client.network.ClientFactory +import com.nextcloud.client.account.User +import com.owncloud.android.lib.resources.users.GetStatusRemoteOperation +import com.owncloud.android.lib.resources.users.Status +import com.owncloud.android.lib.resources.users.StatusType +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.io.IOException + +suspend fun retrieveUserStatus(user: User, clientFactory: ClientFactory): Status { + return withContext(Dispatchers.IO) { + try { + val client = clientFactory.createNextcloudClient(user) + val result = GetStatusRemoteOperation().execute(client) + if (result.isSuccess && result.resultData is Status) { + result.resultData as Status + } else { + offlineStatus() + } + } catch (e: ClientFactory.CreationException) { + offlineStatus() + } catch (e: IOException) { + offlineStatus() + } + } +} + + +private fun offlineStatus() = Status(StatusType.OFFLINE, "", "", -1) \ No newline at end of file diff --git a/app/src/main/java/com/owncloud/android/ui/asynctasks/RetrieveStatusAsyncTask.java b/app/src/main/java/com/owncloud/android/ui/asynctasks/RetrieveStatusAsyncTask.java deleted file mode 100644 index d19238ca0c..0000000000 --- a/app/src/main/java/com/owncloud/android/ui/asynctasks/RetrieveStatusAsyncTask.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2020 Tobias Kaminsky - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only - */ -package com.owncloud.android.ui.asynctasks; - -import android.os.AsyncTask; - -import com.nextcloud.client.account.User; -import com.nextcloud.client.network.ClientFactory; -import com.nextcloud.common.NextcloudClient; -import com.nextcloud.ui.ChooseAccountDialogFragment; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.resources.users.GetStatusRemoteOperation; -import com.owncloud.android.lib.resources.users.Status; -import com.owncloud.android.lib.resources.users.StatusType; - -import java.lang.ref.WeakReference; - -import androidx.lifecycle.Lifecycle; - -public class RetrieveStatusAsyncTask extends AsyncTask { - private final User user; - private final WeakReference chooseAccountDialogFragment; - private final ClientFactory clientFactory; - - public RetrieveStatusAsyncTask(User user, - ChooseAccountDialogFragment chooseAccountDialogFragment, - ClientFactory clientFactory) { - this.user = user; - this.chooseAccountDialogFragment = new WeakReference<>(chooseAccountDialogFragment); - this.clientFactory = clientFactory; - } - - @Override - protected com.owncloud.android.lib.resources.users.Status doInBackground(Void... voids) { - try { - NextcloudClient client = clientFactory.createNextcloudClient(user); - RemoteOperationResult result = - new GetStatusRemoteOperation().execute(client); - - if (result.isSuccess()) { - return result.getResultData(); - } else { - return new com.owncloud.android.lib.resources.users.Status(StatusType.OFFLINE, "", "", -1); - } - } catch (ClientFactory.CreationException | NullPointerException e) { - return new com.owncloud.android.lib.resources.users.Status(StatusType.OFFLINE, "", "", -1); - } - } - - @Override - protected void onPostExecute(com.owncloud.android.lib.resources.users.Status status) { - ChooseAccountDialogFragment fragment = chooseAccountDialogFragment.get(); - - if (fragment != null && fragment.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) { - fragment.setStatus(status, fragment.requireContext()); - } - } -} From 4f0c892eeabeb672ac1d15c17ca81defb14be7ff Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 5 Nov 2024 08:26:11 +0100 Subject: [PATCH 2/2] kotlin check codacy Signed-off-by: tobiasKaminsky --- .../java/com/nextcloud/ui/ChooseAccountDialogFragment.kt | 2 -- app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/nextcloud/ui/ChooseAccountDialogFragment.kt b/app/src/main/java/com/nextcloud/ui/ChooseAccountDialogFragment.kt index 422af471ad..920c595398 100644 --- a/app/src/main/java/com/nextcloud/ui/ChooseAccountDialogFragment.kt +++ b/app/src/main/java/com/nextcloud/ui/ChooseAccountDialogFragment.kt @@ -37,9 +37,7 @@ import com.owncloud.android.ui.adapter.UserListItem import com.owncloud.android.utils.DisplayUtils import com.owncloud.android.utils.DisplayUtils.AvatarGenerationListener import com.owncloud.android.utils.theme.ViewThemeUtils -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import javax.inject.Inject private const val ARG_CURRENT_USER_PARAM = "currentUser" diff --git a/app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt b/app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt index f02d8d632a..c545e4d182 100644 --- a/app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt +++ b/app/src/main/java/com/nextcloud/ui/RetrieveStatus.kt @@ -7,8 +7,8 @@ package com.nextcloud.ui -import com.nextcloud.client.network.ClientFactory import com.nextcloud.client.account.User +import com.nextcloud.client.network.ClientFactory import com.owncloud.android.lib.resources.users.GetStatusRemoteOperation import com.owncloud.android.lib.resources.users.Status import com.owncloud.android.lib.resources.users.StatusType @@ -34,5 +34,4 @@ suspend fun retrieveUserStatus(user: User, clientFactory: ClientFactory): Status } } - -private fun offlineStatus() = Status(StatusType.OFFLINE, "", "", -1) \ No newline at end of file +private fun offlineStatus() = Status(StatusType.OFFLINE, "", "", -1)