我有一个父片段,它使用 ViewModel 和 Retrofit 从 API 获取列表,ViewModel 注入了 Hilt。 获取列表后,父片段将传递给父片段内的子片段。 但问题是 ViewModel 在子片段中又被实例化了一次。
父片段
@AndroidEntryPoint
class ParentFragment : Fragment() {
override val mViewModel: URLViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
mViewBinding = getViewBinding(inflater, container)
mViewModel.liveData.observe(this, { data ->
{
childFragmentManager.beginTransaction().apply {
replace(
mViewBinding.fragmentContainer.id,
ChildFragment(data)
)
}
commit()
} })
mViewModel.getURL("TEST", "2021-06-18", "2021-07-18", 1 , 0 , -1, false)
return mViewBinding.root
}
}
子片段
@AndroidEntryPoint
class ChildFragment(val data: List<Item>) : Fragment() {
override val mViewModel: URLViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
mViewBinding = getViewBinding(inflater, container)
// mViewModel is instantiated again and some all strings properties of it is null.
return mViewBinding.root
}
}
URLViewModel
@HiltViewModel
class URLViewModel @Inject constructor(private val urlApi: URLApi): ViewModel() {
private val _urlLiveData = MutableLiveData<State<Any?>>()
val urlLiveData: LiveData<State<Any?>> = _urlLiveData
var urlName: String? = null
var beginDate: String? = null
var endDate: String? = null
var adultCount = 0
var childrenCount = 0
var airportId = 0
var isRoundTrip = false
init {
Log.e("URLViewModel", "iniialed again" )
}
@ExperimentalStdlibApi
fun getUrl(urlName: String, beginDate: String, endDate: String, adultCount: Int, childCount: Int, airportId: Int, isRoundTrip: Boolean){
Log.e("XXXXXX", "getUrl: called with url of " + urlName )
this.urlName = urlName
this.beginDate = beginDate
this.endDate = endDate
this.adultCount = adultCount
this.childrenCount = childCount
this.airportId = airportId
this.isRoundTrip = isRoundTrip
val mutableLiveData = MutableLiveData<State<Any?>>()
mutableLiveData.value = State.loading()
viewModelScope.launch {
val res = urlApi.getURL(urlName,beginDate,endDate,adultCount,childCount,airportId,isRoundTrip)
Log.e("URLVIewModel", "getUrl: response received" )
_urlLiveData.value = res
}
}
}
当我想访问一些像beginDate这样的属性时,它们是空的,因为ViewModel又被实例化了,
答案 0 :(得分:0)
您正在尝试使用共享视图模型。尝试以下代码以供参考。
@AndroidEntryPoint
class ParentFragment : Fragment() {
private lateinit var viewModel: URLViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(requireActivity()).get(URLViewModel::class.java)
}
}
@AndroidEntryPoint
class ChildFragment : Fragment() {
private lateinit var viewModel: URLViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(requireActivity()).get(URLViewModel::class.java)
}
}
答案 1 :(得分:0)
viewModels()
委托针对同一个实例创建视图模型,即在您的案例中的 Fragment 实例。您需要做的是创建一个共享的 View 模型。
ktx 库提供了辅助委托。
添加您已经拥有的 ktx 依赖项,我猜是 here。
implementation "androidx.fragment:fragment-ktx:1.3.4"
并使用
创建视图模型private val viewModel by activityViewModels<UrlViewModel>()