Skip to content

Commit

Permalink
Move ViewModel to shared KMP common module (#29)
Browse files Browse the repository at this point in the history
* Switch to lifecycle-common after 2.8.0 release
  * https://developer.android.com/jetpack/androidx/releases/lifecycle#2.8.0
* Compose UI 1.7.0-beta07
* Move ViewModel to shared module to prepare for KMP
* Instantiate ViewModel with CreationExtras
* Update to 2.9.0-alpha01 to include CreationExtras.Key() inline method
  • Loading branch information
cartland authored Aug 27, 2024
1 parent da24272 commit 4650a3e
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Fruitties/androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ dependencies {
implementation(libs.compose.material3)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.paging.compose.android)
implementation(libs.androidx.viewmodel.compose)
implementation(libs.androidx.lifecycle.viewmodel.compose)
debugImplementation(libs.compose.ui.tooling)
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,38 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.fruitties.android.R
import com.example.fruitties.android.di.App
import com.example.fruitties.database.CartItemDetails
import com.example.fruitties.model.Fruittie
import com.example.fruitties.viewmodel.MainViewModel

@Composable
fun ListScreen(viewModel: MainViewModel = viewModel(factory = MainViewModel.Factory)) {
fun ListScreen() {
// Instantiate a ViewModel with a dependency on the AppContainer.
// To make ViewModel compatible with KMP, the ViewModel factory must
// create an instance without referencing the Android Application.
// Here we put the KMP-compatible AppContainer into the extras
// so it can be passed to the ViewModel factory.
val app = LocalContext.current.applicationContext as App
val extras = remember(app) {
MutableCreationExtras().apply {
set(MainViewModel.APP_CONTAINER_KEY, app.container)
}
}
val viewModel: MainViewModel = viewModel(
factory = MainViewModel.Factory,
extras = extras,
)

val uiState by viewModel.uiState.collectAsState()
val cartState by viewModel.cartUiState.collectAsState()

Expand Down
10 changes: 5 additions & 5 deletions Fruitties/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ agp = "8.5.2"
androidx-activityCompose = "1.9.1"
androidx-paging = "3.3.2"
androidx-room = "2.7.0-alpha06"
androidx-viewmodelCompose = "2.8.4"
androidx-lifecycle = "2.9.0-alpha01"
atomicfu = "0.23.1"
compose = "1.6.8"
compose = "1.7.0-beta07"
compose-material3 = "1.2.1"
dataStoreVersion = "1.1.1"
kotlin = "2.0.10"
Expand All @@ -29,7 +29,7 @@ ksp = "2.0.10-1.0.24"
ktorVersion = "2.3.8"
pagingComposeAndroid = "3.3.2"
skie = "0.8.4"
sqlite = "2.5.0-alpha06"
sqlite = "2.5.0-alpha07"
spotless = "6.19.0"

[libraries]
Expand All @@ -41,8 +41,8 @@ androidx-paging-compose-android = { group = "androidx.paging", name = "paging-co
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "androidx-room" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "androidx-room" }
androidx-room-paging = { group = "androidx.room", name = "room-paging", version.ref = "androidx-room" }
androidx-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-viewmodelCompose" }
compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" }
androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "compose-material3" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
Expand Down
1 change: 1 addition & 0 deletions Fruitties/shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ kotlin {
implementation(libs.ktor.client.content.negotiation)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(libs.skie.annotations)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.paging.common)
implementation(libs.androidx.room.runtime)
implementation(libs.sqlite.bundled)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@
* limitations under the License.
*/

package com.example.fruitties.android.ui
package com.example.fruitties.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.fruitties.DataRepository
import com.example.fruitties.android.di.App
import com.example.fruitties.database.CartItemDetails
import com.example.fruitties.di.AppContainer
import com.example.fruitties.model.Fruittie
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -57,10 +57,13 @@ class MainViewModel(private val repository: DataRepository) : ViewModel() {
}

companion object {

val APP_CONTAINER_KEY = CreationExtras.Key<AppContainer>()

val Factory: ViewModelProvider.Factory = viewModelFactory {
initializer {
val application = (this[APPLICATION_KEY] as App)
val repository = application.container.dataRepository
val appContainer = this[APP_CONTAINER_KEY] as AppContainer
val repository = appContainer.dataRepository
MainViewModel(repository = repository)
}
}
Expand Down

0 comments on commit 4650a3e

Please sign in to comment.