-
Notifications
You must be signed in to change notification settings - Fork 237
HW Sokolova_coroutines #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Changes from 5 commits
8c748df
5ec862d
5e529fc
fcdfbfb
796be51
fc85974
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,4 +20,4 @@ | |
</activity> | ||
</application> | ||
|
||
</manifest> | ||
</manifest> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package otus.homework.coroutines | ||
|
||
import android.content.res.Resources | ||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import kotlinx.coroutines.CancellationException | ||
import kotlinx.coroutines.CoroutineExceptionHandler | ||
import kotlinx.coroutines.async | ||
import kotlinx.coroutines.cancel | ||
import kotlinx.coroutines.launch | ||
import otus.homework.coroutines.model.CatModel | ||
import java.net.SocketTimeoutException | ||
|
||
|
||
class CatViewModel( | ||
private val factService: CatsFactService, | ||
private val imageService: CatsImageService | ||
) : ViewModel() { | ||
val catModel = MutableLiveData<Result>() | ||
|
||
fun onInitComplete() { | ||
loadData() | ||
} | ||
|
||
private val handler = CoroutineExceptionHandler { _, throwable -> | ||
when (throwable) { | ||
is SocketTimeoutException -> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Я бы это перенес в try/catch. Тут оставил только необработанные There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. d |
||
catModel.value = Result.Error(Throwable(Resources.getSystem().getString(R.string.error_connection))) | ||
} | ||
is CancellationException -> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. в There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. d, унесла в try/catch |
||
throw throwable | ||
} | ||
else -> { | ||
CrashMonitor.trackWarning(throwable.message.toString()) | ||
catModel.value = Result.Error(throwable) | ||
} | ||
} | ||
} | ||
|
||
private fun loadData() { | ||
viewModelScope.launch(handler) { | ||
val catFactJob = async { factService.getCatFact() } | ||
val catImageJob = async { imageService.getCatImage() } | ||
|
||
catModel.value = Result.Success( | ||
CatModel( | ||
catFactJob.await().body()?.fact, | ||
CatsImageService.BASE_URL + catImageJob.await().body()?.url | ||
) | ||
) | ||
|
||
} | ||
} | ||
|
||
override fun onCleared() { | ||
super.onCleared() | ||
viewModelScope.cancel() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. viewModelScope сам будет очищен в There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. d |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package otus.homework.coroutines | ||
|
||
import otus.homework.coroutines.model.Fact | ||
import retrofit2.Response | ||
import retrofit2.http.GET | ||
|
||
interface CatsFactService { | ||
|
||
@GET("fact") | ||
suspend fun getCatFact() : Response<Fact> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Я бы просто Fact оставил There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. d, для картинок сделала аналогично |
||
|
||
companion object { | ||
const val BASE_URL = "https://catfact.ninja/" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package otus.homework.coroutines | ||
|
||
import otus.homework.coroutines.model.RandomCat | ||
import retrofit2.Response | ||
import retrofit2.http.GET | ||
|
||
interface CatsImageService { | ||
|
||
@GET("cat?json=true") | ||
suspend fun getCatImage() : Response<RandomCat> | ||
|
||
companion object { | ||
const val BASE_URL = "https://cataas.com/" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,50 @@ | ||
package otus.homework.coroutines | ||
|
||
import retrofit2.Call | ||
import retrofit2.Callback | ||
import retrofit2.Response | ||
import kotlinx.coroutines.CancellationException | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.async | ||
import kotlinx.coroutines.cancel | ||
import kotlinx.coroutines.launch | ||
import kotlinx.coroutines.runBlocking | ||
import otus.homework.coroutines.model.CatModel | ||
import java.net.SocketTimeoutException | ||
|
||
class CatsPresenter( | ||
private val catsService: CatsService | ||
private val factService: CatsFactService, | ||
private val imageService: CatsImageService | ||
) { | ||
|
||
private var _catsView: ICatsView? = null | ||
private val catsScope = PresenterScope() | ||
|
||
fun onInitComplete() { | ||
catsService.getCatFact().enqueue(object : Callback<Fact> { | ||
|
||
override fun onResponse(call: Call<Fact>, response: Response<Fact>) { | ||
if (response.isSuccessful && response.body() != null) { | ||
_catsView?.populate(response.body()!!) | ||
runBlocking(Dispatchers.IO) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Зачем здесь There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. d |
||
catsScope.launch { | ||
try { | ||
val catFactJob = async { factService.getCatFact() } | ||
val catImageJob = async { imageService.getCatImage() } | ||
|
||
val catModel = CatModel( | ||
catFactJob.await().body()?.fact, | ||
CatsImageService.BASE_URL + catImageJob.await().body()?.url) | ||
|
||
_catsView?.populate(catModel) | ||
} catch (e: Exception) { | ||
when (e) { | ||
is SocketTimeoutException -> { | ||
_catsView?.showToast(R.string.error_connection) | ||
} | ||
is CancellationException -> { | ||
throw e | ||
} | ||
else -> { | ||
CrashMonitor.trackWarning(e.message.toString()) | ||
_catsView?.showToast(e.message.toString()) | ||
} | ||
} | ||
} | ||
} | ||
|
||
override fun onFailure(call: Call<Fact>, t: Throwable) { | ||
CrashMonitor.trackWarning() | ||
} | ||
}) | ||
} | ||
} | ||
|
||
fun attachView(catsView: ICatsView) { | ||
|
@@ -32,4 +54,8 @@ class CatsPresenter( | |
fun detachView() { | ||
_catsView = null | ||
} | ||
} | ||
|
||
fun onStop(){ | ||
catsScope.cancel() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А почему это не перенести в detachView, ты же onStop вызываешь в onStop ЖЦ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. d |
||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,16 @@ | ||
package otus.homework.coroutines | ||
|
||
import android.util.Log | ||
|
||
object CrashMonitor { | ||
|
||
/** | ||
* Pretend this is Crashlytics/AppCenter | ||
*/ | ||
fun trackWarning() { | ||
private val crashesList = ArrayList<String>() | ||
|
||
fun trackWarning(message: String) { | ||
crashesList.add(message) | ||
Log.e("crash_mirror", message) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,48 @@ | ||
package otus.homework.coroutines | ||
|
||
import com.google.gson.GsonBuilder | ||
import okhttp3.OkHttpClient | ||
import okhttp3.logging.HttpLoggingInterceptor | ||
import retrofit2.Retrofit | ||
import retrofit2.converter.gson.GsonConverterFactory | ||
import java.util.concurrent.TimeUnit | ||
|
||
class DiContainer { | ||
|
||
private val retrofit by lazy { | ||
val serviceFact: CatsFactService by lazy { retrofitCatFact.create(CatsFactService::class.java) } | ||
val serviceImage: CatsImageService by lazy { retrofitCatImage.create(CatsImageService::class.java) } | ||
|
||
private val interceptor = run { | ||
val httpLoggingInterceptor = HttpLoggingInterceptor() | ||
httpLoggingInterceptor.apply { | ||
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY | ||
} | ||
} | ||
|
||
private val okHttpClient = OkHttpClient.Builder() | ||
.addNetworkInterceptor(interceptor) // same for .addInterceptor(...) | ||
.connectTimeout(30, TimeUnit.SECONDS) //Backend is really slow | ||
.writeTimeout(30, TimeUnit.SECONDS) | ||
.readTimeout(30, TimeUnit.SECONDS) | ||
.build() | ||
|
||
private val retrofitCatFact by lazy { | ||
Retrofit.Builder() | ||
.baseUrl("https://catfact.ninja/") | ||
.client(okHttpClient) | ||
.baseUrl(CatsFactService.BASE_URL) | ||
.addConverterFactory(GsonConverterFactory.create()) | ||
.build() | ||
} | ||
|
||
val service by lazy { retrofit.create(CatsService::class.java) } | ||
} | ||
private val gson = GsonBuilder() | ||
.setLenient() | ||
.create() | ||
|
||
private val retrofitCatImage by lazy { | ||
Retrofit.Builder() | ||
.client(okHttpClient) | ||
.baseUrl(CatsImageService.BASE_URL) | ||
.addConverterFactory(GsonConverterFactory.create(gson)) | ||
.build() | ||
} | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Мутабельные стримы: лайвдата, стейтфлоу и тп делают приватными(обычно). Это для того чтобы у тебя в стрим мог эмитить только 1 класс, а не все у кого есть ссылка на CatViewModel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d