首页 > 解决方案 > 如何使用 Coroutines 在 Kotlin 中正确初始化 Recyclerview?

问题描述

我正在使用 Coroutines 学习 kotlin Android,但无法正确启动 RecyclerView。我在 onCreate 方法之外有函数,但我无法将 Arraylist 从这个方法传递给 onCreate 中的适配器。正如您在我的代码中看到的那样,我在 getCities 函数中设置了 location_recycler_view.apply 但随后我看到: E/RecyclerView: No adapter attach; 跳过日志中的布局。在我的情况下如何正确设置 Recyclerview 的代码?

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_add_location)

    addLocationViewModel = ViewModelProviders.of(this, addLocationViewModelFactory).get(AddLocationViewModel::class.java)

    window.setFlags(
        WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN)

    back_button.setOnClickListener {
        onBackPressed()
    }
    getCities()
    viewAdapter = LocationAdapter(cities, this) //in this case I can get normal list, but no list from ViewModel
    viewManager = LinearLayoutManager(this)

    deleteIcon = ContextCompat.getDrawable(this, R.drawable.ic_delete_white_24dp)!!

    location_recycler_view.apply {    //in this case I can set Recyclerview in normal way
        adapter = viewAdapter
        layoutManager = viewManager
    }


    val itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
        override fun onMove(
            recyclerView: RecyclerView,
            viewHolder: RecyclerView.ViewHolder,
            target: RecyclerView.ViewHolder
        ): Boolean {
            return false
        }

        override fun onSwiped(viewHolder: RecyclerView.ViewHolder, position: Int) {
            (viewAdapter as LocationAdapter).removeItem(viewHolder)

            Log.e("ALA onSwiped", viewHolder.adapterPosition.toString())
            fun deleteLocation() = launch {
                addLocationViewModel.deleteLocation((viewAdapter as LocationAdapter).getCityAt(viewHolder.adapterPosition))
                Log.e("ALA onSwiped", viewHolder.adapterPosition.toString())
            }
        }

        override fun onChildDraw(
            c: Canvas,
            recyclerView: RecyclerView,
            viewHolder: RecyclerView.ViewHolder,
            dX: Float,
            dY: Float,
            actionState: Int,
            isCurrentlyActive: Boolean
        ) {
            val itemView = viewHolder.itemView

            val iconMargin = (itemView.height - deleteIcon.intrinsicHeight) / 2

            if (dX > 0) {
                swipeBackground.setBounds(itemView.left, itemView.top, dX.toInt(), itemView.bottom)
                deleteIcon.setBounds(itemView.left + iconMargin, itemView.top + iconMargin, itemView.left + iconMargin + deleteIcon.intrinsicWidth,
                    itemView.bottom - iconMargin)
            } else {
                swipeBackground.setBounds(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom)
                deleteIcon.setBounds(itemView.right - iconMargin - deleteIcon.intrinsicWidth, itemView.top + iconMargin, itemView.right - iconMargin,
                    itemView.bottom - iconMargin)
            }

            swipeBackground.draw(c)

            c.save()

            if (dX > 0)
                c.clipRect(itemView.left, itemView.top, dX.toInt(), itemView.bottom)
            else
                c.clipRect(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom)

            deleteIcon.draw(c)

            c.restore()

            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
        }

    }

    val itemTouchHelper = ItemTouchHelper(itemTouchHelperCallback)
    itemTouchHelper.attachToRecyclerView(location_recycler_view)

    add_city_button.setOnClickListener {
        if (location_edit_text.text.toString().trim().isEmpty()) {
            Toast.makeText(this, "Location field is empty!", Toast.LENGTH_SHORT).show()
        }
         else {
            saveLocation()
        }
    }
}

private fun getCities() = launch(Dispatchers.Main) {
     val locationList = addLocationViewModel.locations.await()
    locationList.observe(this@AddLocationActivity, Observer {
        locationList -> viewAdapter = LocationAdapter(locationList as ArrayList<Location>, this@AddLocationActivity)
        location_recycler_view.apply {
            adapter = viewAdapter       //if I'm using this RV works, but I see error in logs
            layoutManager = viewManager
        }
    })
}

标签: androidkotlinandroid-recyclerviewkotlin-coroutines

解决方案


似乎您必须在方法LocationAdapter中使用空列表初始化您,onCreate然后在getCities方法中您必须将城市列表设置为适配器,如下所示:

viewAdapter.cities = locationList
viewAdapter.notifyDataSetChanged()

推荐阅读