Reputation: 947
i have this problem.
I've defined simple activity with RecyclerView
and i wan't to add an item on button click. I've defined custom RecyclerView.Adapter
just like many examples available on the internet, but the view doesn't respond to the data change (todos are being added to todos
list). Could someone please take a look and tell me what am i missing?
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val addButton: FloatingActionButton by lazy { add_button }
private val todoView: RecyclerView by lazy { todo_view }
private val todos = mutableListOf<Todo>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
todoView.adapter = TodoRecyclerAdapter(todos)
todoView.layoutManager = LinearLayoutManager(this)
addButton.setOnClickListener {
todos.add(Todo("test", "dasdasdas", "11-12-19"))
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.menu_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
TodoRecyclerAdapter.kt
class TodoRecyclerAdapter(private val todos: List<Todo>) : RecyclerView.Adapter<TodoViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder =
LayoutInflater
.from(parent.context)
.inflate(R.layout.layout_todo_item, parent, false)
.let { TodoViewHolder(it) }
override fun onBindViewHolder(viewHolder: TodoViewHolder, position: Int) {
todos[position].run {
viewHolder.title.text = title
viewHolder.dueDate.text = dueDate
}
viewHolder.parent.setOnClickListener {
println("Clicked $position item")
}
}
override fun getItemCount(): Int = todos.size
inner class TodoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val parent: ConstraintLayout = itemView.findViewById(R.id.todo_item)
val title: TextView = itemView.findViewById(R.id.todo_title)
val dueDate: TextView = itemView.findViewById(R.id.todo_due_date)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp" android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginTop="8dp"
app:layout_constraintTop_toTopOf="parent" android:layout_margin="8dp" android:id="@+id/todo_view"
android:layout_width="match_parent" android:layout_height="657dp" android:layout_gravity="bottom"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email"/>
</android.support.design.widget.CoordinatorLayout>
layout_todo_item.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="wrap_content"
android:background="@color/todoColor"
android:id="@+id/todo_item">
<TextView
android:layout_width="370dp"
android:layout_height="32dp" android:id="@+id/todo_title"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/todo_due_date" android:layout_marginTop="10dp"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp"
android:textSize="18sp" app:layout_constraintHorizontal_bias="0.52"
app:layout_constraintVertical_bias="1.0" android:text="@tools:sample/cities"/>
<TextView
android:layout_width="369dp"
android:layout_height="21dp" android:id="@+id/todo_due_date"
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="6dp"
android:layout_marginEnd="8dp" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp"
tools:text="@tools:sample/date/ddmmyy"/>
</android.support.constraint.ConstraintLayout>
Todo is just a simple data class. When i run the app on debug, the TodoRecyclerAdapter methods are not being called at all.
Upvotes: 0
Views: 708
Reputation: 1723
In your MainActivity you have the following code:
addButton.setOnClickListener {
todos.add(Todo("test", "dasdasdas", "11-12-19"))
}
This simply adds a Todo
to the list of todos
. The adapter has already received the list before this change and created the todoView
accordingly. In order to update todoView
with the updated list, you need to explicitly tell the adapter that the data has changed.
You can do so like this:
addButton.setOnClickListener {
todos.add(Todo("test", "dasdasdas", "11-12-19"))
todoView.adapter.notifyDataSetChanged()
}
However, since you're only adding an item to the list, you may want to use
notifyItemInserted(int position) instead.
Upvotes: 2