From ce5daf55f5f52258236e9858591d23b88b3f86d7 Mon Sep 17 00:00:00 2001 From: FlorianGandon <165256783+FlorianGandon@users.noreply.github.com> Date: Wed, 16 Apr 2025 13:55:42 +0200 Subject: [PATCH] add async in activities --- app/build.gradle.kts | 2 + .../tdsaeandroid/DisplayMediaActivity.kt | 61 +++++++++++-------- .../tdsaeandroid/MediasFiltersActivity.kt | 37 +++++------ .../example/tdsaeandroid/ResultsActivity.kt | 55 +++++++++++------ gradle/libs.versions.toml | 4 ++ 5 files changed, 94 insertions(+), 65 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fff613d..d9759d3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -58,4 +58,6 @@ dependencies { androidTestImplementation(libs.androidx.espresso.core) implementation (libs.picasso) implementation(libs.androidx.activity.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.ktx.v172) } \ No newline at end of file diff --git a/app/src/main/java/com/example/tdsaeandroid/DisplayMediaActivity.kt b/app/src/main/java/com/example/tdsaeandroid/DisplayMediaActivity.kt index 32b4631..acabc03 100644 --- a/app/src/main/java/com/example/tdsaeandroid/DisplayMediaActivity.kt +++ b/app/src/main/java/com/example/tdsaeandroid/DisplayMediaActivity.kt @@ -2,17 +2,22 @@ package com.example.tdsaeandroid import android.content.Intent import android.os.Bundle +import android.view.LayoutInflater import android.widget.ImageButton import android.widget.ImageView import android.widget.TextView import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import com.example.tdsaeandroid.dao.Dao import com.example.tdsaeandroid.model.media.Media import com.example.tdsaeandroid.model.movie.Movie import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup import com.squareup.picasso.Picasso +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class DisplayMediaActivity : AppCompatActivity() { @@ -43,7 +48,6 @@ class DisplayMediaActivity : AppCompatActivity() { genresChips = findViewById(R.id.media__genres) type = (intent?.getSerializableExtra("type") ?: throw Exception("No activity type found")) as ActivityType - val id = intent?.extras?.getInt("id") ?: throw Exception("No id found") btClose.setOnClickListener { val intent = Intent() @@ -51,34 +55,43 @@ class DisplayMediaActivity : AppCompatActivity() { setResult(RESULT_OK, intent) finish() } + lifecycleScope.launch { + val data = getMediaData() + if (data == null) { + val intent = Intent() + intent.putExtra("found", false) + setResult(RESULT_OK, intent) + return@launch finish() + } + title.text = data.title + overview.text = data.overview + averageText.text = getString(R.string.rating_according, data.vote_average.toString(), data.vote_count.toString()) - // get media data - val data: Media? = when (type) { - ActivityType.Movie -> dao.getMovieById(id) - ActivityType.Tv -> dao.getTvById(id) + if (data is Movie) { + date.text = getString(R.string.released_in, data.release_date) + if (data.adult) { + includeAdultText.text = getString(R.string.warning_not_suitable) + } + } + for (g in data.genres) { + val chip = Chip(this@DisplayMediaActivity) + chip.text = g.name + genresChips.addView(chip) + } + Picasso.get().load(IMG_URL + data.poster_path).into(image) } - if (data == null) { - val intent = Intent() - intent.putExtra("found", false) - setResult(RESULT_OK, intent) - return finish() - } - title.text = data.title - overview.text = data.overview - averageText.text = getString(R.string.rating_according, data.vote_average.toString(), data.vote_count.toString()) - if (data is Movie) { - date.text = getString(R.string.released_in, data.release_date) - if (data.adult) { - includeAdultText.text = getString(R.string.warning_not_suitable) + } + + private suspend fun getMediaData(): Media? { + return withContext(Dispatchers.IO) { + val id = intent?.extras?.getInt("id") ?: throw Exception("No id found") + + when (type) { + ActivityType.Movie -> dao.getMovieById(id) + ActivityType.Tv -> dao.getTvById(id) } } - for (g in data.genres) { - val chip = Chip(this) - chip.text = g.name - genresChips.addView(chip) - } - Picasso.get().load(IMG_URL + data.poster_path).into(image) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/tdsaeandroid/MediasFiltersActivity.kt b/app/src/main/java/com/example/tdsaeandroid/MediasFiltersActivity.kt index 05b3b02..44e9186 100644 --- a/app/src/main/java/com/example/tdsaeandroid/MediasFiltersActivity.kt +++ b/app/src/main/java/com/example/tdsaeandroid/MediasFiltersActivity.kt @@ -7,21 +7,19 @@ import android.content.DialogInterface import android.content.Intent import android.icu.text.DateFormat.getDateInstance import android.icu.util.Calendar -import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.widget.Button import android.widget.DatePicker -import android.widget.EditText import android.widget.RatingBar import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.launch import com.example.tdsaeandroid.component.yearPickerDialog import com.example.tdsaeandroid.dao.Dao import com.example.tdsaeandroid.dao.DateFilter -import com.example.tdsaeandroid.dao.DateSort -import com.example.tdsaeandroid.dao.Filter import com.example.tdsaeandroid.dao.FilterContainer import com.example.tdsaeandroid.dao.GenresFilter import com.example.tdsaeandroid.dao.IncludeAdultFilter @@ -30,21 +28,14 @@ import com.example.tdsaeandroid.dao.VotesFilter import com.example.tdsaeandroid.dao.YearFilter import com.example.tdsaeandroid.dao.formatDate import com.example.tdsaeandroid.model.media.Genre -import com.example.tdsaeandroid.model.movie.MovieInList import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup import com.google.android.material.switchmaterial.SwitchMaterial -import kotlinx.serialization.PolymorphicSerializer +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import kotlinx.serialization.modules.SerializersModule -import kotlinx.serialization.modules.polymorphic -import kotlinx.serialization.modules.subclass -import kotlinx.serialization.serializer -import java.text.SimpleDateFormat import java.time.Year import java.util.Date -import java.util.Random class MediasFiltersActivity : AppCompatActivity(), DatePickerListener { @@ -142,16 +133,20 @@ class MediasFiltersActivity : AppCompatActivity(), DatePickerListener { newFragment.show(supportFragmentManager, "datePicker") } - genres = dao.getGenres().toTypedArray() - - for (g in genres) { - val chip: Chip = LayoutInflater.from(this).inflate(R.layout.chip_layout, null) as Chip - chip.text = g.name - chip.id = g.id - chipGroup.addView(chip) + lifecycleScope.launch { + loadGenres().forEach { + val chip: Chip = LayoutInflater.from(this@MediasFiltersActivity).inflate(R.layout.chip_layout, null) as Chip + chip.text = it.name + chip.id = it.id + chipGroup.addView(chip) + } } + } - // todo lifecyclescope + private suspend fun loadGenres(): Array<Genre> { + return withContext(Dispatchers.IO) { + dao.getGenres().toTypedArray() + } } override fun onDateSetBefore(date: Date) { diff --git a/app/src/main/java/com/example/tdsaeandroid/ResultsActivity.kt b/app/src/main/java/com/example/tdsaeandroid/ResultsActivity.kt index fdb9056..81505ce 100644 --- a/app/src/main/java/com/example/tdsaeandroid/ResultsActivity.kt +++ b/app/src/main/java/com/example/tdsaeandroid/ResultsActivity.kt @@ -1,6 +1,7 @@ package com.example.tdsaeandroid import android.os.Bundle +import android.view.LayoutInflater import android.widget.ArrayAdapter import android.widget.Button import android.widget.ImageButton @@ -14,8 +15,13 @@ import com.example.tdsaeandroid.viewmodel.ResultsViewModel import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup import androidx.activity.viewModels +import androidx.lifecycle.lifecycleScope import com.example.tdsaeandroid.contract.DisplayMediaActivityContract import com.example.tdsaeandroid.dao.FilterContainer +import com.example.tdsaeandroid.model.media.Genre +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class ResultsActivity : AppCompatActivity() { @@ -52,30 +58,26 @@ class ResultsActivity : AppCompatActivity() { type = (intent?.getSerializableExtra("type") ?: throw Exception("No activity type found")) as ActivityType - val nameValue = intent.getStringExtra("nameValue") - val filterContainerJson = intent.getStringExtra("filterContainer") - println("aa") - val filterContainer: FilterContainer? = if (filterContainerJson != null) { - json.decodeFromString(filterContainerJson) - } else { - null - } - println("bb") - resultsViewModel.init(nameValue, filterContainer, type) - - adapter = MediaItemAdapter(this, resultsViewModel.getResults()) + adapter = MediaItemAdapter(this@ResultsActivity, mutableListOf()) listView.adapter = adapter - updateButton(btPreviousPage, !resultsViewModel.isFirstPage()) - updateButton(btNextPage, !resultsViewModel.isLastPage()) + updateButton(btPreviousPage, false) + updateButton(btNextPage, false) + lifecycleScope.launch { + loadResults() + adapter.addAll(resultsViewModel.getResults()) - if (resultsViewModel.filterContainer != null) { - for (f in resultsViewModel.filterContainer?.getFilters()!!) { - val chip = Chip(this) - "${ f.getKey()}: ${ f.getValue() }".also { chip.text = it } - chip.isChecked = true - chipGroup.addView(chip) + updateButton(btPreviousPage, !resultsViewModel.isFirstPage()) + updateButton(btNextPage, !resultsViewModel.isLastPage()) + + if (resultsViewModel.filterContainer != null) { + for (f in resultsViewModel.filterContainer?.getFilters()!!) { + val chip = Chip(this@ResultsActivity) + "${ f.getKey()}: ${ f.getValue() }".also { chip.text = it } + chip.isChecked = true + chipGroup.addView(chip) + } } } @@ -125,4 +127,17 @@ class ResultsActivity : AppCompatActivity() { bt.isEnabled = isEnable bt.isClickable = isEnable } + + private suspend fun loadResults() { + val nameValue = intent.getStringExtra("nameValue") + val filterContainerJson = intent.getStringExtra("filterContainer") + val filterContainer: FilterContainer? = if (filterContainerJson != null) { + json.decodeFromString(filterContainerJson) + } else { + null + } + return withContext(Dispatchers.IO) { + resultsViewModel.init(nameValue, filterContainer, type) + } + } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1a77dc7..4dfcd00 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,6 @@ [versions] activityKtx = "1.10.1" +activityKtxVersion = "1.7.2" agp = "8.5.2" kotlin = "1.9.0" coreKtx = "1.10.1" @@ -9,6 +10,7 @@ espressoCore = "3.5.1" appcompat = "1.6.1" kotlinxSerializationJson = "1.6.3" ktorVersion = "2.3.6" +lifecycleRuntimeKtx = "2.8.7" material = "1.10.0" activity = "1.8.0" constraintlayout = "2.1.4" @@ -18,7 +20,9 @@ junitJupiter = "5.8.1" [libraries] androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityKtx" } +androidx-activity-ktx-v172 = { module = "androidx.activity:activity-ktx", version.ref = "activityKtxVersion" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } -- GitLab