我使用Kotlin,Retrofit和Coroutines定义了一个接口,用于从远程服务器获取数据,最重要的是,将所选RecyclerView项目的ID传递回服务器。
interface CourseService {
@GET("/mobile/feed/course_data.php")
suspend fun getCourseData(@Query("pathName") pathName: String): Response<List<Course>>
}
在这里,我从MainFragment的RecyclerView中获取所选项目的ID,并将其存储在“ selectedItem”变量中。
override fun onPathItemClick(path: Path) {
viewModel.selectedItem.value = path
selectedItem= viewModel.selectedItem.value!!.path_id
navController.navigate(R.id.action_mainFragment_to_courseFragment)
}
我将所选项目的值传递给getCourseData()函数
class CourseRepository(val app: Application) {
val courseData = MutableLiveData<List<Course>>()
init {
CoroutineScope(Dispatchers.IO).launch {
callWebService()
}
}
@WorkerThread
suspend fun callWebService() {
val retrofit = Retrofit.Builder().baseUrl(WEB_SERVICE_URL).addConverterFactory(MoshiConverterFactory.create()).build()
val service = retrofit.create(CourseService::class.java)
val serviceData = service.getCourseData(selectedItem).body() ?: emptyList()
courseData.postValue(serviceData)
}
}
但是我没有任何结果,并且好像传递给getCourseData()函数的值是null,但是在检查日志时确实有一个值。
因此,如果我在代码中的任何地方(如下面)给它一个预定义的值,一切都会很好地工作
selectedItem= "MOB001"
val serviceData = service.getCourseData(selectedItem).body() ?: emptyList()
但是,我不能在运行时之前给它一个固定值,因为当用户从RecyclerView中选择一个项目时会检索该值。
这些是我的多个日志:
2020-05-01 13:56:30.431 23843-23843/ I/mylog: Main Fragment before item click: selectedItem =
2020-05-01 13:56:37.757 23843-23843/ I/mylog: Main Fragment after item click: selectedItem = WEB001
2020-05-01 13:56:37.763 23843-23843/ I/mylog: Course Fragment onCreateView(): selectedItem = WEB001
2020-05-01 13:56:37.772 23843-23901/ I/mylog: Course Fragment CourseRepository: selectedItem = WEB001
我该如何克服这个问题?
答案 0 :(得分:1)
您应该在CourseRepository
内调用callWebService
的暂停函数ViewModel
。这是您的存储库:
class CourseRepository(val app: Application) {
suspend fun callWebService(path: Path): List<Course> {
return withContext(Dispatchers.IO) {
val retrofit = Retrofit.Builder().baseUrl(WEB_SERVICE_URL).addConverterFactory(MoshiConverterFactory.create()).build()
val service = retrofit.create(CourseService::class.java)
service.getCourseData(path.path_id).body() ?: emptyList()
}
}
}
然后,您应该在ViewModel中调用存储库函数,如下所示:
fun getCourseData(path: Path): LiveData<List<Course>> {
val response = MutableLiveData<List<Course>>()
viewModelScope.launch {
response.postValue(repository.callWebService(path))
}
return response
}
然后从您的viewModel. getCourseData(path)
或Activity
或获得有效Fragment
值的任何地方调用Path
。
别忘了在您的gradle文件中包含implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
。
答案 1 :(得分:1)
您的代码似乎是正确的,但是,很可能是第一次填充RecyclerView,并且每次您回去选择另一条路径时,都使用相同的数据和视图填充它。
因此,您的注意力应集中在为何不再再次获取数据的原因上,这是RecyclerView和Fragment保留相同的第一个视图的原因。
答案 2 :(得分:0)
经过几天的思考,我的代码是错误的,事实证明,每次我回退以选择不同的路径时,由于我的RecyclerView在onCreateView()函数中被夸大了,所以我的RecyclerView适配器正在加载同一视图仅当片段第一次膨胀时。
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(requireActivity()).get(CourseViewModel::class.java)
viewModel.courseData.observe(viewLifecycleOwner, Observer {
val adapter =
CourseRecyclerAdapter(
requireContext(),
it,
this
)
recyclerView.adapter = adapter
} )
return view
}
override fun onCourseItemClick(course: Course) {
viewModel.selectedCourse.value = course
navController.navigate(R.id.action_courseFragment_to_detailFragment)
}
}