【问题标题】:Why data is not loaded to the RecyclerView MVVM?为什么数据没有加载到 RecyclerView MVVM?
【发布时间】:2020-01-01 02:10:49
【问题描述】:

我有一个 android 应用程序,它从网络请求一个列表,并且应该在回收站视图中显示它,但这不会发生。 logcat 中没有错误。我认为问题出在我在 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

    }
}

【问题讨论】:

  • 您能否验证从网络收到的列表是否为空或为空?
  • 如果您检查的网络数据不是@iCantC 建议的空。进一步检查,在 onbindviewholder 内,您正在从 ** mCategoryList** 填充项目视图。但是在适配器期间使用 mSourceList 初始化你,你没有使用 mSourceList 你从 onbindview holder 中的 observable 获得。

标签: android android-databinding android-mvvm


【解决方案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)

    .....
}

【讨论】:

  • 非常感谢!我只是对 MVP 和 MVVM 模式感到困惑
  • 现在适配器中有趣的 search() 对我不起作用。我不明白问题是什么,但是在字母搜索过程中,它只是一个空白屏幕
  • 2020 年新年快乐。使用private var mSourceList: ArrayList&lt;Category&gt; = ArrayList(mCategoryList)。它会创建新的列表实例,在清除 mCategoryList 期间不清楚
  • @Md.Asaduzzaman..你能帮帮我吗--->stackoverflow.com/questions/59526045/…
猜你喜欢
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多