【发布时间】:2020-05-04 19:21:53
【问题描述】:
我有三个片段,每个片段都有自己的 RecyclerView。如果用户从第一个片段中选择了一条路径,则根据选择将他带到具有相关课程的下一个片段,然后选择课程并转到具有相关课程的最后一个片段。所以每个 RecyclerView 都依赖于前一个 RecyclerView 的数据。
我对所有 Fragment 都使用了共享 ViewModel,但效果不佳,因为它们都会在 Activity 启动时被初始化,因为数据检索功能在 ViewModel 中初始化的 Repository 中。
我为它们中的每一个都使用了一个单独的 ViewModel,范围仅限于 Activity,但也不能很好地工作,因为只有在 Activity 开始时才会检索数据,而不会再次检索数据,因此在片段之间来回导航时相同数据和项目出现。
如果我仅将单个 ViewModel 限定为片段,则后一个片段无法访问前一个片段所需的数据。
如何使用 ViewModel 架构解决这个难题?还是我应该只使用 SafeArgs 来传递数据?
CourseViewModel
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
}
这是我放弃之前的共享模型:
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>()
}
【问题讨论】:
-
更好的方法是使用单独的视图模型,只需将 id 从一个片段传递到另一个片段,然后从本地数据库或服务器获取必要的数据。 @ReazMurshed 的回答很好,解决了您共享视图模型的问题,但您的实际问题是关注点分离。在未来,您的视图模型将成为一个上帝视图模型,在主屏幕、列表和细节等松散相关的屏幕中执行各种操作。主片段和列表片段之间唯一的共同点是所选列表的 id。而list和detail的共同点就是课程的id
-
@sonnet ,我目前正在使用单独的视图模型。正确地,他们之间唯一共享的是 ID,但中间 CourseFragments 从服务器检索数据和图像,我想将其传递给最后一个 Detail 片段
-
我可以让 CourseFragment 检索数据,也可以让 Detail 片段检索相同的数据,这是我想避免的事情
-
使用 android room 或 sqldelight 将数据存储在 sqlite 数据库中。任何像样的图像加载库都会缓存图像。只有第一次从服务器下载图像时,从下一次它会从应用程序的缓存目录加载图像。您还可以根据您的要求使此图像缓存无效。总的来说,这是一个更好的方法。范围为根/父片段的片段之间的 SharedViewModel 有其用例,但这不是 imo 之一。
-
@sonnet,sqlite 数据库的想法听起来很不错,我绝对认为它是最好的方法,谢谢。
标签: android android-fragments kotlin android-viewmodel