Skip to content

Commit 7d7f939

Browse files
author
Artem Nagorny
committed
1 parent df9049e commit 7d7f939

File tree

7 files changed

+80
-64
lines changed

7 files changed

+80
-64
lines changed

app/src/main/java/otus/homework/coroutines/CatsPresenter.kt

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,66 @@
11
package otus.homework.coroutines
22

3-
import android.content.Context
4-
import android.widget.Toast
3+
import kotlinx.coroutines.CancellationException
54
import kotlinx.coroutines.CoroutineScope
65
import kotlinx.coroutines.Job
6+
import kotlinx.coroutines.async
7+
import kotlinx.coroutines.coroutineScope
78
import kotlinx.coroutines.launch
89
import java.net.SocketTimeoutException
910

1011
class CatsPresenter(
11-
private val context: Context,
1212
private val catsRepository: ICatsRepository,
1313
) {
1414
private var _catsJob: Job? = null
1515
private var _catsView: ICatsView? = null
1616

17-
private val scope: CoroutineScope by lazy { PresenterScope() }
17+
private val scope: CoroutineScope = PresenterScope()
1818

1919
fun onInitComplete() {
2020
cancelCatJob()
2121
_catsJob = scope.launch {
2222
try {
23-
val cat: Cat = catsRepository.getCat()
23+
val cat: Cat = loadCat()
2424

2525
_catsView?.populate(cat)
2626
} catch (e: SocketTimeoutException) {
27-
Toast.makeText(
28-
context,
29-
"Не удалось получить ответ от сервера",
30-
Toast.LENGTH_SHORT,
31-
).show()
27+
_catsView?.showToast("Не удалось получить ответ от сервера")
3228
} catch (e: Exception) {
29+
if (e is CancellationException) {
30+
throw e
31+
}
32+
3333
e.printStackTrace()
3434
CrashMonitor.trackWarning()
3535
e.message?.let { eMessage ->
36-
Toast.makeText(
37-
context,
38-
eMessage,
39-
Toast.LENGTH_SHORT,
40-
).show()
36+
_catsView?.showToast(eMessage)
4137
}
4238
}
4339
}
4440
}
4541

42+
private suspend fun loadCat(): Cat = coroutineScope {
43+
val defFact = async {
44+
catsRepository.getCatFact()
45+
}
46+
val defPresentation = async {
47+
catsRepository.getCatPresentation()
48+
}
49+
val (fact, presentation) = Pair(defFact.await(), defPresentation.await())
50+
51+
Cat(
52+
fact = fact,
53+
presentation = presentation,
54+
)
55+
}
56+
4657
fun attachView(catsView: ICatsView) {
4758
_catsView = catsView
4859
}
4960

5061
fun detachView() {
51-
_catsView = null
52-
}
53-
54-
fun dispose() {
5562
cancelCatJob()
63+
_catsView = null
5664
}
5765

5866
private fun cancelCatJob() {
Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,25 @@
11
package otus.homework.coroutines
22

3-
import kotlinx.coroutines.Dispatchers
4-
import kotlinx.coroutines.async
3+
import kotlinx.coroutines.CoroutineDispatcher
54
import kotlinx.coroutines.withContext
65

76
interface ICatsRepository {
8-
suspend fun getCat(): Cat
7+
suspend fun getCatFact(): Fact
8+
suspend fun getCatPresentation(): Presentation
99
}
1010

1111
class CatsRepositoryImpl(
12+
private val ioDispatcher: CoroutineDispatcher,
1213
private val service: CatsService,
1314
) : ICatsRepository {
14-
override suspend fun getCat(): Cat = withContext(Dispatchers.IO) {
15-
val defFact = async {
16-
getCatFact()
17-
}
18-
val defPresentation = async {
19-
getCatPresentation()
20-
}
21-
val (fact, presentation) = Pair(defFact.await(), defPresentation.await())
22-
Cat(
23-
fact = fact,
24-
presentation = presentation,
25-
)
26-
}
27-
28-
private suspend fun getCatFact(): Fact {
29-
return service.getCatFact(Endpoints.FACTS_BASE_URL + "fact").toDomain()
15+
override suspend fun getCatFact(): Fact = withContext(ioDispatcher) {
16+
service.getCatFact(Endpoints.FACTS_BASE_URL + "fact").toDomain()
3017
}
3118

32-
private suspend fun getCatPresentation(): Presentation {
33-
return service.getCatPresentation(Endpoints.PRESENTATION_BASE_URL)
34-
.firstOrNull()?.toDomain()
35-
?: throw Exception("first presentation not found")
36-
}
19+
override suspend fun getCatPresentation(): Presentation =
20+
withContext(ioDispatcher) {
21+
service.getCatPresentation(Endpoints.PRESENTATION_BASE_URL)
22+
.firstOrNull()?.toDomain()
23+
?: throw Exception("first presentation not found")
24+
}
3725
}

app/src/main/java/otus/homework/coroutines/CatsView.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.util.AttributeSet
55
import android.widget.Button
66
import android.widget.ImageView
77
import android.widget.TextView
8+
import android.widget.Toast
89
import androidx.constraintlayout.widget.ConstraintLayout
910
import com.squareup.picasso.Picasso
1011

@@ -14,7 +15,7 @@ class CatsView @JvmOverloads constructor(
1415
defStyleAttr: Int = 0
1516
) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView {
1617

17-
var presenter :CatsPresenter? = null
18+
var presenter: CatsPresenter? = null
1819

1920
override fun onFinishInflate() {
2021
super.onFinishInflate()
@@ -37,9 +38,19 @@ class CatsView @JvmOverloads constructor(
3738
.load(presentation.url)
3839
.into(findViewById<ImageView>(R.id.picture_imageView))
3940
}
41+
42+
override fun showToast(text: String) {
43+
Toast.makeText(
44+
context,
45+
text,
46+
Toast.LENGTH_SHORT,
47+
).show()
48+
}
4049
}
4150

4251
interface ICatsView {
4352

4453
fun populate(cat: Cat)
54+
55+
fun showToast(text: String)
4556
}

app/src/main/java/otus/homework/coroutines/CatsViewModel.kt

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package otus.homework.coroutines
22

3+
import androidx.lifecycle.LiveData
34
import androidx.lifecycle.MutableLiveData
45
import androidx.lifecycle.ViewModel
56
import androidx.lifecycle.ViewModelProvider
67
import androidx.lifecycle.viewModelScope
7-
import kotlinx.coroutines.CancellationException
88
import kotlinx.coroutines.CoroutineExceptionHandler
99
import kotlinx.coroutines.Job
10+
import kotlinx.coroutines.async
11+
import kotlinx.coroutines.coroutineScope
1012
import kotlinx.coroutines.launch
1113
import java.net.SocketTimeoutException
1214

@@ -15,39 +17,48 @@ class CatsViewModel(
1517
): ViewModel() {
1618
private var _catsJob: Job? = null
1719

18-
val uiState = MutableLiveData<Result<Cat>>()
20+
private val mutableUiState = MutableLiveData<Result<Cat>>()
21+
val uiState: LiveData<Result<Cat>> = mutableUiState
1922

2023
private val exceptionHandle = CoroutineExceptionHandler { _, throwable ->
2124
when (throwable) {
22-
is CancellationException -> {
23-
// ...
24-
}
2525
is SocketTimeoutException -> {
26-
uiState.value = Error("Не удалось получить ответ от сервера")
26+
mutableUiState.value = Error("Не удалось получить ответ от сервера")
2727
}
2828
else -> {
2929
throwable.printStackTrace()
3030
CrashMonitor.trackWarning()
3131
throwable.message?.let { eMessage ->
32-
uiState.value = Error(eMessage)
32+
mutableUiState.value = Error(eMessage)
3333
}
3434
}
3535
}
3636
}
3737

38-
override fun onCleared() {
39-
super.onCleared()
40-
cancelCatJob()
41-
}
42-
4338
fun onInitComplete() {
4439
cancelCatJob()
4540
_catsJob = viewModelScope.launch(exceptionHandle) {
46-
val cat: Cat = catsRepository.getCat()
47-
uiState.value = Success(cat)
41+
val cat: Cat = loadCat()
42+
43+
mutableUiState.value = Success(cat)
4844
}
4945
}
5046

47+
private suspend fun loadCat(): Cat = coroutineScope {
48+
val defFact = async {
49+
catsRepository.getCatFact()
50+
}
51+
val defPresentation = async {
52+
catsRepository.getCatPresentation()
53+
}
54+
val (fact, presentation) = Pair(defFact.await(), defPresentation.await())
55+
56+
Cat(
57+
fact = fact,
58+
presentation = presentation,
59+
)
60+
}
61+
5162
private fun cancelCatJob() {
5263
_catsJob?.cancel()
5364
_catsJob = null

app/src/main/java/otus/homework/coroutines/DiContainer.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package otus.homework.coroutines
22

3+
import kotlinx.coroutines.Dispatchers
34
import retrofit2.Retrofit
45
import retrofit2.converter.gson.GsonConverterFactory
56

@@ -17,6 +18,7 @@ class DiContainer {
1718

1819
val repository: ICatsRepository by lazy {
1920
CatsRepositoryImpl(
21+
ioDispatcher = Dispatchers.IO,
2022
service = service,
2123
)
2224
}

app/src/main/java/otus/homework/coroutines/MainActivity.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ class MainActivity : AppCompatActivity() {
2323
val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView
2424
setContentView(view)
2525

26-
catsPresenter = CatsPresenter(
27-
context = applicationContext,
28-
catsRepository = diContainer.repository,
29-
)
26+
catsPresenter = CatsPresenter(diContainer.repository)
3027
view.presenter = catsPresenter
3128
// catsPresenter.attachView(view)
3229
// catsPresenter.onInitComplete()
@@ -50,7 +47,6 @@ class MainActivity : AppCompatActivity() {
5047
if (isFinishing) {
5148
catsPresenter.detachView()
5249
}
53-
catsPresenter.dispose()
5450
super.onStop()
5551
}
5652
}

app/src/main/java/otus/homework/coroutines/PresenterScope.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ class PresenterScope : CoroutineScope {
1010
get() = Dispatchers.Main + CoroutineName(NAME)
1111

1212
companion object {
13-
const val NAME = "CatsCoroutine"
13+
private const val NAME = "CatsCoroutine"
1414
}
1515
}

0 commit comments

Comments
 (0)