我正在学习如何在我的应用程序中实现LiveData。我的应用程序有一个MainActivity,其中有2个片段,带有导航列表器。ListFragment和DetailListFragment。
我通过viewModel在onCreateViewListFragment上调用函数从服务器获取数据,并观察这一点,以便在成功时将数据填充到RecyclerView中。然后,我单击一个项目,在DetailListFragment中显示详细信息。
问题是当从DetailListFragment返回时,观察viewModel被重新调用,但我不想要它
惨叫我的代码
列表片段
class ListFragment : BaseFragment(), ListClickListener {
private lateinit var _observeListViewModel: Observer<BaseViewModel.State>
lateinit var listViewModel: ListViewModel
private lateinit var adapter: ListAdapter
private var _binding: ListBinding? = null
private val binding get() = _binding!!
override fun onDestroyView() {
super.onDestroyView()
_binding = null
listViewModel.state.removeObserver(_observeListViewModel)
}
private var itemsData = ArrayList<ListResponseDtoListModel>()
@SuppressLint("PrivateResource")
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
_binding = ListBinding.inflate(inflater, container, false)
listViewModel =
ViewModelProvider(this).get(ListViewModel::class.java)
adapter = ListAdapter(itemsData, this)
val llm = LinearLayoutManager(requireActivity())
binding.rv.setHasFixedSize(true)
binding.rv.layoutManager = llm
binding.rv.adapter = adapter
//get List
_observeListViewModel =
Observer<BaseViewModel.State> { observeListViewModel(it) }
listViewModel.state.observe(viewLifecycleOwner, _observeListViewModel)
listViewModel.getList(requireContext())
return binding.root
}
private fun observeListViewModel(state: BaseViewModel.State?) {
when (state) {
BaseViewModel.State.Loading -> {
loadingState()
}
is BaseViewModel.State.Error -> {
errorState()
}
is BaseViewModel.State.Success -> {
val data = state.data as ListModel
if (data.status == KopraMobile().SUCCESS) {
if (data.content!!.listResponseDtoList.size == 0) {
nodataState()
} else data.content?.listResponseDtoList.let {
successState(it)
}
} else
errorState()
}
is BaseViewModel.State.SessionTimeout -> {
errorState()
(parentFragment as BaseFragment).logOut()
}
is BaseViewModel.State.ErrorResponse -> {
errorState()
}
else -> {}
}
}
private fun successState(it: Any) {
....
}
private fun loadingState() {
....
}
private fun nodataState() {
....
}
private fun errorState() {
....
}
override fun onItemClicked(dashboardItem: ListResponseDtoListModel?) {
findNavController().navigate(R.id.action_listFragment_to_detailListFragment)
}
}
详细数据片段
class DetailListFragment : BaseFragment(){
private var _binding: DetailListBinding? = null
private val binding get() = _binding!!
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private var itemsData = ArrayList<DetailListResponseDtoListModel>()
@SuppressLint("PrivateResource")
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
_binding = DetailListBinding.inflate(inflater, container, false)
binding.incToolbar1.header.text = "Detail"
binding.incToolbar1.back.setImageResource(com.google.android.material.R.drawable.material_ic_keyboard_arrow_previous_black_24dp)
binding.incToolbar1.back.setOnClickListener {
findNavController().popBackStack()
}
return binding.root
}
}
列表视图模型
class ListViewModel : BaseViewModel() {
fun getList(context: Context)
{
_state.postValue(State.Loading)
job = CoroutineScope(Dispatchers.IO + exceptionHandler).launch {
try {
val response =
NetworkApi().getListApi().getList( BuildConfig.APPLICATION_ID, Prefs.getPublicAuthorization(context)
)
withContext(Dispatchers.Main) {
_state.postValue(
if (response.isSuccessful) {
State.Success( response.headers(), response.body() )
} else {
State.ErrorResponse( response.headers(), response.errorBody() ) }
)
}
} catch (throwble: Throwable) {
_state.postValue(
State.Error("Error : ${throwble.message.toString()} ")
)
}
}
}
}
基本视图模型
open class BaseViewModel : ViewModel() {
sealed class State {
object Loading : State()
data class Success(val headers: Headers, val data: Any?) : State()
data class ErrorResponse(val headers: Headers, val errorResponse: ResponseErrorModel) :
State()
data class Error(val message: String?) : State()
data class SessionTimeout(val sessionTimeout: String?) : State()
}
var job: Job? = null
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
_state.postValue(State.Error("Exception handled: ${throwable.localizedMessage}"))
}
val _state = MutableLiveData<State>()
val state: LiveData<State> get() = _state
override fun onCleared() {
super.onCleared()
job?.cancel()
}
}
我希望有人能帮我解决这个问题。谢谢,对不起我的英语。
1条答案
按热度按时间wpcxdonn1#
您可以使用LiveData的这个子类,它只会发出一次