Replace MessageActivity's AsyncTasks with Coroutines

This commit is contained in:
Niko Diamadis
2022-12-29 20:13:27 +01:00
parent 6aeb21ebc3
commit c32d6a81bd

View File

@@ -6,7 +6,6 @@ import android.graphics.Canvas
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.os.AsyncTask
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
@@ -31,6 +30,7 @@ import com.github.gotify.BuildConfig
import com.github.gotify.MissedMessageUtil import com.github.gotify.MissedMessageUtil
import com.github.gotify.R import com.github.gotify.R
import com.github.gotify.Utils import com.github.gotify.Utils
import com.github.gotify.Utils.launchCoroutine
import com.github.gotify.api.Api import com.github.gotify.api.Api
import com.github.gotify.api.ApiException import com.github.gotify.api.ApiException
import com.github.gotify.api.Callback import com.github.gotify.api.Callback
@@ -56,6 +56,8 @@ import com.google.android.material.navigation.NavigationView
import com.google.android.material.snackbar.BaseTransientBottomBar.BaseCallback import com.google.android.material.snackbar.BaseTransientBottomBar.BaseCallback
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import java.io.IOException import java.io.IOException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
internal class MessagesActivity : internal class MessagesActivity :
AppCompatActivity(), AppCompatActivity(),
@@ -74,7 +76,9 @@ internal class MessagesActivity :
messageJson, messageJson,
Message::class.java Message::class.java
) )
NewSingleMessage().execute(message) launchCoroutine {
addSingleMessage(message)
}
} }
} }
@@ -126,8 +130,10 @@ internal class MessagesActivity :
override fun onDrawerClosed(drawerView: View) { override fun onDrawerClosed(drawerView: View) {
if (updateAppOnDrawerClose != null) { if (updateAppOnDrawerClose != null) {
viewModel.appId = updateAppOnDrawerClose!! viewModel.appId = updateAppOnDrawerClose!!
UpdateMessagesForApplication(true).execute(updateAppOnDrawerClose) launchCoroutine {
updateMessagesForApplication(true, updateAppOnDrawerClose!!)
updateAppOnDrawerClose = null updateAppOnDrawerClose = null
}
invalidateOptionsMenu() invalidateOptionsMenu()
} }
} }
@@ -143,7 +149,9 @@ internal class MessagesActivity :
swipeRefreshLayout.isEnabled = true swipeRefreshLayout.isEnabled = true
} }
} }
UpdateMessagesForApplication(true).execute(viewModel.appId) launchCoroutine {
updateMessagesForApplication(true, viewModel.appId)
}
} }
override fun onPostCreate(savedInstanceState: Bundle?) { override fun onPostCreate(savedInstanceState: Bundle?) {
@@ -167,7 +175,9 @@ internal class MessagesActivity :
private fun onRefresh() { private fun onRefresh() {
viewModel.messages.clear() viewModel.messages.clear()
LoadMore().execute(viewModel.appId) launchCoroutine {
loadMore(viewModel.appId)
}
} }
private fun openDocumentation() { private fun openDocumentation() {
@@ -175,10 +185,6 @@ internal class MessagesActivity :
startActivity(browserIntent) startActivity(browserIntent)
} }
fun commitDelete() {
CommitDeleteMessage().execute()
}
private fun onUpdateApps(applications: List<Application>) { private fun onUpdateApps(applications: List<Application>) {
val menu: Menu = binding.navView.menu val menu: Menu = binding.navView.menu
menu.removeGroup(R.id.apps) menu.removeGroup(R.id.apps)
@@ -283,7 +289,9 @@ internal class MessagesActivity :
private fun doLogout() { private fun doLogout() {
setContentView(R.layout.splash) setContentView(R.layout.splash)
DeleteClientAndNavigateToLogin().execute() launchCoroutine {
deleteClientAndNavigateToLogin()
}
} }
private fun startLoading() { private fun startLoading() {
@@ -303,7 +311,9 @@ internal class MessagesActivity :
val filter = IntentFilter() val filter = IntentFilter()
filter.addAction(NEW_MESSAGE_BROADCAST) filter.addAction(NEW_MESSAGE_BROADCAST)
registerReceiver(receiver, filter) registerReceiver(receiver, filter)
UpdateMissedMessages().execute(viewModel.messages.getLastReceivedMessage()) launchCoroutine {
updateMissedMessages(viewModel.messages.getLastReceivedMessage())
}
var selectedIndex: Int = R.id.nav_all_messages var selectedIndex: Int = R.id.nav_all_messages
val appId = viewModel.appId val appId = viewModel.appId
if (appId != MessageState.ALL_MESSAGES) { if (appId != MessageState.ALL_MESSAGES) {
@@ -372,7 +382,9 @@ internal class MessagesActivity :
// deletion to be sent to the server twice, since the deletion is sent to the server // deletion to be sent to the server twice, since the deletion is sent to the server
// in MessageFacade if a message is deleted while another message was already // in MessageFacade if a message is deleted while another message was already
// waiting for deletion. // waiting for deletion.
commitDelete() launchCoroutine {
commitDeleteMessage()
}
} }
} }
} }
@@ -474,32 +486,24 @@ internal class MessagesActivity :
) { ) {
if (!isLoadMore) { if (!isLoadMore) {
isLoadMore = true isLoadMore = true
LoadMore().execute(viewModel.appId) launchCoroutine {
loadMore(viewModel.appId)
}
} }
} }
} }
} }
} }
private inner class UpdateMissedMessages : AsyncTask<Long?, Void?, Boolean>() { private suspend fun updateMissedMessages(id: Long) {
override fun doInBackground(vararg ids: Long?): Boolean { if (id == -1L) return
val id = ids.first()!!
if (id == -1L) { val newMessages = MissedMessageUtil(viewModel.client.createService(MessageApi::class.java))
return false .missingMessages(id).filterNotNull()
}
val newMessages = MissedMessageUtil(
viewModel.client.createService(
MessageApi::class.java
)
).missingMessages(id).filterNotNull()
viewModel.messages.addMessages(newMessages) viewModel.messages.addMessages(newMessages)
return newMessages.isNotEmpty()
}
override fun onPostExecute(update: Boolean) { if (newMessages.isNotEmpty()) {
if (update) { updateMessagesForApplication(true, viewModel.appId)
UpdateMessagesForApplication(true).execute(viewModel.appId)
}
} }
} }
@@ -512,7 +516,9 @@ internal class MessagesActivity :
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.action_delete_all) { if (item.itemId == R.id.action_delete_all) {
DeleteMessages().execute(viewModel.appId) launchCoroutine {
deleteMessages(viewModel.appId)
}
} }
if (item.itemId == R.id.action_delete_app) { if (item.itemId == R.id.action_delete_app) {
val alert = android.app.AlertDialog.Builder(this) val alert = android.app.AlertDialog.Builder(this)
@@ -544,80 +550,50 @@ internal class MessagesActivity :
}) })
} }
private inner class LoadMore : AsyncTask<Long?, Void?, List<MessageWithImage>>() { private suspend fun loadMore(appId: Long) {
override fun doInBackground(vararg appId: Long?): List<MessageWithImage> { val messagesWithImages = viewModel.messages.loadMore(appId)
return viewModel.messages.loadMore(appId.first()!!) withContext(Dispatchers.Main) {
} updateMessagesAndStopLoading(messagesWithImages)
override fun onPostExecute(messageWithImages: List<MessageWithImage>) {
updateMessagesAndStopLoading(messageWithImages)
} }
} }
private inner class UpdateMessagesForApplication(withLoadingSpinner: Boolean) : private suspend fun updateMessagesForApplication(withLoadingSpinner: Boolean, appId: Long) {
AsyncTask<Long?, Void?, Long>() {
init {
if (withLoadingSpinner) { if (withLoadingSpinner) {
withContext(Dispatchers.Main) {
startLoading() startLoading()
} }
} }
override fun doInBackground(vararg appIds: Long?): Long {
val appId = appIds.first()!!
viewModel.messages.loadMoreIfNotPresent(appId) viewModel.messages.loadMoreIfNotPresent(appId)
return appId withContext(Dispatchers.Main) {
}
override fun onPostExecute(appId: Long) {
updateMessagesAndStopLoading(viewModel.messages[appId]) updateMessagesAndStopLoading(viewModel.messages[appId])
} }
} }
private inner class NewSingleMessage : AsyncTask<Message?, Void?, Void?>() { private suspend fun addSingleMessage(message: Message) {
override fun doInBackground(vararg newMessages: Message?): Void? { viewModel.messages.addMessages(listOf(message))
viewModel.messages.addMessages(listOfNotNull(*newMessages)) updateMessagesForApplication(false, viewModel.appId)
return null
} }
override fun onPostExecute(data: Void?) { private suspend fun commitDeleteMessage() {
UpdateMessagesForApplication(false).execute(viewModel.appId)
}
}
private inner class CommitDeleteMessage : AsyncTask<Void?, Void?, Void?>() {
override fun doInBackground(vararg messages: Void?): Void? {
viewModel.messages.commitDelete() viewModel.messages.commitDelete()
return null updateMessagesForApplication(false, viewModel.appId)
} }
override fun onPostExecute(data: Void?) { private suspend fun deleteMessages(appId: Long) {
UpdateMessagesForApplication(false).execute(viewModel.appId) withContext(Dispatchers.Main) {
}
}
private inner class DeleteMessages : AsyncTask<Long?, Void?, Boolean>() {
init {
startLoading() startLoading()
} }
val success = viewModel.messages.deleteAll(appId)
override fun doInBackground(vararg appId: Long?): Boolean { if (success) {
return viewModel.messages.deleteAll(appId.first()!!) updateMessagesForApplication(false, viewModel.appId)
} } else {
override fun onPostExecute(success: Boolean) {
if (!success) {
Utils.showSnackBar(this@MessagesActivity, "Delete failed :(") Utils.showSnackBar(this@MessagesActivity, "Delete failed :(")
} }
UpdateMessagesForApplication(false).execute(viewModel.appId)
}
} }
private inner class DeleteClientAndNavigateToLogin : AsyncTask<Void?, Void?, Void?>() { private fun deleteClientAndNavigateToLogin() {
override fun doInBackground(vararg ignore: Void?): Void? {
val settings = viewModel.settings val settings = viewModel.settings
val api = ClientFactory.clientToken( val api = ClientFactory.clientToken(settings.url, settings.sslSettings(), settings.token)
settings.url, settings.sslSettings(), settings.token
)
.createService(ClientApi::class.java) .createService(ClientApi::class.java)
stopService(Intent(this@MessagesActivity, WebSocketService::class.java)) stopService(Intent(this@MessagesActivity, WebSocketService::class.java))
try { try {
@@ -638,15 +614,10 @@ internal class MessagesActivity :
} catch (e: ApiException) { } catch (e: ApiException) {
Log.e("Could not delete client", e) Log.e("Could not delete client", e)
} }
return null
}
override fun onPostExecute(aVoid: Void?) {
viewModel.settings.clear() viewModel.settings.clear()
startActivity(Intent(this@MessagesActivity, LoginActivity::class.java)) startActivity(Intent(this@MessagesActivity, LoginActivity::class.java))
finish() finish()
super.onPostExecute(aVoid)
}
} }
private fun updateMessagesAndStopLoading(messageWithImages: List<MessageWithImage>) { private fun updateMessagesAndStopLoading(messageWithImages: List<MessageWithImage>) {