RecyclerView观察者,片段不更新数据。

问题描述 投票:2回答:1

我的MainFragment中包含一个教育路径的RecyclerView,当选择一个项目时,它会把用户带到CourseFragment,里面有不同的相关课程的RecyclerView。然而,如果用户回到第一个RecyclerView并选择不同的路径,同样的数据项又会出现。

课程片段(Course Fragment)

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()
    }
}

我添加了一些日志,发现我的Repository只在第一次打开app时被调用一次,但再也没有取到数据,因为callWebService()再也没有被调用。

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

我添加了一些http日志来跟踪数据,确认数据只被检索了一次。

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)
android kotlin android-recyclerview android-viewmodel
1个回答
3
投票

你正在使用 ViewModelProvider(requireActivity()).get(CourseViewModel::class.java),这意味着你正在创建你的 CourseViewModel 作用于整个活动。这意味着只有一个 CourseViewModel 为该活动的整个生命周期创建。

如果您想在活动的整个生命周期中创建一个单独的 CourseViewModel (因此,单独的 CourseRepository 实例),您应该为每个片段使用 ViewModelProvider(this) 以将ViewModel的范围扩大到片段本身。

viewModel = ViewModelProvider(this).get(CourseViewModel::class.java)
© www.soinside.com 2019 - 2024. All rights reserved.