Ajeeli
Ajeeli

Reputation: 373

RecyclerView Observer, fragment not updating data

My MainFragment contains a RecyclerView of educational paths, when an item is selected it takes the user to CourseFragment with a different RecyclerView of relevant courses. However, if the user goes back to the first RecyclerView and chooses a different path, the same data items show up again.

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

Course Repository

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

I added some logs and noticed that my Repository is only called once the app opens up first time, but never fetches the data again because the callWebService() is never called again.

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

I added some http logs to trace data and confirmed that the data was being retrieved once only:

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)

Upvotes: 1

Views: 320

Answers (1)

ianhanniballake
ianhanniballake

Reputation: 199825

You're using ViewModelProvider(requireActivity()).get(CourseViewModel::class.java), which means you're creating your CourseViewModel scoped to the entire activity. That means there will only be one instance of CourseViewModel created for the entire lifetime of the activity.

If you want a separate CourseViewModel (and hence, a separate CourseRepository instance) for each fragment, you should use ViewModelProvider(this) to scope the ViewModel to the fragment itself:

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

Upvotes: 3

Related Questions