![](/img/trans.png)
[英]Pass parameter WeakReference<View> to method of ViewModel?
[英]Android viewmodel pass parameter to view model from view
我有一個片段代碼 -
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val safeArgs: PetDetailsViewArgs by navArgs()
val petId = safeArgs.petId
viewModel.getPetDetailsForId(petId).observe(viewLifecycleOwner, {
// ...
})
}
我有一個 ViewModel 代碼 -
private val viewState = PetDetailsViewState()
fun getPetDetailsForId(id: String?): LiveData<PetDetailsViewState> {
return if (id.isNullOrEmpty()) {
liveData {
emit(
viewState.copy(
loading = false,
error = ErrorType.PET_ID_NULL_OR_EMPTY
)
)
}
} else {
petDetailsLiveData
}
}
var petDetailsLiveData = petService.performPetAction(PetAction.GetPetDetails("2")).map {
when (it) {
// ...
}
}.asLiveData(Dispatchers.Default + viewModelScope.coroutineContext)
正如您在我的 ViewModel 中看到的,我目前正在對PetAction.GetPetDetails("2")
中的 id 進行硬編碼,這是不正確的。
如何將 id 從我的視圖傳遞給 viewModel?
您有兩個選擇,如果petId
(來自 Fragment)沒有改變,您可以創建/注入您的 ViewModel 並通過構造函數傳遞petId
。
您的petId
可以是null
嗎? 如果沒有,您可以直接初始化您的 LiveData 並從您的片段中觀察它。
class PetViewModel(petId: String): ViewModel() {
val petDetailsLiveData = petService.performPetAction(PetAction.GetPetDetails(petId)).map {
// ...
}.asLiveData(Dispatchers.Default + viewModelScope.coroutineContext)
}
第二個選項,正如您在問題中顯示的那樣,如果petId
可以更改,請在 function getPetDetailsForId(id: String?)
中創建 LiveData。
fun getPetDetailsForId(id: String?): LiveData<PetDetailsViewState> {
return if (id.isNullOrEmpty()) {
liveData {
emit(
viewState.copy(
loading = false,
error = ErrorType.PET_ID_NULL_OR_EMPTY
)
)
}
} else {
petService.performPetAction(PetAction.GetPetDetails("2")).map {
// ...
}.asLiveData(Dispatchers.Default + viewModelScope.coroutineContext)
}
討論后
您可以考慮對您的petId
和PetDetailsViewState
進行一些緩存,以避免重復的 api 調用。 以這個非常簡單的例子來理解這個想法。 這里有很多需要改進的地方。
class PetViewModel : ViewModel() {
private val cachedPetDetailsViewState: PetDetailsViewState? = null
private val cachedPetId: String = ""
fun getPetDetailsForId(id: String?): LiveData<PetDetailsViewState> {
if (id == cachedPetId && cachedPetDetailsViewState != null) return MutableLiveData(cachedPetDetailsViewState)
cachedPetId == id
if (id.isNullOrEmpty() { ... }
else {
val petIdViewState = // make the API call
cachedPetDetailsViewState = petIdViewState
return MutableLiveData(petIdViewState)
}
}
}
找到了一種方法來處理savedStateHandle
-
這是我的片段-
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.petDetailsViewData.observe(viewLifecycleOwner, {
})
}
視圖模型 -
class PetDetailsViewModel @ViewModelInject constructor(
private val petService: PetService,
@Assisted private val savedStateHandle: SavedStateHandle
) :
ViewModel() {
private val viewState = PetDetailsViewState()
var petDetailsViewData =
petService.performPetAction(PetAction.GetPetDetails(savedStateHandle.get<String>("petId")!!))
.map {
when (it) {
// ...
}
}.asLiveData(Dispatchers.Default + viewModelScope.coroutineContext)
}
我基本上在 viewModel 中使用 safeArgs 鍵並通過 savedStateHandle 訪問它。 這樣我就不需要訪問 id 和配置更改來打擾我的視圖,我只調用我的服務一次。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.