Reputation: 373
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
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