我有三个片段,每个片段都有自己的RecyclerView。如果用户从第一个片段中选择了一个路径,它就会根据用户的选择带他到下一个有相关课程的片段,然后选择一个课程,再到最后一个有相关课程的片段。所以每个RecyclerView都是依赖于前一个RecyclerView的数据。
我为所有的片段使用了共享的ViewModel,但效果并不好,因为当活动开始时,它们都会被初始化,因为数据检索功能在Repository中,而Repository是在ViewModel中初始化的。
我为每个ViewModel使用了一个单独的ViewModel,但效果不好,也是因为数据只在活动开始时被检索一次,而不会再被检索,所以当在片段之间来回浏览时,会出现相同的数据和项目。
如果我只把单个ViewModels的范围扩大到片段,那么后一个片段就不能访问前一个片段所需的数据。
如何使用ViewModel架构来解决这个难题,还是说我应该直接使用SafeArgs来传递数据?
课程ViewModel
class CourseViewModel(app: Application): AndroidViewModel(app) {
private val courseDataRepository = CourseRepository(app)
val courseData = courseDataRepository.courseData
val selectedCourse = MutableLiveData<Course>()
}
CourseFragment.kt
class CourseFragment : Fragment(),
CourseRecyclerAdapter.CourseItemListener {
private lateinit var viewModel: CourseViewModel
private lateinit var recyclerView: RecyclerView
private lateinit var navController: NavController
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_course, container, false)
recyclerView = view.findViewById(R.id.courseRecyclerView)
navController = Navigation.findNavController(requireActivity(), R.id.nav_host )
viewModel = ViewModelProvider(this).get(CourseViewModel::class.java)
viewModel.courseData.observe(viewLifecycleOwner, Observer {
val adapter =
CourseRecyclerAdapter(
requireContext(),
it,
this
)
recyclerView.adapter = adapter
} )
return view
}
这是我之前的共享模型,在我放弃它之前,我有三个片段,每个片段都有自己的RecyclerView。
class SharedViewModel(app: Application): AndroidViewModel(app) {
private val pathDataRepository = PathRepository(app)
val pathData = pathDataRepository.pathData
val selectedPath = MutableLiveData<Path>()
private val courseDataRepository = CourseRepository(app)
val courseData = courseDataRepository.courseData
val selectedCourse = MutableLiveData<Course>()
private val lessonDataRepository = LessonRepository(app)
val lessonData = lessonDataRepository.lessonData
val selectedLesson = MutableLiveData<Lesson>()
}
如果我的理解没错的话,你可以将片段架构成以下结构。
MainFragment
- CourseFragment
- DetailsFragment
这个想法是为了让 MainFragment
作为父体,并使用以下方法启动其他两个片段。getChildFragmentManager()
来自 MainFragment
如下所示。
getChildFragmentManager().beginTransaction()
.replace(R.id.fragment_container, courseFragment)
.addToBackStack(null).commit();
现在创建一个 ViewModel
对于 MainFragment
和范围,即 ViewModel
到您的生命周期 MainFragment
. 这将作为一个共享的工作 ViewModel
对于两个 CourseFragment
和 DetailsFragment
. 您可以访问 ViewModel
范围内的父片段(即 MainFragment
),如下所示。
SharedViewModel vm = ViewModelProviders.of(getParentFragment())
.get(SharedViewModel.class);
按照@sonnet的建议,我通过将数据存储在Room数据库中,然后每当用户输入re-输入任何fragment时就检索数据,从而限制远程数据检索来解决这个问题。