ViewModel архитектура Диллема - PullRequest
1 голос
/ 04 мая 2020

У меня есть три фрагмента, каждый с собственным RecyclerView. Если пользователь выбирает путь из первого фрагмента, он переносит его к следующему фрагменту с соответствующими курсами на основе выбора, а затем выбирает курс и переходит к последнему фрагменту с соответствующими уроками. Таким образом, каждый RecyclerView зависит от данных из предыдущего RecyclerView.

enter image description here

Я использовал общий ViewModel для всех фрагментов, но он не работал должным образом, потому что они все будут инициализированы при запуске действия, потому что функция извлечения данных находится в репозитории, который инициализируется в ViewModel.

Я использовал отдельную ViewModel для каждого из них, ограниченных для действия, но не сделал работают хорошо также потому, что данные извлекаются только один раз, когда начинается действие, и никогда больше, поэтому при навигации между фрагментами назад и вперед отображаются одни и те же данные и элементы.

Если я ограничиваю отдельные ViewModels только фрагментом , тогда последний фрагмент не может получить доступ к данным, необходимым из предыдущего.

Как решить эту дилемму с помощью ViewModel Architecture? или я должен просто использовать 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>()
}

Ответы [ 2 ]

1 голос
/ 04 мая 2020

Если я правильно понял, вы можете создать фрагменты, чтобы иметь следующую структуру.

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);
0 голосов
/ 11 мая 2020

Как предложено @ so nnet, я решил проблему, сохранив данные в базе данных Room и затем извлекая их всякий раз, когда пользователь вводил / вводил какой-либо фрагмент, и, следовательно, ограничивая удаленный поиск данных.

...