DEV Community

Devika Android
Devika Android

Posted on

How to Implement Room Database CRUD in Android with RecyclerView (Step-by-Step Kotlin Guide)

In this blog, we will learn how to implement complete CRUD (Create, Read, Update, Delete) operations using Room Database in Android with Kotlin. This guide covers a practical implementation using RecyclerView to display data and perform real-time updates.

We will build a simple user management feature where users can add, view, update, and delete records. The project uses modern Android development practices including Coroutines, LiveData for observing database changes, and a clean adapter-based RecyclerView setup.

By the end of this tutorial, you will understand how to:
Insert data into Room Database
Observe and display data using LiveData
Update existing records dynamically
Delete items directly from RecyclerView
Structure your code for better scalability

class RoomDatabaseActivity : AppCompatActivity() {
    private lateinit var binding: ActivityRoomDatabaseBinding
    private lateinit var db: AppDatabase

    private lateinit var userAdapter: UserAdapter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        binding = DataBindingUtil.setContentView(this, R.layout.activity_room_database)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
        initView()
    }

    private fun initView() {
        db = DatabaseBuilder.getInstance(this@RoomDatabaseActivity)

        userAdapter = UserAdapter(onDelete = { userData ->
            lifecycleScope.launch {
                db.userDao().deleteUser(userData)
            }
        }, onUpdate = { userData ->
            lifecycleScope.launch {
                db.userDao().updateUser(
                    userData.copy(name = userData.name + " Updated")
                )
            }
        })

        binding.rvUser.adapter = userAdapter
        binding.rvUser.layoutManager = LinearLayoutManager(this)

        binding.btnSubmit.setOnClickListener {
            if (binding.edtAge.text.toString().isNotEmpty() && binding.edtName.text.toString()
                    .isNotEmpty()
            ) {
                lifecycleScope.launch {

                    db.userDao().insertUser(
                        User(
                            name = binding.edtName.text.toString().trim(),
                            age = binding.edtAge.text.toString().toInt()
                        )
                    )
                }
            } else {
                Toast.makeText(this, "Enter Name & Age", Toast.LENGTH_SHORT).show()
            }
        }

        lifecycleScope.launch {
            db.userDao().getAllUsers().observe(this@RoomDatabaseActivity) { userList ->
                userAdapter.setData(userList)
            }
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

implement Room Database in Android with Kotlin, including Entity, DAO, CRUD operations, and a singleton database setup using best practices.

Database class

@Database(entities = [User::class], version = 1)
abstract class AppDatabase: RoomDatabase() {
    abstract fun userDao(): UserDao
}
Enter fullscreen mode Exit fullscreen mode

User Table(Model)

@Entity(tableName = "user_table")
data class User(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    val name: String,
    val age: Int
)

Enter fullscreen mode Exit fullscreen mode

UserDao Class

@Dao
interface UserDao {
    // CREATE
    @Insert
    suspend fun insertUser(user: User)

    // READ
    @Query("SELECT * FROM user_table")
    fun getAllUsers(): LiveData<List<User>>

    // UPDATE
    @Update
    suspend fun updateUser(user: User)

    // DELETE
    @Delete
    suspend fun deleteUser(user: User)
}
Enter fullscreen mode Exit fullscreen mode

Create Database Instance


object DatabaseBuilder {
    private var INSTANCE: AppDatabase? = null

    fun getInstance(context: Context): AppDatabase {
        return INSTANCE ?: synchronized(this) {
            val instance = Room.databaseBuilder(
                context.applicationContext,
                AppDatabase::class.java,
                "user_db"
            ).build()
            INSTANCE = instance
            instance
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Adapter For Display Data

class UserAdapter(
    private val onDelete: (User) -> Unit,
    private val onUpdate: (User) -> Unit
) : RecyclerView.Adapter<UserAdapter.ViewHolder>() {
    private var list = ArrayList<User>()

    fun setData(data: List<User>) {
        list.clear()
        list.addAll(data)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ViewHolder {
        val binding =
            ItemUserDesignBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(
        holder: ViewHolder,
        position: Int
    ) {
        val itemData = list[position]
        holder.setData(itemData, onDelete, onUpdate)

    }

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

    class ViewHolder(private val binding: ItemUserDesignBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun setData(itemData: User, onDelete: (User) -> Unit, onUpdate: (User) -> Unit) {
            binding.tvName.text = itemData.name
            binding.tvAge.text = itemData.age.toString()

            binding.btnDelete.setOnClickListener {
                onDelete(itemData)
            }

            binding.btnUpdate.setOnClickListener {
                onUpdate(itemData)
            }
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

This guide demonstrates how to implement Room Database in Android using Kotlin. It covers creating an Entity to define the table structure, a DAO for handling CRUD operations, and a Database class to manage data access.

A singleton pattern is used to ensure a single instance of the database throughout the app. LiveData is utilized to observe data changes and automatically update the UI, making the app more reactive and efficient.

Overall, this setup provides a simple and scalable approach to local data storage in Android applications.

Top comments (0)