Skip to content

Commit 94a663b

Browse files
Add line chart to Flow Use Case 1
1 parent c0e6f1c commit 94a663b

File tree

12 files changed

+80
-67
lines changed

12 files changed

+80
-67
lines changed

.idea/jarRepositories.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ dependencies {
9393
implementation "androidx.room:room-ktx:$room_version"
9494
kapt "androidx.room:room-compiler:$room_version"
9595

96+
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
97+
9698
testImplementation project(path: ':app')
9799

98100
testImplementation 'junit:junit:4.12'

app/src/main/java/com/lukaslechner/coroutineusecasesonandroid/base/UseCase.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ const val useCase16Description =
6060
const val useCase17Description =
6161
"#17 Perform heavy calculation on Main Thread without freezing the UI"
6262

63+
const val flowUseCase1Description = "#1 Read from database that exposes Flow, ViewModel exposes LiveData"
64+
6365
private val coroutinesUseCases =
6466
UseCaseCategory(
6567
"Coroutine Use Cases", listOf(
@@ -164,7 +166,7 @@ private val flowUseCases =
164166
"Flow Use Cases",
165167
listOf(
166168
UseCase(
167-
"Flow Use Case 1",
169+
flowUseCase1Description,
168170
FlowUseCase1Activity::class.java
169171
)
170172
)

app/src/main/java/com/lukaslechner/coroutineusecasesonandroid/usecases/flow/mock/FlowMockApi.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@ import retrofit2.http.GET
88

99
interface FlowMockApi {
1010

11-
@GET("current-bitcoin-price")
12-
suspend fun getCurrentBitcoinPrice(): BitcoinPrice
13-
14-
@GET("current-etherium-price")
15-
suspend fun getCurrentEtheriumPrice(): EtheriumPrice
11+
@GET("current-google-stock-price")
12+
suspend fun getCurrentGoogleStockPrice(): GoogleStock
1613
}
1714

1815
fun createFlowMockApi(interceptor: MockNetworkInterceptor): FlowMockApi {

app/src/main/java/com/lukaslechner/coroutineusecasesonandroid/usecases/flow/mock/FlowMockData.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ package com.lukaslechner.coroutineusecasesonandroid.usecases.flow.mock
22

33
import kotlin.random.Random
44

5-
data class BitcoinPrice(val usd: Float)
5+
data class GoogleStock(val currentPriceUsd: Float)
66

7-
data class EtheriumPrice(val usd: Float)
8-
9-
fun fakeCurrentBitcoinPrice(): BitcoinPrice {
10-
val initialPrice = 50_000f
11-
val increase = Random.nextInt(1000)
7+
fun fakeCurrentGoogleStockPrice(): GoogleStock {
8+
val initialPrice = 2_000f
9+
val increase = Random.nextInt(100)
1210
val currentPrice = initialPrice + increase
13-
return BitcoinPrice(currentPrice)
11+
return GoogleStock(currentPrice)
1412
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.lukaslechner.coroutineusecasesonandroid.usecases.flow.usecase1
22

33
import android.os.Bundle
4-
import android.view.View
54
import androidx.activity.viewModels
5+
import androidx.core.content.ContextCompat
6+
import com.github.mikephil.charting.data.Entry
7+
import com.github.mikephil.charting.data.LineData
8+
import com.github.mikephil.charting.data.LineDataSet
9+
import com.lukaslechner.coroutineusecasesonandroid.R
610
import com.lukaslechner.coroutineusecasesonandroid.base.BaseActivity
11+
import com.lukaslechner.coroutineusecasesonandroid.base.flowUseCase1Description
712
import com.lukaslechner.coroutineusecasesonandroid.databinding.ActivityFlowUsecase1Binding
8-
import java.time.Instant
913

1014
class FlowUseCase1Activity : BaseActivity() {
1115

@@ -17,23 +21,60 @@ class FlowUseCase1Activity : BaseActivity() {
1721
super.onCreate(savedInstanceState)
1822
setContentView(binding.root)
1923

24+
initChart()
25+
2026
viewModel.whileTrueInCoroutine()
21-
viewModel.bitcoinPrice.observe(this) { uiState ->
27+
viewModel.currentGoogleStockPrice.observe(this) { uiState ->
2228
if (uiState != null) {
2329
render(uiState)
2430
}
2531
}
2632
}
2733

34+
private fun initChart() {
35+
val entries: ArrayList<Entry> = ArrayList()
36+
entries.add(Entry(0f, 2000f))
37+
38+
val data = LineDataSet(entries, "Google Stock Price")
39+
40+
val colorPrimary = ContextCompat.getColor(this, R.color.colorPrimary)
41+
data.color = colorPrimary
42+
data.setCircleColor(colorPrimary)
43+
44+
val lineData = LineData(data)
45+
46+
with(binding.googleStockChart) {
47+
this.data = lineData
48+
setDrawGridBackground(false)
49+
axisRight.isEnabled = false
50+
xAxis.isEnabled = false
51+
}
52+
53+
binding.googleStockChart.axisLeft.apply {
54+
axisMinimum = 1990f
55+
axisMaximum = 2100f
56+
}
57+
}
58+
2859
private fun render(uiState: UiState) {
2960
when (uiState) {
3061
is UiState.Success -> {
31-
binding.progressBar.visibility = View.GONE
32-
binding.lastFetch.text = Instant.now().epochSecond.toString()
33-
binding.bitcoinPrice.text = uiState.bitcoinPrice.usd.toString()
62+
addNewChartEntry(uiState)
3463
}
3564
}
3665
}
3766

38-
override fun getToolbarTitle() = "Flow Use Case 1 Activity"
67+
private fun addNewChartEntry(uiState: UiState.Success) {
68+
val currentLineData = binding.googleStockChart.data
69+
currentLineData.addEntry(
70+
Entry(
71+
currentLineData.entryCount.toFloat(),
72+
uiState.googleStock.currentPriceUsd
73+
), 0
74+
)
75+
binding.googleStockChart.data = currentLineData
76+
binding.googleStockChart.invalidate()
77+
}
78+
79+
override fun getToolbarTitle() = flowUseCase1Description
3980
}

app/src/main/java/com/lukaslechner/coroutineusecasesonandroid/usecases/flow/usecase1/FlowUseCase1ViewModel.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ class FlowUseCase1ViewModel(
1111
private val mockApi: FlowMockApi = mockApi()
1212
) : BaseViewModel<UiState>() {
1313

14-
val bitcoinPrice = MutableLiveData<UiState>(UiState.Loading)
14+
val currentGoogleStockPrice = MutableLiveData<UiState>(UiState.Loading)
1515

1616
fun whileTrueInCoroutine() {
1717
viewModelScope.launch {
1818
while (true) {
19-
val currentBitcoinPrice = mockApi.getCurrentBitcoinPrice()
20-
bitcoinPrice.value = UiState.Success(currentBitcoinPrice)
21-
delay(5_000)
19+
val currentGoogleStockPrice = mockApi.getCurrentGoogleStockPrice()
20+
this@FlowUseCase1ViewModel.currentGoogleStockPrice.value = UiState.Success(currentGoogleStockPrice)
21+
delay(2000)
2222
}
2323
}
2424
}

app/src/main/java/com/lukaslechner/coroutineusecasesonandroid/usecases/flow/usecase1/MockApi.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ package com.lukaslechner.coroutineusecasesonandroid.usecases.flow.usecase1
22

33
import com.google.gson.Gson
44
import com.lukaslechner.coroutineusecasesonandroid.usecases.flow.mock.createFlowMockApi
5-
import com.lukaslechner.coroutineusecasesonandroid.usecases.flow.mock.fakeCurrentBitcoinPrice
5+
import com.lukaslechner.coroutineusecasesonandroid.usecases.flow.mock.fakeCurrentGoogleStockPrice
66
import com.lukaslechner.coroutineusecasesonandroid.utils.MockNetworkInterceptor
77

88
fun mockApi() =
99
createFlowMockApi(
1010
MockNetworkInterceptor()
1111
.mock(
12-
path = "http://localhost/current-bitcoin-price",
13-
body = { Gson().toJson(fakeCurrentBitcoinPrice()) },
12+
path = "http://localhost/current-google-stock-price",
13+
body = { Gson().toJson(fakeCurrentGoogleStockPrice()) },
1414
status = 200,
15-
delayInMs = 1500,
15+
delayInMs = 100,
1616
)
1717
)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package com.lukaslechner.coroutineusecasesonandroid.usecases.flow.usecase1
22

3-
import com.lukaslechner.coroutineusecasesonandroid.usecases.flow.mock.BitcoinPrice
3+
import com.lukaslechner.coroutineusecasesonandroid.usecases.flow.mock.GoogleStock
44

55
sealed class UiState {
66
object Loading : UiState()
7-
data class Success(val bitcoinPrice: BitcoinPrice) : UiState()
7+
data class Success(val googleStock: GoogleStock) : UiState()
88
data class Error(val message: String) : UiState()
99
}

0 commit comments

Comments
 (0)