RecyclerView не обновляет элементы - PullRequest
0 голосов
/ 02 мая 2020

MainFragment содержит RecyclerView путей, когда пользователь выбирает путь, по которому он переходит к CourseFragment, который содержит RecyclerView соответствующих курсов. Однако, если пользователь возвращается, чтобы выбрать другой путь, каждый раз отображаются одни и те же элементы курса.

Fragments and recyclerviews

Фрагмент курса

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? {
        Log.i(LOG_TAG, "Course Fragment onCreateView(): selectedItem = $globalSelectedPath")

        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(requireActivity()).get(CourseViewModel::class.java)
        viewModel.courseData.observe(viewLifecycleOwner, Observer {
            val adapter =
                CourseRecyclerAdapter(
                    requireContext(),
                    it,
                    this
                )
            recyclerView.adapter = adapter
        } )
        return view
    }

CourseViewModel

class CourseViewModel(app: Application): AndroidViewModel(app) {

    private val courseDataRepository = CourseRepository(app)
    val courseData = courseDataRepository.courseData
    val selectedCourse = MutableLiveData<Course>()
}

Репозиторий курса

class CourseRepository(val app: Application) {

    val courseData = MutableLiveData<List<Course>>()

    init {
        CoroutineScope(Dispatchers.IO).launch {
            callWebService()
        }
    }

    @WorkerThread
    suspend fun callWebService() {
        if (Utility.networkAvailable(app)) {

            val retrofit = Retrofit.Builder().baseUrl(WEB_SERVICE_URL).addConverterFactory(MoshiConverterFactory.create()).build()
            val service = retrofit.create(CourseService::class.java)
            val serviceData = service.getCourseData(globalSelectedPath).body() ?: emptyList()
            courseData.postValue(serviceData)
        }
        else
            Toast.makeText(app, Resources.getSystem().getString(R.string.noConnectivity), Toast.LENGTH_LONG).show()
    }
}

После регистрации он показывает, что CourseRepository является вызывается только один раз, следовательно, callWebService () запускается только один раз, а новые данные не извлекаются.

2020-05-02 12:24:02.520 I/mylog: Course Fragment onCreateView(): selected path = MOB001
2020-05-02 12:24:02.529 I/mylog: Course Repository callWebService(): selected path = MOB001
-------------------------------
2020-05-02 12:24:35.009 I/mylog: Course Fragment onCreateView(): selected path = WEB999

Чтобы убедиться, что я сделал журнал перехвата Okhttp для callWebService (), который подтвердил, что данные были выбирается только один раз:

    12:24:02.551 D/OkHttp: --> GET https://.../mobile/feed/course_data.php?pathName=MOB001
    12:24:02.551 D/OkHttp: --> END GET
    12:24:03.007 D/OkHttp: <-- 200 https://.../mobile/feed/course_data.php?pathName=MOB001 (455ms)
    12:24:03.007 D/OkHttp: date: Sat, 02 May 2020 09:24:03 GMT
    12:24:03.007 D/OkHttp: server: Apache
    12:24:03.007 D/OkHttp: x-powered-by: PHP/5.6.40
    12:24:03.007 D/OkHttp: vary: Accept-Encoding
    12:24:03.007 D/OkHttp: content-type: text/html; charset=UTF-8
    12:24:03.009 D/OkHttp: [{"courseName":"Android App Development Essentials","instructor":"John Lennon","courseDescription":"Description ...","courseImage":"android_development_essentials.jpg","instructorImage":"john.jpg"}]
    12:24:03.009 D/OkHttp: <-- END HTTP (206-byte body)

Ответы [ 3 ]

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

Скорее всего, проблема является причиной, потому что наблюдатель не обновляется. Вы можете использовать жизненный цикл представления фрагмента с помощью getViewLifeCycleOwner () или getViewLifeCycleLiveData (), чтобы LiveData удаляла наблюдателей каждый раз, когда фрагмент уничтожается.

0 голосов
/ 11 мая 2020

Оказывается, что в следующей строке:

viewModel = ViewModelProvider(requireActivity()).get(CourseViewModel::class.java)

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

Поэтому, чтобы решить эту проблему, я заменил requireActivity() на this, что означает, что модель представления видна только фрагменту, в котором она находится и, следовательно, RecyclerView будет обновляться всякий раз, когда пользователь вводит и повторно вводит фрагмент

viewModel = ViewModelProvider(this).get(CourseViewModel::class.java)
0 голосов
/ 02 мая 2020

ViewModelProvider (requireActivity ()) вызывает извлечение предыдущей модели представления, поскольку хранилище модели представления сохраняет ссылку на ранее созданную модель представления, а затем обслуживает ее, если вы хотите снова. Вы должны указать этот фрагмент как владельца магазина модели представления, а не как деятельность. Кроме того, я думаю, что ваш дизайн хранилища некорректен, если вам не нужен тот же список курсов в другом месте, вы должны вызывать метод с соответствующим аргументом всякий раз, когда создается фрагмент списка курсов, чтобы вы могли получить соответствующие данные с сервера.

...