![](/img/trans.png)
[英]Using the repository functions in the viewModel with coruntineScope in android Room
[英]Compose and Room: Issue with initializing ViewModel with a repository
我目前正在關注帶有 View codelab 的 Android Room,並嘗試將其與 Jetpack Compose 結合使用。 我堅持在 function 中初始化 viewModel。
我得到的錯誤:
None of the following functions can be called with the arguments supplied:
public inline fun <reified VM : ViewModel> viewModel(viewModelStoreOwner: ViewModelStoreOwner = ..., key: String? = ..., factory: ViewModelProvider.Factory? = ...): TypeVariable(VM) defined in androidx.lifecycle.viewmodel.compose
public fun <VM : ViewModel> viewModel(modelClass: Class<TypeVariable(VM)>, viewModelStoreOwner: ViewModelStoreOwner = ..., key: String? = ..., factory: ViewModelProvider.Factory? = ...): TypeVariable(VM) defined in androidx.lifecycle.viewmodel.compose
@Composable
fun WordBookApp() {
val context = LocalContext.current
val wordViewModel: WordViewModel by viewModel( // error here - viewModel
WordViewModelFactory((context.applicationContext as WordsApplication).repository)
)
val words: List<Word> by wordViewModel.allWords.observeAsState(listOf())
...
視圖 Model 和視圖 Model 工廠:
class WordViewModel(private val repository: WordRepository) : ViewModel() {
val allWords: LiveData<List<Word>> = repository.allWords.asLiveData()
fun insert(word: Word) = viewModelScope.launch {
repository.insert(word)
}
}
class WordViewModelFactory(private val repository: WordRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(WordViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return WordViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
代碼的其他部分:
class WordRepository(private val wordDao: WordDao) {
val allWords: Flow<List<Word>> = wordDao.getAlphabetizedWords()
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun insert(word: Word) {
wordDao.insert(word)
}
}
class WordsApplication : Application() {
private val database by lazy { WordRoomDatabase.getDatabase(this) }
val repository by lazy { WordRepository(database.wordDao()) }
}
@Database(entities = [Word::class], version = 1, exportSchema = false)
public abstract class WordRoomDatabase : RoomDatabase() {
abstract fun wordDao(): WordDao
companion object {
// Singleton prevents multiple instances of database opening at the
// same time.
@Volatile
private var INSTANCE: WordRoomDatabase? = null
fun getDatabase(context: Context): WordRoomDatabase {
// if the INSTANCE is not null, then return it,
// if it is, then create the database
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
WordRoomDatabase::class.java,
"word_database"
).build()
INSTANCE = instance
// return instance
instance
}
}
}
}
AndroidMenifest.xml
<application
android:name=".WordsApplication"
....
有人可以幫忙嗎? 謝謝!
因為你沒有提到這個問題,我已經開始輸入這個了。 這可能與您的問題無關,但也許您仍然應該閱讀此內容。
如果問題是視圖模型中的值沒有更新, - 在可組合的內部初始化視圖模型,這是一個非常糟糕的主意。
您會看到可組合項經常進行重組,重新執行其中的每一行代碼。 因此,如果您像這樣初始化此可組合項內的視圖模型,它將在每次重新組合時重新初始化。 理論上,即使在幀速率下也可以進行重組(在許多情況下甚至可以)。 因此,這不是在可組合項中聲明變量的方法。
好的, remember
可組合項可以幫助您解決這個問題。 如果你用remember
包裝初始化語句,它不會在重組時重新初始化。 但是,它有其局限性。 例如,如果可組合項被銷毀,例如,如果您將其滑出屏幕,則remember
值將丟失。 remember
隨包含它的可組合項的銷毀而被銷毀。
因此,對於像動畫之類的小東西,可以將變量存儲在可組合項中,但對於重要的東西,你不應該相信這個框架。
因此,最好的方法是在您的主要活動中初始化視圖模型,然后將其方法和變量傳遞給可組合項。 您甚至可以傳遞視圖模型本身,但大多數時候不需要。
代碼:
@Composable
fun WordBookApp() {
val context = LocalContext.current
val wordViewModel: WordViewModel by remember {
viewModel( // error here - viewModel
WordViewModelFactory((context.applicationContext as WordsApplication).repository)
)
}
val words: List<Word> by wordViewModel.allWords.observeAsState(listOf())
...
從@MARSK 的回答中得到線索並修復了它。 將視圖 model 的初始化移動到MainActivity
的onCreate()
,並將其傳遞給可組合的 function。現在一切正常!
這是代碼,如果將來有人需要的話:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
val wordViewModel by viewModels<WordViewModel> {
WordViewModelFactory((this.applicationContext as WordsApplication).repository)
}
setContent {
WordBookApp(wordViewModel)
}
}
}
@Composable
fun WordBookApp(wordViewModel: WordViewModel) {
val words: List<Word> by wordViewModel.allWords.observeAsState(listOf())
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.