LiveData Observer не обновляет пользовательский интерфейс после получения данных с сервера в ViewModel - PullRequest
1 голос
/ 30 сентября 2019

Я пытаюсь получить данные с сервера, используя запрос на модификацию get, во ViewModel я инициирую запрос, метод OnResponse запроса показывает, что данные успешно получены с сервера, но наблюдатель во фрагменте не получаетобновлено. Я делюсь приведенным ниже кодом.

RETROFIT CALL API

fun getGenres(application: Context,callback:(List<Genre>)->Unit){
        val baseURL = "https://listen-api.listennotes.com/"
        var genreList: MutableLiveData<List<Genre>> =MutableLiveData()
        val logging = HttpLoggingInterceptor()
//      set your desired log level
        logging.level = HttpLoggingInterceptor.Level.BODY

        val httpClient = OkHttpClient.Builder()
//      add your other interceptors …
//      add logging as last interceptor
        httpClient.addInterceptor(logging)

        val gson = GsonBuilder()
            .setLenient()
            .create()

        val retrofit = Retrofit.Builder()
            .baseUrl(baseURL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(httpClient.build())
            .build()

        val api: ApiFunctions = retrofit.create(ApiFunctions::class.java)



        val call: Call<PodcastGetCategoryResponse> = api.getGenres()

        call.enqueue(object : Callback<PodcastGetCategoryResponse> {
            override fun onFailure(call: Call<PodcastGetCategoryResponse>, t: Throwable) {

                Toast.makeText(application, "failure" + t.stackTrace, Toast.LENGTH_SHORT).show()

            }

            override fun onResponse(
                call: Call<PodcastGetCategoryResponse>,
                response: Response<PodcastGetCategoryResponse>
            ) {


                response.body().apply {
                    callback(this?.genres!!)                    }
                Toast.makeText(application, "success: ${response.body()?.genres?.size}", Toast.LENGTH_SHORT).show()

            }

        })

        return genreList;
    }

Это успешно выполняется и получает список жанров с сервера.

VIEWMODEL CLASS

class CategoryViewModel(application: Application) : AndroidViewModel(application) {
private val rootJob = SupervisorJob()

private val coroutineContext: CoroutineContext
    get() = Dispatchers.Main + rootJob

 var listOfCategory: MutableLiveData<List<Genre>> = MutableLiveData()

init {
    getistOfCategory()
}

// this method is responsible for retrieving data from the result of the API call method using a coroutine.

 fun getistOfCategory() {
    CoroutineScope(coroutineContext).launch() {
        ApiFunctions.getGenres(getApplication<Application>(), { l -> listOfCategory.value = l } )
         listOfCategory.postValue(listOfCategory.value)
    }
  }

Я предполагаю, что проблема заключается в этом классе, но я не могу ее выяснить.

** Класс FRAGMENT **

class MainFragment : Fragment() {
private lateinit var viewModel: CategoryViewModel
private lateinit var binding: FragmentMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    viewModel = ViewModelProviders.of(this).get(CategoryViewModel::class.java)
    viewModel.getistOfCategory()

}

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {

    binding =DataBindingUtil.inflate(inflater, R.layout.fragment_main, container, false)
    var myView: View = binding.root




    viewModel.listOfCategory.observe(this,
        Observer { list ->
            Toast.makeText(
                context,
                "Data Changed" + list?.size,
                Toast.LENGTH_LONG
            ).show()
        })

    return myView
}

Я хочу, чтобы при получении новых значений с сервера они сохранялись в LiveData в классе ViewModel, и фрагмент должен успешно их наблюдать.

1 Ответ

2 голосов
/ 30 сентября 2019

в соответствии с текущей реализацией значение listOfCategory постоянно меняется с каждым обновлением. это означает, что когда ваш список обновляется, наблюдатели не уведомляются, потому что они наблюдают за другим объектом LiveData (который был назначен вашей ссылке до того, как произошло обновление). Необходимо убедиться, что вы создаете экземпляр объекта liveData только один раз и обновляете его значение. всякий раз, когда вы получаете обновление.

Ваш код должен выглядеть примерно так

fun getGenres(application: Context, callback:(List<Genre>)->Unit){
...
     response.body().apply {
            callback(this?.genres!!)
     }
...
}



fun getistOfCategory(): {
  CoroutineScope(coroutineContext).launch() {
      ApiFunctions.getGenres(getApplication<Application>(), l -> listOfCategory.value = l)
    }

}
...