Skip to content

Commit 6dceb08

Browse files
author
Vladislav Sviridov
committed
Code review fixes Otus-Android#1
1 parent 44efc78 commit 6dceb08

File tree

7 files changed

+85
-76
lines changed

7 files changed

+85
-76
lines changed
Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
package otus.homework.coroutines
22

3-
import androidx.lifecycle.LiveData
4-
import androidx.lifecycle.MutableLiveData
5-
import androidx.lifecycle.ViewModel
6-
import androidx.lifecycle.viewModelScope
7-
import kotlinx.coroutines.*
3+
import androidx.lifecycle.*
4+
import kotlinx.coroutines.CoroutineExceptionHandler
5+
import kotlinx.coroutines.async
6+
import kotlinx.coroutines.launch
87
import java.net.SocketTimeoutException
98

10-
class CatViewModel(private val catsService: CatsService = DiContainer.service) : ViewModel() {
11-
12-
private var job: Job? = null
9+
class CatViewModel(private val catsService: CatsService) : ViewModel() {
1310

1411
private val stateLiveData = MutableLiveData<Result<CatUiState>>()
1512
val state: LiveData<Result<CatUiState>> = stateLiveData
@@ -23,25 +20,13 @@ class CatViewModel(private val catsService: CatsService = DiContainer.service) :
2320
CrashMonitor.trackWarning(exception)
2421
}
2522

26-
fun onStart() {
27-
requestFact()
28-
}
29-
30-
fun onStop() {
31-
job?.cancel()
32-
job = null
33-
}
34-
3523
fun requestFact() {
36-
if (job != null && job!!.isActive)
37-
return
38-
39-
job = viewModelScope.launch(handler) {
40-
val fact = async(Dispatchers.IO) {
24+
viewModelScope.launch(handler) {
25+
val fact = async {
4126
catsService.getCatFact()
4227
}
4328

44-
val image = async(Dispatchers.IO) {
29+
val image = async {
4530
catsService.getCatImage()
4631
}
4732

@@ -51,3 +36,10 @@ class CatViewModel(private val catsService: CatsService = DiContainer.service) :
5136
}
5237
}
5338
}
39+
40+
@Suppress("UNCHECKED_CAST")
41+
class CatViewModelFactory(private val catsService: CatsService) : ViewModelProvider.Factory {
42+
override fun <T : ViewModel> create(modelClass: Class<T>): T {
43+
return CatViewModel(catsService) as T
44+
}
45+
}

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

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,60 +4,47 @@ import kotlinx.coroutines.*
44
import java.net.SocketTimeoutException
55

66
class CatsPresenter(
7-
private val catsService: CatsService
7+
private val catsService: CatsService,
8+
private val presenterScope: CoroutineScope
89
) {
9-
10-
private var requestJob: Job? = null
1110
private var _catsView: ICatsView? = null
12-
13-
private val presenterScope = MainScope() + CoroutineName("CatsCoroutine")
1411
private val catsView get() = checkNotNull(_catsView)
1512

1613
fun onInitComplete() {
17-
loadData()
14+
presenterScope.launch {
15+
loadData()
16+
}
1817
}
1918

2019
fun attachView(catsView: ICatsView) {
2120
_catsView = catsView
2221
}
2322

2423
fun detachView() {
25-
presenterScope.cancel()
2624
_catsView = null
2725
}
2826

29-
fun onStart() {
30-
loadData()
31-
}
32-
33-
fun onStop() {
34-
requestJob?.cancel()
35-
requestJob = null
27+
fun stop() {
28+
presenterScope.cancel()
3629
}
3730

38-
private fun loadData() {
39-
if (requestJob != null && requestJob!!.isActive)
40-
return
41-
42-
requestJob = presenterScope.launch {
43-
try {
44-
coroutineScope {
45-
val fact = async(Dispatchers.IO) {
46-
catsService.getCatFact()
47-
}
48-
49-
val image = async(Dispatchers.IO) {
50-
catsService.getCatImage()
51-
}
31+
private suspend fun loadData() =
32+
try {
33+
coroutineScope {
34+
val fact = async {
35+
catsService.getCatFact()
36+
}
5237

53-
catsView.populate(CatUiState(fact.await(), image.await()))
38+
val image = async {
39+
catsService.getCatImage()
5440
}
55-
} catch (timeoutException: SocketTimeoutException) {
56-
catsView.showMessage("Не удалось получить ответ от сервера")
57-
} catch (exception: Exception) {
58-
catsView.showMessage("Упс, произошла ошибка: ${exception.message}")
59-
CrashMonitor.trackWarning(exception)
41+
42+
catsView.populate(CatUiState(fact.await(), image.await()))
6043
}
44+
} catch (timeoutException: SocketTimeoutException) {
45+
catsView.showMessage("Не удалось получить ответ от сервера")
46+
} catch (exception: Exception) {
47+
catsView.showMessage("Упс, произошла ошибка: ${exception.message}")
48+
CrashMonitor.trackWarning(exception)
6149
}
62-
}
6350
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
package otus.homework.coroutines
22

3+
import okhttp3.OkHttpClient
34
import retrofit2.Retrofit
45
import retrofit2.converter.gson.GsonConverterFactory
56

67
object DiContainer {
78

9+
private val client = OkHttpClient.Builder().addInterceptor(MockInterceptor()).build()
10+
811
private val retrofit by lazy {
912
Retrofit.Builder()
13+
.client(client)
1014
.baseUrl("https://cat-fact.herokuapp.com/facts/")
1115
.addConverterFactory(GsonConverterFactory.create())
1216
.build()
1317
}
1418

1519
val service by lazy { retrofit.create(CatsService::class.java) }
20+
21+
val scope by lazy(mode = LazyThreadSafetyMode.NONE) {
22+
PresenterScope()
23+
}
1624
}

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class MainActivity : AppCompatActivity() {
1616
val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView
1717
setContentView(view)
1818

19-
catsPresenter = CatsPresenter(DiContainer.service)
19+
catsPresenter = CatsPresenter(DiContainer.service, DiContainer.scope)
2020
view.presenter = catsPresenter
2121
catsPresenter.attachView(view)
2222
catsPresenter.onInitComplete()
@@ -28,12 +28,7 @@ class MainActivity : AppCompatActivity() {
2828
}
2929
super.onStop()
3030

31-
catsPresenter.onStop()
32-
}
33-
34-
override fun onStart() {
35-
super.onStart()
36-
catsPresenter.onStart()
31+
catsPresenter.stop()
3732
}
3833

3934
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package otus.homework.coroutines
2+
3+
import okhttp3.*
4+
5+
class MockInterceptor : Interceptor {
6+
override fun intercept(chain: Interceptor.Chain): Response {
7+
val request = chain.request()
8+
9+
if (request.url().host() == "cat-fact.herokuapp.com") {
10+
val contentType = "application/json"
11+
val body = "{\"text\": \"Cats have nine lives\"}"
12+
13+
return Response.Builder()
14+
.request(request)
15+
.message(body)
16+
.protocol(Protocol.HTTP_1_0)
17+
.code(200)
18+
.header("content-type", contentType)
19+
.body(ResponseBody.create(MediaType.get(contentType), body))
20+
.build()
21+
}
22+
23+
return chain.proceed(request)
24+
}
25+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package otus.homework.coroutines
2+
3+
import kotlinx.coroutines.CoroutineName
4+
import kotlinx.coroutines.CoroutineScope
5+
import kotlinx.coroutines.Dispatchers
6+
import kotlinx.coroutines.SupervisorJob
7+
import kotlin.coroutines.CoroutineContext
8+
9+
class PresenterScope : CoroutineScope {
10+
override val coroutineContext: CoroutineContext
11+
get() = SupervisorJob() + Dispatchers.Main + CoroutineName("CatsCoroutine")
12+
}

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import androidx.activity.viewModels
66
import androidx.appcompat.app.AppCompatActivity
77

88
class ViewModelActivity : AppCompatActivity() {
9-
private val viewModel by viewModels<CatViewModel>()
9+
private val viewModel by viewModels<CatViewModel> { CatViewModelFactory(DiContainer.service) }
1010

1111
override fun onCreate(savedInstanceState: Bundle?) {
1212
super.onCreate(savedInstanceState)
@@ -28,14 +28,4 @@ class ViewModelActivity : AppCompatActivity() {
2828
}
2929
}
3030
}
31-
32-
override fun onStart() {
33-
super.onStart()
34-
viewModel.onStart()
35-
}
36-
37-
override fun onStop() {
38-
super.onStop()
39-
viewModel.onStop()
40-
}
4131
}

0 commit comments

Comments
 (0)