Skip to content

Commit

Permalink
ref: use coroutines and lifecycle to do async operations instead of r…
Browse files Browse the repository at this point in the history
…xjava and disposables
  • Loading branch information
VaiTon committed Jun 28, 2021
1 parent 117e9fe commit a10edcf
Show file tree
Hide file tree
Showing 23 changed files with 480 additions and 487 deletions.
Expand Up @@ -7,7 +7,6 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.rx2.await
import kotlinx.coroutines.test.runBlockingTest
import openfoodfacts.github.scrachx.openfood.models.DaoSession
import openfoodfacts.github.scrachx.openfood.models.entities.allergen.Allergen
Expand Down Expand Up @@ -92,7 +91,7 @@ class ProductRepositoryTest {

@Test
fun testGetAllergensByLanguageCode() = runBlockingTest {
val allergenNames = productRepository.getAllergensByLanguageCode(TEST_LANGUAGE_CODE).await()
val allergenNames = productRepository.getAllergensByLanguageCode(TEST_LANGUAGE_CODE)
assertNotNull(allergenNames)
assertEquals(2, allergenNames.size.toLong())
}
Expand Down
Expand Up @@ -27,9 +27,6 @@ import androidx.core.content.edit
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.rxkotlin.addTo
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -168,22 +165,21 @@ class HomeFragment : NavigationBaseFragment() {
private fun refreshProductCount(oldCount: Int) {
Log.d(LOG_TAG, "Refreshing total product count...")

productsApi.getTotalProductCount(getUserAgent())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { setProductCount(oldCount) }
.doOnError {
lifecycleScope.launch {
val resp = try {
withContext(Dispatchers.IO) { productsApi.getTotalProductCount(getUserAgent()) }
} catch (err: Exception) {
Log.e(LOG_TAG, "Could not retrieve product count from server.", err)
setProductCount(oldCount)
Log.e(LOG_TAG, "Could not retrieve product count from server.", it)
return@launch
}
.subscribe { resp ->
val totalProductCount = resp.count.toInt()
Log.d(LOG_TAG, "Refreshed total product count. There are $totalProductCount products on the database.")
setProductCount(totalProductCount)
sharedPrefs.edit {
putInt(PRODUCT_COUNT_KEY, totalProductCount)
apply()
}
}.addTo(disp)
val count = resp.count.toInt()
Log.d(LOG_TAG, "Refreshed total product count. There are $count products on the database.")

setProductCount(count)

sharedPrefs.edit { putInt(PRODUCT_COUNT_KEY, count) }
}
}

/**
Expand All @@ -193,7 +189,7 @@ class HomeFragment : NavigationBaseFragment() {
*/
private fun setProductCount(count: Int) {
if (count == 0) {
binding.textHome.setText(R.string.txtHome)
binding.textHome.text = getString(R.string.txtHome)
} else {
binding.textHome.text = resources.getString(R.string.txtHomeOnline, NumberFormat.getInstance().format(count))
}
Expand All @@ -203,29 +199,32 @@ class HomeFragment : NavigationBaseFragment() {
* get tag line url from OpenFoodAPIService
*/
private fun refreshTagLine() {
productsApi.getTagline(getUserAgent())
.subscribeOn(Schedulers.io()) // io for network
.observeOn(AndroidSchedulers.mainThread()) // Move to main thread for UI changes
.doOnError { Log.w(LOG_TAG, "Could not retrieve tag-line from server.", it) }
.subscribe { tagLines ->
val appLanguage = localeManager.getLanguage()
var isLanguageFound = false
var isExactLanguageFound = false
tagLines.forEach { tag ->
if (!isExactLanguageFound && (tag.language == appLanguage || tag.language.contains(appLanguage))) {
isExactLanguageFound = tag.language == appLanguage
taglineURL = tag.tagLine.url
binding.tvTagLine.text = tag.tagLine.message
isLanguageFound = true
}
}
if (!isLanguageFound) {
taglineURL = tagLines.last().tagLine.url
binding.tvTagLine.text = tagLines.last().tagLine.message
}
binding.tvTagLine.visibility = View.VISIBLE
lifecycleScope.launch {
val tagLines = try {
withContext(Dispatchers.IO) { productsApi.getTagline(getUserAgent()) }
} catch (err: Exception) {
Log.w(LOG_TAG, "Could not retrieve tag-line from server.", err)
return@launch
}
.addTo(disp)

val appLanguage = localeManager.getLanguage()
var isLanguageFound = false

for (tag in tagLines) {
if (appLanguage !in tag.language) continue
isLanguageFound = true
if (tag.language == appLanguage) break

taglineURL = tag.tagLine.url
binding.tvTagLine.text = tag.tagLine.message
}

if (!isLanguageFound) {
taglineURL = tagLines.last().tagLine.url
binding.tvTagLine.text = tagLines.last().tagLine.message
}
binding.tvTagLine.visibility = View.VISIBLE
}
}

companion object {
Expand Down
Expand Up @@ -322,7 +322,9 @@ class ImagesManageActivity : BaseActivity() {

getProduct()?.let {
startRefresh(getString(R.string.loading_product, "${it.getProductName(localeManager.getLanguage())}..."))
client.getProductImages(it.code).observeOn(AndroidSchedulers.mainThread()).subscribe { newState ->

lifecycleScope.launch {
val newState = client.getProductImages(it.code).observeOn(AndroidSchedulers.mainThread()).await()
val newProduct = newState.product
var imageReloaded = false

Expand All @@ -344,7 +346,8 @@ class ImagesManageActivity : BaseActivity() {
}

if (!imageReloaded) stopRefresh()
}.addTo(disp)
}

}
}

Expand Down Expand Up @@ -405,12 +408,15 @@ class ImagesManageActivity : BaseActivity() {
private fun unSelectImage() {
if (cannotEdit(REQUEST_UNSELECT_IMAGE_AFTER_LOGIN)) return
startRefresh(getString(R.string.unselect_image))
client.unSelectImage(getProduct()!!.code, getSelectedType(), getCurrentLanguage())
.doOnError { reloadProduct() }
.subscribe { _ ->
setResult(RESULTCODE_MODIFIED)
lifecycleScope.launch {
try {
client.unSelectImage(getProduct()!!.code, getSelectedType(), getCurrentLanguage())
} catch (err: Exception) {
reloadProduct()
}.addTo(disp)
}
setResult(RESULTCODE_MODIFIED)
reloadProduct()
}
}

private fun selectImage() {
Expand Down Expand Up @@ -605,11 +611,8 @@ class ImagesManageActivity : BaseActivity() {
binding.imageViewFullScreen.visibility = View.INVISIBLE

lifecycleScope.launch(Dispatchers.IO) {
val value = client.editImage(code, map).await()
if (value != null) {
setResult(RESULTCODE_MODIFIED)
}

client.editImage(code, map)
setResult(RESULTCODE_MODIFIED)
withContext(Dispatchers.Main) { reloadProduct() }
}
}
Expand Down
Expand Up @@ -4,22 +4,23 @@ import android.content.Context
import android.widget.ArrayAdapter
import android.widget.Filter
import android.widget.Filterable
import kotlinx.coroutines.runBlocking
import openfoodfacts.github.scrachx.openfood.network.OpenFoodAPIClient
import org.apache.commons.lang3.StringUtils
import java.util.*

class EmbCodeAutoCompleteAdapter(
context: Context,
textViewResourceId: Int,
private val client: OpenFoodAPIClient
context: Context,
textViewResourceId: Int,
private val client: OpenFoodAPIClient
) : ArrayAdapter<String>(context, textViewResourceId), Filterable {
private val codeList: MutableList<String> = arrayListOf()


override fun getCount() = codeList.size

override fun getItem(position: Int) =
if (position in 0..codeList.size) codeList[position] else StringUtils.EMPTY
if (position in 0..codeList.size) codeList[position] else StringUtils.EMPTY

override fun getFilter() = object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
Expand All @@ -28,7 +29,7 @@ class EmbCodeAutoCompleteAdapter(
if (constraint == null) return FilterResults().apply { count = 0 }

// Retrieve the autocomplete results from server.
val list = client.getEMBCodeSuggestions(constraint.toString()).blockingGet()
val list = runBlocking { client.getEMBCodeSuggestions(constraint.toString()) }

// Assign the data to the FilterResults
return FilterResults().apply {
Expand Down
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import android.widget.ArrayAdapter
import android.widget.Filter
import android.widget.Filterable
import kotlinx.coroutines.runBlocking
import openfoodfacts.github.scrachx.openfood.network.OpenFoodAPIClient
import org.apache.commons.lang3.StringUtils
import java.util.*
Expand All @@ -26,7 +27,7 @@ class PeriodAfterOpeningAutoCompleteAdapter(
if (constraint == null) return FilterResults().apply { count = 0 }

// Retrieve the autocomplete results from server.
val list = client.getPeriodAfterOpeningSuggestions(constraint.toString()).blockingGet()
val list = runBlocking { client.getPeriodAfterOpeningSuggestions(constraint.toString()) }

// Assign the data to the FilterResults
return FilterResults().apply {
Expand Down
Expand Up @@ -12,9 +12,11 @@ import androidx.core.text.bold
import androidx.core.text.color
import androidx.core.text.inSpans
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.fasterxml.jackson.databind.JsonNode
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
import kotlinx.coroutines.launch
import kotlinx.coroutines.rx2.await
import openfoodfacts.github.scrachx.openfood.R
import openfoodfacts.github.scrachx.openfood.features.search.ProductSearchActivity
import openfoodfacts.github.scrachx.openfood.features.shared.BaseFragment
Expand All @@ -36,25 +38,21 @@ object AdditiveFragmentHelper {
*/
@JvmStatic
fun showAdditives(
additives: List<AdditiveName>,
additivesView: TextView,
apiClientForWikiData: WikiDataApiClient,
fragment: BaseFragment,
compositeDisposable: CompositeDisposable
additives: List<AdditiveName>,
additivesView: TextView,
apiClientForWikiData: WikiDataApiClient,
fragment: BaseFragment
) = additivesView.run {
movementMethod = LinkMovementMethod.getInstance()
isClickable = true
text = SpannableStringBuilder()
.bold { append(fragment.getString(R.string.txtAdditives)) }
.apply {
additives.forEach {
append("\n")
append(getAdditiveTag(it,
apiClientForWikiData,
fragment,
compositeDisposable))
}
.bold { append(fragment.getString(R.string.txtAdditives)) }
.apply {
additives.forEach {
append("\n")
append(getAdditiveTag(it, apiClientForWikiData, fragment, fragment))
}
}
}

/**
Expand All @@ -64,17 +62,20 @@ object AdditiveFragmentHelper {
* @param apiClientForWikiData object of WikidataApiClient
* @param fragment holds a reference to the calling fragment
*/
private fun getAdditiveTag(additive: AdditiveName,
apiClientForWikiData: WikiDataApiClient,
fragment: BaseFragment,
compositeDisposable: CompositeDisposable): CharSequence {
private fun getAdditiveTag(
additive: AdditiveName,
apiClientForWikiData: WikiDataApiClient,
fragment: BaseFragment,
lifecycleOwner: LifecycleOwner
): CharSequence {
val activity = fragment.requireActivity()
val clickableSpan = object : ClickableSpan() {
override fun onClick(view: View) {
if (additive.isWikiDataIdPresent) {
apiClientForWikiData.doSomeThing(additive.wikiDataId).subscribe { result ->
lifecycleOwner.lifecycleScope.launch {
val result = apiClientForWikiData.doSomeThing(additive.wikiDataId).await()
getOnWikiResponse(activity, additive)(result)
}.addTo(compositeDisposable)
}
} else {
onWikiNoResponse(additive, activity)
}
Expand All @@ -92,14 +93,14 @@ object AdditiveFragmentHelper {
if (isHighRisk) ContextCompat.getDrawable(activity, R.drawable.ic_additive_high_risk)
else ContextCompat.getDrawable(activity, R.drawable.ic_additive_moderate_risk)
)?.apply {
setBounds(0, 0, this.intrinsicWidth, this.intrinsicHeight)
}!!
setBounds(0, 0, this.intrinsicWidth, this.intrinsicHeight)
}!!
val riskWarningStr =
if (isHighRisk) fragment.getString(R.string.overexposure_high)
else fragment.getString(R.string.overexposure_moderate)
if (isHighRisk) fragment.getString(R.string.overexposure_high)
else fragment.getString(R.string.overexposure_moderate)
val riskWarningColor =
if (isHighRisk) ContextCompat.getColor(activity, R.color.overexposure_high)
else ContextCompat.getColor(activity, R.color.overexposure_moderate)
if (isHighRisk) ContextCompat.getColor(activity, R.color.overexposure_high)
else ContextCompat.getColor(activity, R.color.overexposure_moderate)

it.append(" ")
it.inSpans(ImageSpan(riskIcon, DynamicDrawableSpan.ALIGN_BOTTOM)) { it.append("-") }
Expand Down

0 comments on commit a10edcf

Please sign in to comment.