Use coroutines instead of threads

This commit is contained in:
2020-09-01 21:13:08 +02:00
committed by Matte23
parent c96ab593b0
commit c47ee95780
3 changed files with 102 additions and 90 deletions

View File

@@ -19,6 +19,8 @@
package net.underdesk.circolapp.server package net.underdesk.circolapp.server
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.underdesk.circolapp.data.Circular import net.underdesk.circolapp.data.Circular
import net.underdesk.circolapp.server.pojo.Response import net.underdesk.circolapp.server.pojo.Response
import org.jsoup.Jsoup import org.jsoup.Jsoup
@@ -34,49 +36,53 @@ class DataFetcher {
} }
@Throws(IOException::class) @Throws(IOException::class)
fun getCircularsFromServer(): List<Circular> { suspend fun getCircularsFromServer(): List<Circular> {
val json = gson.fromJson(retrieveDataFromServer(), Response::class.java) return withContext(Dispatchers.Default) {
val json = gson.fromJson(retrieveDataFromServer(), Response::class.java)
val document = Jsoup.parseBodyFragment(json.content!!.rendered) val document = Jsoup.parseBodyFragment(json.content!!.rendered)
val htmlList = document.getElementsByTag("ul")[0].getElementsByTag("a") val htmlList = document.getElementsByTag("ul")[0].getElementsByTag("a")
val list = ArrayList<Circular>() val list = ArrayList<Circular>()
htmlList.forEach { element -> htmlList.forEach { element ->
if (element.parents().size == 6) { if (element.parents().size == 6) {
list.last().attachmentsNames.add(element.text()) list.last().attachmentsNames.add(element.text())
list.last().attachmentsUrls.add(element.attr("href")) list.last().attachmentsUrls.add(element.attr("href"))
} else if (element.parents().size == 4) { } else if (element.parents().size == 4) {
list.add(Circular.generateFromString(element.text(), element.attr("href"))) list.add(Circular.generateFromString(element.text(), element.attr("href")))
}
} }
}
return list list
}
} }
@Throws(IOException::class) @Throws(IOException::class)
fun retrieveDataFromServer(): String? { private suspend fun retrieveDataFromServer(): String? {
var connection: HttpsURLConnection? = null var connection: HttpsURLConnection? = null
return try {
connection = (URL(ENDPOINT_URL).openConnection() as? HttpsURLConnection)
connection?.run {
// Set GET HTTP method
requestMethod = "GET"
setRequestProperty("Accept-Encoding", "none") return withContext(Dispatchers.IO) {
try {
connection = (URL(ENDPOINT_URL).openConnection() as? HttpsURLConnection)
connection?.run {
// Set GET HTTP method
requestMethod = "GET"
connect() setRequestProperty("Accept-Encoding", "none")
if (responseCode != HttpsURLConnection.HTTP_OK) {
throw IOException("HTTP error code: $responseCode") connect()
if (responseCode != HttpsURLConnection.HTTP_OK) {
throw IOException("HTTP error code: $responseCode")
}
inputStream?.reader()?.readText()
} }
} finally {
inputStream?.reader()?.readText() // Close Stream and disconnect HTTPS connection.
connection?.inputStream?.close()
connection?.disconnect()
} }
} finally {
// Close Stream and disconnect HTTPS connection.
connection?.inputStream?.close()
connection?.disconnect()
} }
} }
} }

View File

@@ -19,10 +19,8 @@
package net.underdesk.circolapp.viewmodels package net.underdesk.circolapp.viewmodels
import android.app.Application import android.app.Application
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.*
import androidx.lifecycle.LiveData import kotlinx.coroutines.launch
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import net.underdesk.circolapp.data.AppDatabase import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.Circular import net.underdesk.circolapp.data.Circular
import net.underdesk.circolapp.server.DataFetcher import net.underdesk.circolapp.server.DataFetcher
@@ -48,25 +46,23 @@ class CircularLetterViewModel(application: Application) : AndroidViewModel(appli
fun updateCirculars() { fun updateCirculars() {
if (isNotUpdating) { if (isNotUpdating) {
object : Thread() { viewModelScope.launch {
override fun run() { isNotUpdating = false
isNotUpdating = false val fetcher = DataFetcher()
val fetcher = DataFetcher()
try { try {
val newCirculars = fetcher.getCircularsFromServer() val newCirculars = fetcher.getCircularsFromServer()
if (newCirculars.size != circulars.value?.size ?: true) { if (newCirculars.size != circulars.value?.size ?: true) {
AppDatabase.getInstance(getApplication()).circularDao() AppDatabase.getInstance(getApplication()).circularDao()
.insertAll(newCirculars) .insertAll(newCirculars)
}
} catch (exception: IOException) {
showMessage.postValue(true)
} finally {
isNotUpdating = true
circularsUpdated.postValue(true)
} }
} catch (exception: IOException) {
showMessage.postValue(true)
} finally {
isNotUpdating = true
circularsUpdated.postValue(true)
} }
}.start() }
} }
} }
} }

View File

@@ -30,6 +30,9 @@ import androidx.core.app.NotificationManagerCompat
import androidx.core.app.TaskStackBuilder import androidx.core.app.TaskStackBuilder
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.work.* import androidx.work.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
import net.underdesk.circolapp.MainActivity import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R import net.underdesk.circolapp.R
import net.underdesk.circolapp.data.AppDatabase import net.underdesk.circolapp.data.AppDatabase
@@ -40,7 +43,7 @@ import java.util.concurrent.TimeUnit
class PollWork(appContext: Context, workerParams: WorkerParameters) : class PollWork(appContext: Context, workerParams: WorkerParameters) :
Worker(appContext, workerParams) { CoroutineWorker(appContext, workerParams) {
companion object { companion object {
const val CHANNEL_ID = "net.underdesk.circolapp.NEW_CIRCULAR" const val CHANNEL_ID = "net.underdesk.circolapp.NEW_CIRCULAR"
@@ -84,52 +87,59 @@ class PollWork(appContext: Context, workerParams: WorkerParameters) :
} }
} }
override fun doWork(): Result { override suspend fun doWork(): Result = coroutineScope {
val fetcher = DataFetcher() val fetcher = DataFetcher()
val oldCirculars = AppDatabase.getInstance(applicationContext).circularDao().getCirculars() withContext(Dispatchers.IO) {
val newCirculars = try { val oldCirculars =
fetcher.getCircularsFromServer() AppDatabase.getInstance(applicationContext).circularDao().getCirculars()
} catch (exception: IOException) { val newCirculars = try {
return Result.retry() fetcher.getCircularsFromServer()
} } catch (exception: IOException) {
return@withContext Result.retry()
if (newCirculars.size != oldCirculars.size) {
createNotificationChannel()
val summaryStyle = NotificationCompat.InboxStyle()
.setBigContentTitle(applicationContext.getString(R.string.notification_summary_title))
.setSummaryText(applicationContext.getString(R.string.notification_summary))
val circularCount = newCirculars.size - oldCirculars.size
for (i in 0 until circularCount) {
createNotification(newCirculars[i])
summaryStyle.addLine(newCirculars[i].name)
} }
val summaryNotification = NotificationCompat.Builder(applicationContext, CHANNEL_ID) if (newCirculars.size != oldCirculars.size) {
.setContentTitle(applicationContext.getString(R.string.notification_summary_title)) withContext(Dispatchers.Main) {
.setContentText( createNotificationChannel()
applicationContext.resources.getQuantityString(
R.plurals.notification_summary_text,
circularCount,
circularCount
)
)
.setSmallIcon(R.drawable.ic_notification)
.setStyle(summaryStyle)
.setGroup(CHANNEL_ID)
.setGroupSummary(true)
.build()
with(NotificationManagerCompat.from(applicationContext)) { val summaryStyle = NotificationCompat.InboxStyle()
notify(-1, summaryNotification) .setBigContentTitle(applicationContext.getString(R.string.notification_summary_title))
.setSummaryText(applicationContext.getString(R.string.notification_summary))
val circularCount = newCirculars.size - oldCirculars.size
for (i in 0 until circularCount) {
createNotification(newCirculars[i])
summaryStyle.addLine(newCirculars[i].name)
}
val summaryNotification =
NotificationCompat.Builder(applicationContext, CHANNEL_ID)
.setContentTitle(applicationContext.getString(R.string.notification_summary_title))
.setContentText(
applicationContext.resources.getQuantityString(
R.plurals.notification_summary_text,
circularCount,
circularCount
)
)
.setSmallIcon(R.drawable.ic_notification)
.setStyle(summaryStyle)
.setGroup(CHANNEL_ID)
.setGroupSummary(true)
.build()
with(NotificationManagerCompat.from(applicationContext)) {
notify(-1, summaryNotification)
}
}
AppDatabase.getInstance(applicationContext).circularDao()
.insertAll(newCirculars)
} }
Result.success()
AppDatabase.getInstance(applicationContext).circularDao().insertAll(newCirculars)
} }
return Result.success()
} }
private fun createNotification(circular: Circular) { private fun createNotification(circular: Circular) {