Kotlin Android app development course, task management

Hello! This time, as part of a series of lectures on Android app development using Kotlin, we will create a task management application. This application will provide users with the ability to manage their to-do list and will help in learning basic CRUD (Create, Read, Update, Delete) operations.

1. Project Setup

First, we need to set up a new Android project. Open Android Studio and follow these steps:

  • Click on New Project.
  • Select Empty Activity and click Next.
  • Enter ‘TaskManager’ in Project Name and set Language to Kotlin.
  • Finally, click on Finish.

2. Define Data Model

Define a data model class called Task that represents a task. This class will have properties for the task’s title, description, and completion status:

data class Task(
    var id: Long = 0,
    var title: String,
    var description: String,
    var isCompleted: Boolean = false
)

3. Design User Interface

The basic user interface of the task management application consists of the following elements:

  • A RecyclerView that displays the list of tasks
  • A button to add a new task
  • Options to edit and delete tasks

First, we modify the activity_main.xml file to set up the user interface:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_add_task"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add New Task"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

4. Setup RecyclerView

We display the list of tasks using RecyclerView. Next, we create a TaskAdapter class to show the task items in a list format:

class TaskAdapter(private val tasks: List) : RecyclerView.Adapter() {

    inner class TaskViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val taskTitle: TextView = itemView.findViewById(R.id.task_title)
        val taskDescription: TextView = itemView.findViewById(R.id.task_description)
        val taskStatus: CheckBox = itemView.findViewById(R.id.task_status)
    }

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

    override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {
        val task = tasks[position]
        holder.taskTitle.text = task.title
        holder.taskDescription.text = task.description
        holder.taskStatus.isChecked = task.isCompleted

        holder.taskStatus.setOnCheckedChangeListener { _, isChecked ->
            task.isCompleted = isChecked
        }
    }

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

4.1. Create task_item.xml Layout

Create the task_item.xml file for each item in the RecyclerView as follows:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/task_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"/>

    <TextView
        android:id="@+id/task_description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="14sp"/>

    <CheckBox
        android:id="@+id/task_status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

5. Implement Add and Delete Task Features

We will implement the functionality to add new tasks and delete existing ones. Add the following code in MainActivity:

class MainActivity : AppCompatActivity() {

    private val taskList = mutableListOf()
    private lateinit var taskAdapter: TaskAdapter

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

        taskAdapter = TaskAdapter(taskList)
        findViewById(R.id.recycler_view).apply {
            layoutManager = LinearLayoutManager(this@MainActivity)
            adapter = taskAdapter
        }

        findViewById

5.1. Create Task Add Dialog Layout

Create the dialog_add_task.xml file with the following content:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <EditText
        android:id="@+id/task_title_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Task Title"/>

    <EditText
        android:id="@+id/task_description_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Task Description"/>

</LinearLayout>

6. Manage Data Storage

We will use the Room database to maintain the task list even after the app is restarted. Using Room allows us to easily store and manage objects in an SQLite database. We will proceed with the setup for this process:

  • Add Room dependencies to the Gradle file:
dependencies {
    implementation "androidx.room:room-runtime:2.4.1"
    kapt "androidx.room:room-compiler:2.4.1"
}

6.1. Define Room Entity

We define an entity for the Room database using a new TaskEntity class:

@Entity(tableName = "tasks")
data class TaskEntity(
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    val title: String,
    val description: String,
    val isCompleted: Boolean = false
)

6.2. Define DAO Interface

We define a Data Access Object (DAO) interface to interact with the Room database:

@Dao
interface TaskDao {
    @Insert
    suspend fun insert(task: TaskEntity)

    @Query("SELECT * FROM tasks")
    suspend fun getAllTasks(): List

    @Delete
    suspend fun delete(task: TaskEntity)
}

6.3. Define Database Class

We define a database class that inherits from Room Database:

@Database(entities = [TaskEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun taskDao(): TaskDao
}

6.4. Initialize Database

Add logic to the main activity to initialize the database and load tasks:

private lateinit var db: AppDatabase

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

    db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "task-database").build()

    // Load tasks
    loadTasks()
}

private fun loadTasks() {
    CoroutineScope(Dispatchers.IO).launch {
        val tasks = db.taskDao().getAllTasks()
        taskList.clear()
        taskList.addAll(tasks.map { Task(it.id, it.title, it.description, it.isCompleted) })
        runOnUiThread { taskAdapter.notifyDataSetChanged() }
    }
}

7. Implement Task Deletion Feature

We implement functionality that allows users to delete tasks. Add the following code:

override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {
    // Maintain existing code

    holder.itemView.setOnLongClickListener {
        deleteTask(task)
        true
    }
}

private fun deleteTask(task: Task) {
    CoroutineScope(Dispatchers.IO).launch {
        db.taskDao().delete(TaskEntity(task.id, task.title, task.description, task.isCompleted))
        runOnUiThread {
            taskList.remove(task)
            taskAdapter.notifyDataSetChanged()
        }
    }
}

8. Conclusion and Additional Improvements

With this, the basic structure and functionality of your task management application are complete! This application provides users with the ability to add, edit, and delete tasks from their list. You might consider several additional improvements, including:

  • Adding a feature to display the date when a task was completed
  • Adding the ability to set task priorities
  • Adding search and filter functionality for tasks
  • Improving design for better UI/UX

Creating your own task management application using Kotlin and Android Studio will be a great learning experience. I hope this tutorial has been helpful. If you have any questions or need additional information, please leave a comment!