将数据传递到远程服务器

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

使用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()函数的值是空的,但当检查日志时,确实有一个值。

所以,如果我在我的代码中的任何地方给它一个预定义的值,比如下面,一切都完全正常。

    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

我怎样才能解决这个问题?

android kotlin retrofit retrofit2 kotlin-coroutines
1个回答
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) 从你 ActivityFragment 或任何地方,当你得到有效的 Path 值。

不要忘记包括 implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0" 到你的gradle文件。


1
投票

你的代码似乎是正确的,但是,你的RecyclerView很有可能是第一次被填充了,而且每次你回去选择另一个路径时,它都被填充了相同的数据和视图。

因此,你的注意力应该集中在为什么数据没有被再次获取,这就是RecyclerView和Fragment坚持相同的第一次视图的原因。


0
投票

经过几天的思考,我发现我的RecyclerView适配器每次都在加载相同的视图,因为我的RecyclerView在onCreateView()函数中被膨胀了,而这个函数只被调用一次,当一个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? {

        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)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.