我正在从ViewModel中的DialogFragment更新LiveData值,但无法在Fragment中获取该值。
The ViewModel:
class OtpViewModel(private val otpUseCase: OtpUseCase, analyticsModel: IAnalyticsModel) : BaseViewModel(analyticsModel) {
override val globalNavModel = GlobalNavModel(titleId = R.string.otp_contact_title, hasGlobalNavBar = false)
private val _contactListLiveData = MutableLiveData<List<Contact>>()
val contactListLiveData: LiveData<List<Contact>>
get() = _contactListLiveData
private lateinit var cachedContactList: LiveData<List<Contact>>
private val contactListObserver = Observer<List<Contact>> {
_contactListLiveData.value = it
}
private lateinit var cachedResendOtpResponse: LiveData<LogonModel>
private val resendOTPResponseObserver = Observer<LogonModel> {
_resendOTPResponse.value = it
}
private var _resendOTPResponse = MutableLiveData<LogonModel>()
val resendOTPResponseLiveData: LiveData<LogonModel>
get() = _resendOTPResponse
var userSelectedIndex : Int = 0 //First otp contact selected by default
val selectedContact : LiveData<Contact>
get() = MutableLiveData(contactListLiveData.value?.get(userSelectedIndex))
override fun onCleared() {
if (::cachedContactList.isInitialized) {
cachedContactList.removeObserver(contactListObserver)
}
if (::cachedOtpResponse.isInitialized) {
cachedOtpResponse.removeObserver(otpResponseObserver)
}
super.onCleared()
}
fun updateIndex(pos: Int){
userSelectedIndex = pos
}
fun onChangeDeliveryMethod() {
navigate(
OtpVerificationHelpCodeSentBottomSheetFragmentDirections
.actionOtpContactVerificationBottomSheetToOtpChooseContactFragment()
)
}
fun onClickContactCancel() {
navigateBackTo(R.id.logonFragment, true)
}
fun retrieveContactList() {
cachedContactList = otpUseCase.fetchContactList()
cachedContactList.observeForever(contactListObserver)
}
fun resendOTP(contactId : String){
navigateBack()
cachedResendOtpResponse = otpUseCase.resendOTP(contactId)
cachedResendOtpResponse.observeForever(resendOTPResponseObserver)
}
}
The BaseViewModel:
abstract class BaseViewModel(val analyticsModel: IAnalyticsModel) : ViewModel() {
protected val _navigationCommands: SingleLiveEvent<NavigationCommand> = SingleLiveEvent()
val navigationCommands: LiveData<NavigationCommand> = _navigationCommands
abstract val globalNavModel: GlobalNavModel
/**
* Posts a navigation event to the navigationsCommands LiveData observable for retrieval by the view
*/
fun navigate(directions: NavDirections) {
_navigationCommands.postValue(NavigationCommand.ToDirections(directions))
}
fun navigate(destinationId: Int) {
_navigationCommands.postValue(NavigationCommand.ToDestinationId(destinationId))
}
fun navigateBack() {
_navigationCommands.postValue(NavigationCommand.Back)
}
fun navigateBackTo(destinationId: Int, isInclusive: Boolean) {
_navigationCommands.postValue(NavigationCommand.BackTo(destinationId, isInclusive))
}
open fun init() {
// DEFAULT IMPLEMENTATION - override to initialize your view model
}
/**
* Called from base fragment when the view has been created.
*/
fun onViewCreated() {
analyticsModel.onNewState(getAnalyticsPathCrumb())
}
/**
* gets the Path for the current page to be used for the trackstate call
*
* Override this method if you need to modify the path
*
* the page id for the track state call will be calculated in the following manner
* 1) analyticsPageId
* 2) titleId
* 3) the page title string
*/
protected fun getAnalyticsPathCrumb() : AnalyticsBreadCrumb {
return analyticsBreadCrumb {
pathElements {
if (globalNavModel.analyticsPageId != null) {
waPath {
path = PathElement(globalNavModel.analyticsPageId as Int)
}
} else if (globalNavModel.titleId != null) {
waPath {
path = PathElement(globalNavModel.titleId as Int)
}
} else {
waPath {
path = PathElement(globalNavModel.title ?: "")
}
}
}
}
}
}
The DialogFragment:
class OtpVerificationHelpCodeSentBottomSheetFragment : BaseBottomSheetDialogFragment(){
private lateinit var rootView: View
lateinit var binding: BottomSheetFragmentOtpVerificationHelpCodeSentBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
viewModel = getViewModel<OtpViewModel>()
binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_fragment_otp_verification_help_code_sent, container, false)
rootView = binding.root
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val otpViewModel = (viewModel as OtpViewModel)
binding.viewmodel = otpViewModel
otpViewModel.resendOTPResponseLiveData.observe(viewLifecycleOwner, Observer {
it?.let { resendOtpResponse ->
if(resendOtpResponse.statusCode.equals("000")){
//valid status code
requireActivity().toastMessageOtp(getString(R.string.otp_code_verification_sent))
}else{
//show the error model
//it?.errorModel?.let { it1 -> handleDiasNetworkError(it1) }
}
}
})
}
}
我正在从DialogFragment的xml文件中调用viewmodel的resendOTP(contactId:String)方法。
<TextView android:id="@+id/verification_help_code_sent_resend_code" style="@style/TruTextView.SubText2.BottomActions" android:layout_height="@dimen/spaceXl" android:gravity="center_vertical" android:text="@string/verification_help_resend_code" android:onClick="@{() -> viewmodel.resendOTP(Integer.toString(viewmodel.userSelectedIndex))}" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/top_guideline" />
现在,每当我尝试从Fragment调用resendOTPResponseLiveData时,它都不会被调用:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) Log.d("OtpVerify" , "OnViewCreatedCalled") viewModel.onViewCreated() val otpViewModel = (viewModel as OtpViewModel) binding.lifecycleOwner = this binding.viewmodel = otpViewModel binding.toAuthenticated = OtpVerifyFragmentDirections.actionOtpVerifyFragmentToAuthenticatedActivity() binding.toVerificationBtmSheet = OtpVerifyFragmentDirections.actionOtpVerifyFragmentToOtpContactVerificationCodeSentBottomSheet() otpViewModel.resendOTPResponseLiveData.observe(viewLifecycleOwner, Observer { if(it?.statusCode.equals("000")){ //valid status code requireActivity().toastMessageOtp(getString(R.string.otp_code_verification_sent)) }else{ //show the error model it?.errorModel?.let { it1 -> handleDiasNetworkError(it1) } } }) }
所以我在这里做什么错。
编辑
基本上,我需要在dialogfragment中单击clicklistener(重新发送按钮单击),并需要在片段中读取它。因此,我使用了SharedViewModel的概念。
所以我在ViewModel中进行了必要的更改:
private val selected = MutableLiveData<LogonModel>() fun select(logonModel: LogonModel) { selected.value = logonModel } fun getSelected(): LiveData<LogonModel> { return selected }
在DialogFragment中:
otpViewModel.resendOTPResponseLiveData.observe(viewLifecycleOwner, Observer{ otpViewModel.select(it); })
并且在我要读取值的片段中:
otpViewModel.getSelected().observe(viewLifecycleOwner, Observer { Log.d("OtpVerify" , "ResendCalled") // Update the UI. if(it?.statusCode.equals("000")){ //valid status code requireActivity().toastMessageOtp(getString(R.string.otp_code_verification_sent)) }else{ //show the error model it?.errorModel?.let { it1 -> handleDiasNetworkError(it1) } } })
但是它仍然无法正常工作。
编辑:
片段的ViewModel源:
viewModel = getSharedViewModel<OtpViewModel>(from = { Navigation.findNavController(container as View).getViewModelStoreOwner(R.id.two_step_authentication_graph) })
对话框片段的ViewModel源:
viewModel = getViewModel<OtpViewModel>()
我正在从ViewModel的DialogFragment更新LiveData值,但无法在Fragment中获取该值。 ViewModel:类OtpViewModel(priv val otpUseCase:OtpUseCase,analyticsModel:...
问题是您实际上没有在Fragment
[我认为这里的问题是您使用的是viewModels
,这意味着您返回的ViewModel仅限于当前上下文/片段...如果您希望在应用程序的多个部分之间共享视图模型它们必须在活动范围内。