Передача данных на удаленный сервер - PullRequest
0 голосов
/ 01 мая 2020

Используя Kotlin, Retrofit и Coroutines, я определил интерфейс для получения данных с удаленного сервера и, что наиболее важно, передаю идентификатор выбранного элемента RecyclerView обратно на сервер.

interface CourseService {
    @GET("/mobile/feed/course_data.php")
    suspend fun getCourseData(@Query("pathName") pathName: String): Response<List<Course>>
}

Здесь Я получаю идентификатор выбранного элемента из RecyclerView из моего MainFragment и сохраняю его в переменной 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

Как мне решить эту проблему?

Ответы [ 3 ]

1 голос
/ 03 мая 2020

Ваш код кажется правильным, однако, весьма вероятно, что ваш RecyclerView заполняется в первый раз и когда вы go возвращаетесь назад и выбираете другой путь, он заполняется теми же данными и представлением.

Таким образом, ваше внимание должно быть сосредоточено на том, почему данные не извлекаются снова, что является причиной того, что RecyclerView и Fragment держатся за одно и то же первое представление.

1 голос
/ 01 мая 2020

Вы должны вызвать функцию приостановки 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.

Не забудьте включить implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0" в ваш файл Gradle.

0 голосов
/ 01 мая 2020

После нескольких дней размышлений мой код оказался неправильным, оказалось, что мой адаптер RecyclerView загружал одно и то же представление каждый раз, когда я возвращался, чтобы выбрать другой путь, потому что мой RecyclerView был раздут в функции onCreateView (), которая вызывается только один раз. только когда фрагмент раздувается в первый раз.

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