Skip to content
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

UseCase + ViewModel #22

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Examples/DemoApp/androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ android {
dependencies {
implementation(project(":shared"))
implementation(kotlin("stdlib", Build.Versions.kotlin))
implementation(Coroutines.core)
implementation(Coroutines.android)
implementation(AndroidX.appCompat)
implementation(AndroidX.coreKtx)
implementation(AndroidX.viewModel)
implementation(Libs.koinAndroid)
implementation(Libs.timber)
implementation(Libs.coil)
Expand Down
2 changes: 1 addition & 1 deletion Examples/DemoApp/androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
tools:ignore="GoogleAppIndexingWarning"
>

<activity android:name=".ui.MainActivity">
<activity android:name=".ui.KomposeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package com.jtouzy.demo.app.di

import com.jtouzy.demo.app.ui.NavigationManager
import com.jtouzy.demo.app.ui.characters.CharactersViewModel
import com.jtouzy.demo.app.ui.quote.QuoteViewModel
import com.jtouzy.demo.cache.DataStore
import com.jtouzy.demo.cache.InMemoryDataStore
import com.jtouzy.demo.network.BreakingBadApi
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module

val appModule = module {

single { NavigationManager() }
single { BreakingBadApi() }
single<DataStore> { InMemoryDataStore(get()) }

viewModel { CharactersViewModel(get()) }
viewModel { QuoteViewModel(get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ import androidx.compose.Composable
import androidx.ui.core.setContent
import androidx.ui.material.MaterialTheme
import com.jtouzy.demo.app.ui.characters.CharactersScreen
import com.jtouzy.demo.app.ui.characters.CharactersViewModel
import com.jtouzy.demo.app.ui.common.themeColors
import com.jtouzy.demo.app.ui.quote.QuoteScreen
import com.jtouzy.demo.cache.DataStore
import com.jtouzy.demo.app.ui.quote.QuoteViewModel
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel

class MainActivity : AppCompatActivity() {
class KomposeActivity : AppCompatActivity() {

private val navigationManager by inject<NavigationManager>()
private val dataStore by inject<DataStore>()
private val charactersViewModel by viewModel<CharactersViewModel>()
private val quoteViewModel by viewModel<QuoteViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -29,8 +32,8 @@ class MainActivity : AppCompatActivity() {
private fun KomposeApp() {
MaterialTheme(colors = themeColors) {
when (val screen = navigationManager.currentScreen) {
Screen.Home -> CharactersScreen.show(navigationManager, dataStore)
is Screen.Quote -> QuoteScreen.show(navigationManager, dataStore, screen.character)
Screen.Home -> CharactersScreen(navigationManager, charactersViewModel).MainScreen()
is Screen.Quote -> QuoteScreen(navigationManager, quoteViewModel).MainScreen(screen.character)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,25 @@ import androidx.ui.material.ripple.Ripple
import androidx.ui.res.stringResource
import com.jtouzy.demo.app.R
import com.jtouzy.demo.app.ui.NavigationManager
import com.jtouzy.demo.app.ui.ObservableStore
import com.jtouzy.demo.app.ui.Screen
import com.jtouzy.demo.app.ui.common.ErrorScreen
import com.jtouzy.demo.app.ui.common.LoadingScreen
import com.jtouzy.demo.app.ui.common.VectorImage
import com.jtouzy.demo.app.ui.common.image
import com.jtouzy.demo.cache.DataStore
import com.jtouzy.demo.ui.Store
import com.jtouzy.demo.ui.characters.CharactersPresenter
import com.jtouzy.demo.ui.characters.CharactersPresenterImpl
import com.jtouzy.demo.ui.characters.CharactersViewState
import com.jtouzy.demo.ui.model.Character

class CharactersScreen(
private val navigationManager: NavigationManager,
private val store: Store<CharactersViewState>,
presenter: CharactersPresenter
private val viewModel: CharactersViewModel
) {

init {
presenter.loadCharacters()
}

@Composable
private fun MainScreen() {
fun MainScreen() {
viewModel.loadCharacters()
Column {
TopAppBar(title = { Text(text = +stringResource(R.string.app_name)) })
Crossfade(store.viewState) { state ->
Crossfade(viewModel.viewState) { state ->
when (state) {
CharactersViewState.Loading -> LoadingScreen()
is CharactersViewState.Content -> CharacterList(state.characters)
Expand Down Expand Up @@ -92,12 +83,4 @@ class CharactersScreen(
}
}
}

companion object {
fun show(navigationManager: NavigationManager, dataStore: DataStore) {
val store = ObservableStore<CharactersViewState>(CharactersViewState.Loading)
val presenter = CharactersPresenterImpl(store, dataStore)
CharactersScreen(navigationManager, store, presenter).MainScreen()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.jtouzy.demo.app.ui.characters

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.jtouzy.demo.app.ui.ObservableStore
import com.jtouzy.demo.cache.DataStore
import com.jtouzy.demo.ui.characters.CharactersUseCase
import com.jtouzy.demo.ui.characters.CharactersViewState
import kotlinx.coroutines.launch

class CharactersViewModel(dataStore: DataStore) : ViewModel() {

val viewState: CharactersViewState
get() = store.viewState
private val store = ObservableStore<CharactersViewState>(CharactersViewState.Loading)
private val useCase = CharactersUseCase(store, dataStore)

fun loadCharacters() {
viewModelScope.launch {
useCase.asyncLoadCharacters()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,31 @@ import androidx.ui.material.TopAppBar
import androidx.ui.res.stringResource
import com.jtouzy.demo.app.R
import com.jtouzy.demo.app.ui.NavigationManager
import com.jtouzy.demo.app.ui.ObservableStore
import com.jtouzy.demo.app.ui.common.ErrorScreen
import com.jtouzy.demo.app.ui.common.LoadingScreen
import com.jtouzy.demo.app.ui.common.VectorImageButton
import com.jtouzy.demo.cache.DataStore
import com.jtouzy.demo.ui.Store
import com.jtouzy.demo.ui.model.Character
import com.jtouzy.demo.ui.model.Quote
import com.jtouzy.demo.ui.quotes.QuotesPresenter
import com.jtouzy.demo.ui.quotes.QuotesPresenterImpl
import com.jtouzy.demo.ui.quotes.QuotesViewState

class QuoteScreen(
private val navigationManager: NavigationManager,
private val store: Store<QuotesViewState>,
presenter: QuotesPresenter
private val viewModel: QuoteViewModel
) {

init {
presenter.loadQuotes()
}

@Composable
private fun MainScreen() {
fun MainScreen(character: Character) {
viewModel.loadQuote(character)
Column {
TopAppBar(
title = { Text(store.viewState.title) },
title = { Text(viewModel.viewState.title) },
navigationIcon = {
VectorImageButton(R.drawable.ic_back) {
navigationManager.pop()
}
}
)
Crossfade(store.viewState) { state ->
Crossfade(viewModel.viewState) { state ->
when (state) {
is QuotesViewState.Loading -> LoadingScreen()
is QuotesViewState.Content -> QuoteList(state.quotes)
Expand Down Expand Up @@ -87,12 +78,4 @@ class QuoteScreen(
Divider(color = (+MaterialTheme.colors()).onBackground)
}
}

companion object {
fun show(navigationManager: NavigationManager, dataStore: DataStore, character: Character) {
val store = ObservableStore<QuotesViewState>(QuotesViewState.Loading(character.name))
val presenter = QuotesPresenterImpl(store, dataStore, character)
QuoteScreen(navigationManager, store, presenter).MainScreen()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.jtouzy.demo.app.ui.quote

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.jtouzy.demo.app.ui.ObservableStore
import com.jtouzy.demo.cache.DataStore
import com.jtouzy.demo.ui.model.Character
import com.jtouzy.demo.ui.quotes.QuotesUseCase
import com.jtouzy.demo.ui.quotes.QuotesViewState
import kotlinx.coroutines.launch

class QuoteViewModel(dataStore: DataStore) : ViewModel() {

val viewState: QuotesViewState
get() = store.viewState
private val store = ObservableStore<QuotesViewState>(QuotesViewState.Loading(""))
private val useCase = QuotesUseCase(store, dataStore)

fun loadQuote(character: Character) {
viewModelScope.launch {
useCase.asyncLoadQuotes(character)
}
}
}
33 changes: 12 additions & 21 deletions Examples/DemoApp/buildSrc/src/main/kotlin/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,42 +37,26 @@ object Libs {
private object Versions {
const val timber = "4.7.1"
const val koin = "2.0.1"
const val uniflow = "0.9.3"
const val coil = "0.9.2"
const val jsr310 = "1.2.1"
}

const val timber = "com.jakewharton.timber:timber:${Versions.timber}"
const val koinAndroid = "org.koin:koin-androidx-viewmodel:${Versions.koin}"
const val uniflow = "io.uniflow:uniflow-androidx:${Versions.uniflow}"
const val coil = "io.coil-kt:coil:${Versions.coil}"
const val jsr310 = "com.jakewharton.threetenabp:threetenabp:${Versions.jsr310}"
}

object Google {

private object Versions {
const val material = "1.1.0-beta02"
const val firebaseCore = "17.2.1"
const val firebaseMessaging = "20.0.1"
}

const val material = "com.google.android.material:material:${Versions.material}"
const val firebaseCore = "com.google.firebase:firebase-core:${Versions.firebaseCore}"
const val firebaseMessaging = "com.google.firebase:firebase-messaging:${Versions.firebaseMessaging}"
}


object AndroidX {

private object Versions {
const val appCompat = "1.1.0"
const val coreKtx = "1.1.0"
const val viewModel = "2.1.0-beta01"
const val compose = "0.1.0-dev03"
}

const val appCompat = "androidx.appcompat:appcompat:${Versions.appCompat}"
const val coreKtx = "androidx.core:core-ktx:${Versions.coreKtx}"
const val viewModel = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.viewModel}"

const val composeFoundation = "androidx.ui:ui-foundation:${Versions.compose}"
const val composeFramework = "androidx.ui:ui-framework:${Versions.compose}"
Expand All @@ -84,9 +68,9 @@ object AndroidX {

object Coroutines {

private const val version = "1.3.3"
const val version = "1.3.3"

const val core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version"
const val common = "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$version"
const val android = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version"
const val native = "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$version"
}
Expand All @@ -102,7 +86,7 @@ object Serialization {

object Ktor {

private const val version = "1.2.6"
private const val version = "1.3.0"

// Common
const val clientCore = "io.ktor:ktor-client-core:$version"
Expand All @@ -120,3 +104,10 @@ object Ktor {
const val clientSerializationIos = "io.ktor:ktor-client-serialization-iosx64:$version"
const val clientLoggingIos = "io.ktor:ktor-client-logging-native:$version"
}

object Tests {

const val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Coroutines.version}"
const val androidxTestJunit = "androidx.test.ext:junit:1.1.1"
const val mockk = "io.mockk:mockk:1.9.3"
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import shared
class CharactersAssembler {
static func assemble() -> CharactersView {
let store = ObservableStore<CharactersViewState>(baseState: CharactersViewState.Loading())
let presenter = CharactersPresenterImpl(store: store, dataStore: Factory.dataStore)
return CharactersView(presenter: presenter, store: store)
let useCase = CharactersUseCase(store: store, dataStore: Factory.dataStore)
return CharactersView(useCase: useCase, store: store)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import shared
// MARK: View Layout
//
struct CharactersView: View {
let presenter: CharactersPresenter
let useCase: CharactersUseCase
@ObservedObject var store: ObservableStore<CharactersViewState>
var viewState: CharactersViewState { store.state }

Expand Down Expand Up @@ -55,6 +55,6 @@ struct CharactersView: View {
//
extension CharactersView {
func onViewAppear() {
presenter.loadCharacters()
useCase.loadCharacters()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ class QuotesAssembler {
let store = ObservableStore<QuotesViewState>(
baseState: QuotesViewState.Loading(title: character.name)
)
let presenter = QuotesPresenterImpl(
store: store, dataStore: Factory.dataStore, character: character
let useCase = QuotesUseCase(
store: store, dataStore: Factory.dataStore
)
return QuotesView(presenter: presenter, store: store)
return QuotesView(useCase: useCase, store: store, character: character)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import shared
// MARK: View Layout
//
struct QuotesView: View {
let presenter: QuotesPresenter
let useCase: QuotesUseCase
@ObservedObject var store: ObservableStore<QuotesViewState>
let character: Character
var viewState: QuotesViewState { store.state }

var body: some View {
Expand Down Expand Up @@ -57,6 +58,6 @@ struct QuotesView: View {
//
extension QuotesView {
func onViewAppear() {
presenter.loadQuotes()
useCase.loadQuotes(character)
}
}
Loading