Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
177 views
in Technique[技术] by (71.8m points)

kotlin - Android : Cannot update RecyclerView

I am developing an Android application in Kotlin and I implemented a RecyclerView.

The two parameters that are added to the parametersList are displayed, but when I press the TEST button, the RecyclerView is not updated! I don't understand my mistake, can you help me?

Here is my adapter:

class CustomAdapter(private val parameterList: List<Parameter>, private val onClick: ((selectedParameter: Parameter) -> Unit)? = null) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun showItem(parameter: Parameter, onClick: ((selectedParameter: Parameter) -> Unit)? = null) {
            itemView.findViewById<TextView>(R.id.parameterName).text = parameter.parameterName
            itemView.findViewById<TextView>(R.id.parameterValue).text = parameter.parameterValue as CharSequence?

            if(onClick != null) {
                itemView.setOnClickListener {
                    onClick(parameter)
                }
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.parameter_text, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.showItem(parameterList[position], onClick)
    }

    override fun getItemCount(): Int {
        return parameterList.size
    }

}

My activity:

class NFCActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_nfc)

        buttonTest.setOnClickListener() {

            parametersList = parametersList + ParameterText("Temperature", "24°C")
            rv_parameters2.adapter?.notifyDataSetChanged()
        }

        rv_parameters2.adapter = CustomAdapter(parametersList) { item ->
            println("------------------OnClick------------------")
        }
        rv_parameters2.layoutManager = LinearLayoutManager(this)

    }


    private var parametersList : List<Parameter> = listOf<Parameter> (
            ParameterText("Temperature", "24°C"),
            ParameterText("Temperature", "24°C")
    )

    companion object {
        fun getStartIntent(context: Context): Intent {
            return Intent(context, NFCActivity::class.java)
        }
    }
}

parameter_text.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:padding="10dp">


    <TextView
        android:id="@+id/parameterName"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:text="@string/parameter_name"
        android:textColor="@color/black"
        android:textSize="16sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/parameterValue"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/parameterValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:text="@string/parameter_value"
        android:textSize="16sp"
        app:layout_constraintStart_toEndOf="@id/parameterName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="@+id/parameterName"
        app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

activity_nfc.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".view.ble.NFCActivity">

    <Button
        android:id="@+id/buttonTest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TEST"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_parameters2"
        tools:listitem="@layout/parameter_text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/buttonTest"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

EDIT 1: (following SlothCoding's answer)

My new activity:

class NFCActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_nfc)

        buttonTest.setOnClickListener() {

            parametersList = parametersList + ParameterText("Temperature", "24°C")
            rv_parameters2.adapter?.notifyDataSetChanged()
        }

        rv_parameters2.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        rv_parameters2.adapter = CustomAdapter(parametersList) { item ->
            println("------------------OnClick------------------")
        }
    }

    private var parametersList : List<Parameter> = listOf<Parameter> (
            ParameterText("Temperature", "24°C"),
            ParameterText("Temperature", "24°C")
    )

    companion object {
        fun getStartIntent(context: Context): Intent {
            return Intent(context, NFCActivity::class.java)
        }
    }
}

EDIT 2: (following Sekiro's answer)

CustomAdapter

class CustomAdapter(private val parameterList: List<Parameter>, private val onClick: ((selectedParameter: Parameter) -> Unit)? = null) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    private var parameterListLocal: List<Parameter> = parameterList

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun showItem(parameter: Parameter, onClick: ((selectedParameter: Parameter) -> Unit)? = null) {
            itemView.findViewById<TextView>(R.id.parameterName).text = parameter.parameterName
            itemView.findViewById<TextView>(R.id.parameterValue).text = parameter.parameterValue as CharSequence?

            if(onClick != null) {
                itemView.setOnClickListener {
                    onClick(parameter)
                }
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.parameter_text, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.showItem(parameterListLocal[position], onClick)
    }

    override fun getItemCount(): Int {
        return parameterListLocal.size
    }

    fun addNewList(newList: List<Parameter>){
        parameterListLocal = newList;
        notifyDataSetChanged();
    }

}

NFCActivity

class NFCActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_nfc)

        buttonTest.setOnClickListener() {

            parametersList = parametersList + ParameterText("Temperature", "24°C")
            (rv_parameters2.adapter as CustomAdapter).addNewList(parametersList)
        }

        rv_parameters2.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        rv_parameters2.adapter = CustomAdapter(parametersList) { item ->
            println("------------------OnClick------------------")
        }
    }

    private var parametersList : List<Parameter> = listOf<Parameter> (
            ParameterText("Temperature", "24°C"),
            ParameterText("Temperature", "24°C")
    )

    companion object {
        fun getStartIntent(context: Context): Intent {
            return Intent(context, NFCActivity::class.java)
        }
    }
}
question from:https://stackoverflow.com/questions/65953094/android-cannot-update-recyclerview

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The issue is with your buttonTest.setOnClickListener() where you are updating the list but the adapter knows nothing about the updation of the arraylist, instead pass the new arraylist to the adapter and call notifyDataSetChanged()

Try the following

CustomAdapter

// add this new function

fun addNewList(newList: List<Parameter>){
   parameterList = newList;
   notifyDataSetChanged();
}

trigger addNewList through buttonTest.setOnClickListener

buttonTest.setOnClickListener() {
       parametersList = parametersList + ParameterText("Temperature", "24°C")
       (rv_parameters2.adapter as CustomAdapter).addNewList(parametersList)
}

Edit:

notifyDataSetChanged() is indeed a costly operation and should be replaced with either notifyItemInserted or a better choice would be to use ListAdapter


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...