-
Notifications
You must be signed in to change notification settings - Fork 242
Homework Baturina #164
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?
Homework Baturina #164
Changes from all commits
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 |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package otus.homework.coroutines | ||
|
||
import com.google.gson.annotations.SerializedName | ||
|
||
data class CatImage( | ||
@field:SerializedName("file") | ||
val url: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package otus.homework.coroutines | ||
|
||
data class CatModel( | ||
val fact: String, | ||
val url: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,31 @@ | ||
package otus.homework.coroutines | ||
|
||
import retrofit2.Call | ||
import retrofit2.Callback | ||
import retrofit2.Response | ||
import kotlinx.coroutines.* | ||
import java.net.SocketTimeoutException | ||
|
||
class CatsPresenter( | ||
private val catsService: CatsService | ||
private val serviceCatFact: CatsService, | ||
private val serviceCatImage: CatsService | ||
) { | ||
|
||
private var _catsView: ICatsView? = null | ||
private val outerScope = PresenterScope() | ||
private lateinit var innerScope: CoroutineScope | ||
|
||
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()!!) | ||
} | ||
} | ||
|
||
override fun onFailure(call: Call<Fact>, t: Throwable) { | ||
CrashMonitor.trackWarning() | ||
outerScope.launch { | ||
innerScope = CoroutineScope(Dispatchers.IO) | ||
try { | ||
val catFact = innerScope.async { serviceCatFact.getCatFact() } | ||
val catImage = innerScope.async { serviceCatImage.getCatImage() } | ||
_catsView?.populate(CatModel(catFact.await().fact, catImage.await().url)) | ||
} catch (exc: SocketTimeoutException) { | ||
_catsView?.makeToast("Не удалось получить ответ от сервером") | ||
} catch (exc: Exception) { | ||
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. Здесь будет также пойман CancellationException, через который работает механизм отмены. Нужно его пробросить дальше, либо не ловить такой общий тип исключений |
||
CrashMonitor.trackWarning(exc) | ||
_catsView?.makeToast(exc.message.toString()) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
fun attachView(catsView: ICatsView) { | ||
|
@@ -31,5 +34,7 @@ class CatsPresenter( | |
|
||
fun detachView() { | ||
_catsView = null | ||
outerScope.cancel() | ||
innerScope.cancel() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package otus.homework.coroutines | ||
|
||
sealed interface CatsResult { | ||
class Success<T> (val result: T): CatsResult | ||
class Error(val exc: String): CatsResult | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
package otus.homework.coroutines | ||
|
||
import retrofit2.Call | ||
import retrofit2.http.GET | ||
|
||
interface CatsService { | ||
|
||
@GET("fact") | ||
fun getCatFact() : Call<Fact> | ||
suspend fun getCatFact(): Fact | ||
|
||
@GET("meow") | ||
suspend fun getCatImage(): CatImage | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package otus.homework.coroutines | ||
|
||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import kotlinx.coroutines.CoroutineExceptionHandler | ||
import kotlinx.coroutines.async | ||
import kotlinx.coroutines.launch | ||
|
||
class CatsViewModel( | ||
private val serviceCatFact: CatsService, | ||
private val serviceCatImage: CatsService | ||
): ViewModel() { | ||
|
||
var result: MutableLiveData<CatsResult> = MutableLiveData() | ||
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. Наружу нужно показывать иммутабельную версию лайвдаты/стейтфлоу |
||
|
||
private val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable -> | ||
CrashMonitor.trackWarning(throwable) | ||
result.postValue(CatsResult.Error(throwable.message.toString())) | ||
} | ||
|
||
fun onInitComplete() { | ||
viewModelScope.launch(exceptionHandler) { | ||
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 |
||
val catFact = async { serviceCatFact.getCatFact() } | ||
val catImage = async { serviceCatImage.getCatImage() } | ||
result.postValue(CatsResult.Success(CatModel(catFact.await().fact, catImage.await().url))) | ||
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. А зачем тут postValue, ты же уже на главный поток вернулась |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,26 @@ | ||
package otus.homework.coroutines | ||
|
||
import androidx.appcompat.app.AppCompatActivity | ||
import android.os.Bundle | ||
import androidx.appcompat.app.AppCompatActivity | ||
|
||
class MainActivity : AppCompatActivity() { | ||
|
||
lateinit var catsPresenter: CatsPresenter | ||
|
||
private val diContainer = DiContainer() | ||
private var catsViewModel = CatsViewModel(diContainer.serviceCatFact, diContainer.serviceCatImage) | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
|
||
val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView | ||
setContentView(view) | ||
|
||
catsPresenter = CatsPresenter(diContainer.service) | ||
view.presenter = catsPresenter | ||
catsPresenter.attachView(view) | ||
catsPresenter.onInitComplete() | ||
} | ||
|
||
override fun onStop() { | ||
if (isFinishing) { | ||
catsPresenter.detachView() | ||
view.viewModel = catsViewModel | ||
catsViewModel.result.observe(this) { | ||
when(it) { | ||
is CatsResult.Success<*> -> view.populate(it.result as CatModel) | ||
is CatsResult.Error -> view.makeToast(it.exc) | ||
} | ||
} | ||
super.onStop() | ||
catsViewModel.onInitComplete() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package otus.homework.coroutines | ||
|
||
import kotlinx.coroutines.CoroutineName | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlin.coroutines.CoroutineContext | ||
|
||
class PresenterScope: CoroutineScope { | ||
|
||
override val coroutineContext: CoroutineContext | ||
get() = Dispatchers.Main + CoroutineName("CatsCoroutine") | ||
} |
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.
А иннер скоуп ты зачем делаешь?