android - 为什么数据没有加载到 RecyclerView MVVM?

标签 android android-databinding android-mvvm

我有一个 android 应用程序,它从网络请求一个列表,并且应该在回收站 View 中显示它,但这并没有发生。 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
    }
}

我的类别 Activity 类

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

    }
}

最佳答案

您的数据不会从异步 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)

    .....
}

关于android - 为什么数据没有加载到 RecyclerView MVVM?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59543675/

相关文章:

java - 在 Android Studio 中关闭应用程序时推送通知无法正常工作

android - 数据绑定(bind): how to bind different data variables in one view

android - 如何在 View 模型中同步改造?

android - 是否可以在 Android 中使用具有 MVP 架构的分页库?

android - 错误 : Cannot find ActivitySplashBinding

java - x 必须 < bitmap.width()

android - Android Studio 中的 list 合并

带有权重的安卓圆形按钮数字键盘

android - 如何在 Android Studio 3.0.0 中使用数据绑定(bind)和 Kotlin

android - 无法使用 lambda 找到数据绑定(bind)事件的方法