Почему данные не загружаются в RecyclerView MVVM?

У меня есть приложение для Android, которое запрашивает список из сети и должно отображать его в представлении переработчика, но этого не происходит. В логарифме ошибок нет. Я думаю, что проблема в моей функции во ViewModel. Помогите мне понять

Мой класс CategoryClient:

class CategoryClient {

    companion object {
        const val KEY = "5de979d34658275ac9dc2375"
    }

    var category: List<Category>? = null

    fun loadCategory(): List<Category>? {
        // x-apikey interceptor for restdb API
        fun createOkHttpClient(): OkHttpClient? {
            val httpClient = OkHttpClient.Builder()
            httpClient.addInterceptor(object : Interceptor {
                @Throws(IOException::class)
                override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
                    val original = chain.request()
                    val originalHttpUrl = original.url
                    val url = originalHttpUrl.newBuilder()
                        .addQueryParameter("apikey", KEY)
                        .build()
                    val requestBuilder = original.newBuilder()
                        .url(url)
                    val request = requestBuilder.build()
                    return chain.proceed(request)
                }
            })
            // logging interceptor
            val logging = HttpLoggingInterceptor()
            logging.level = HttpLoggingInterceptor.Level.BODY
            httpClient.addInterceptor(logging)
            return httpClient.build()
        }

        val retrofit = Retrofit.Builder()
            .baseUrl("https://testcategory-d6d7.restdb.io/rest/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(createOkHttpClient())
            .build()

        val api = retrofit.create(CategoryApi::class.java)
        api.fetchAllCategory().enqueue(object : Callback<List<Category>> {
            override fun onFailure(call: Call<List<Category>>, t: Throwable) {
            }

            override fun onResponse(call: Call<List<Category>>, response: Response<List<Category>>) {
                //Log.d(TAG, "onResponse: ${response.body()!![0].name}")
                category = response.body()!!
                 //presenter.setupCategoryList(categoryList = category as ArrayList<Category>)
            }
        })
        return category
    }
}

Мой класс активности категории

val binding: ActivityCategoryBinding =
            DataBindingUtil.setContentView(this@CategoryActivity, R.layout.activity_category)
        val categoryViewModel =
            ViewModelProviders.of(this@CategoryActivity).get(CategoryViewModel::class.java)
        binding.categoryViewModel = categoryViewModel

        categoryViewModel.getArrayList().observe(this@CategoryActivity, Observer { category ->
            mAdapter = CategoryAdapter(this@CategoryActivity, categoryList = category )
            recycler_category.layoutManager = LinearLayoutManager(applicationContext, OrientationHelper.VERTICAL, false)
            recycler_category.adapter = mAdapter
            recycler_category.setHasFixedSize(true)
        })

Мой класс адаптера RecyclerView

class CategoryAdapter(private val context: Context, private val categoryList: ArrayList<Category>?)
    : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private var mCategoryList: ArrayList<Category> = ArrayList()
    private var mSourceList: ArrayList<Category> = ArrayList()

    fun setupCategory(categoryList: ArrayList<Category>) {
        mSourceList.clear()
        mSourceList.addAll(categoryList)
        search(query = "")
    }

    fun search(query: String) {
        mCategoryList.clear()
        mSourceList.forEach {
            if (it.name.contains(query, ignoreCase = true)) {
                mCategoryList.add(it)
            }
        }
        notifyDataSetChanged()
    }

    fun sortByName() {
        mCategoryList.sortBy { it.name }
        notifyDataSetChanged()
    }

    fun sortByPrice() {
        mCategoryList.sortBy { it.price }
        notifyDataSetChanged()
    }

    fun filter() {

    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is CategoryViewHolder) {
            holder.bind(categoryModel = mCategoryList[position])


        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val itemView = layoutInflater.inflate(R.layout.cell_category, parent, false)
        return CategoryViewHolder(itemView = itemView)
    }

    override fun getItemCount(): Int {
        return mCategoryList.count()
    }

    class CategoryViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {

        var mCategoryIcon: CircleImageView = itemView.findViewById(R.id.category_icon)
        var mCategoryName: TextView = itemView.findViewById(R.id.category_name)
        var mCategoryPrice: TextView = itemView.findViewById(R.id.category_price)
        private var mCategoryType: TextView = itemView.findViewById(R.id.category_type)

        fun bind(categoryModel: Category) {
            categoryModel.icon.let { url ->
                Picasso.with(itemView.context).load(url)
                    .into(mCategoryIcon)
            }

            mCategoryName.text = categoryModel.name
            mCategoryPrice.text = categoryModel.price.toString()
            mCategoryType.text = categoryModel.category

        }
    }
}

И мой класс ViewModel

class CategoryViewModel : ViewModel() {

    var mutableLiveData = MutableLiveData<ArrayList<Category>>()

    fun getArrayList(): MutableLiveData<ArrayList<Category>> {

        mutableLiveData.value = CategoryClient().loadCategory() as ArrayList<Category>?

        return  mutableLiveData

    }
}

person Infernal    schedule 31.12.2019    source источник
comment
Можете ли вы проверить, не является ли список, полученный из сети, пустым или нулевым?   -  person iCantC    schedule 31.12.2019
comment
Если вы проверили, что сетевые данные не пусты, как предлагает @iCantC. Далее проверьте это, внутри onbindviewholder вы заполняете представления элементов из ** mCategoryList**. но во время инициализации адаптера вы используете mSourceList< /b>, вы не используете mSourceList, который вы получаете из наблюдаемого внутри держателя onbindview.   -  person Oooha    schedule 31.12.2019


Ответы (1)


Ваши данные не обновляются после asynchronous вызова API. Измените свою реализацию, как показано ниже, чтобы получить обновленные данные:

class CategoryViewModel : ViewModel() {
    fun getArrayList(): MutableLiveData<ArrayList<Category>> {
        return CategoryClient().loadCategory()
    }
}

И ваш loadCategory

var mutableLiveData = MutableLiveData<ArrayList<Category>>()

fun loadCategory(): MutableLiveData<ArrayList<Category>> {
    api.fetchAllCategory().enqueue(object : Callback<List<Category>> {
        override fun onFailure(call: Call<List<Category>>, t: Throwable) {
        }

        override fun onResponse(call: Call<List<Category>>, response: Response<List<Category>>) {
            mutableLiveData.postValue(response.body())
        }
    })

    return mutableLiveData
}

И ваш адаптер должен быть исправлен для использования одного источника

class CategoryAdapter(private val context: Context, private val mCategoryList: ArrayList<Category>?)
    : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private var mSourceList: ArrayList<Category> = ArrayList(mCategoryList)

    .....
}
person Md. Asaduzzaman    schedule 31.12.2019
comment
Большое спасибо! Я просто запутался между шаблонами MVP и MVVM - person Infernal; 31.12.2019
comment
Теперь забавный поиск() в адаптере у меня не работает. Не понимаю в чем проблема, но при поиске по букве просто пустой экран - person Infernal; 31.12.2019
comment
С Новым 2020 годом. Используйте 1_. Он создает новый экземпляр списка, который не очищается во время очистки mCategoryList - person Md. Asaduzzaman; 31.12.2019
comment
@Md.Asaduzzaman .. вы можете мне помочь ---› stackoverflow.com/questions/59526045/ - person Wini; 01.01.2020