Paramclasses Academy - Blog

Tutorials Details

←
Post 23 of 40
→

How to Build a CRUD Android App Using Java and SQLite ?

How to Build a CRUD Android App Using Java and SQLite ?

November 3, 2026

1. Introduction

Most Android applications need to store, display, update, and delete information. For example, a Student Management App should allow users to add student details, view saved records, edit existing information, and remove unwanted records.

In this tutorial, we will build a complete Student Management CRUD App using Android Studio, Java, SQLite Database, and RecyclerView.

The application will support four main operations:

  • Create: Add a new student record.

  • Read: Display all saved student records.

  • Update: Edit an existing student's information.

  • Delete: Remove a student record from the database.

By the end of this tutorial, you will understand how to connect SQLite with RecyclerView and build a functional database-driven Android application.

2. Project Overview

We will create an application named:

StudentCRUDApp

The application will contain:

  • Student ID generated automatically by SQLite.

  • Student name input field.

  • Student email input field.

  • Add Student button.

  • Update Student button.

  • Clear button.

  • RecyclerView to display all student records.

  • Delete button for each student record.

Application Workflow

  1. The user enters a student's name and email.

  2. The user clicks Add Student.

  3. The application saves the record in SQLite.

  4. RecyclerView displays the saved student.

  5. The user selects a student to edit the details.

  6. The user clicks Update Student to save changes.

  7. The user clicks Delete to remove a record.

3. Create a New Android Studio Project

Follow these steps:

  1. Open Android Studio.

  2. Click New Project.

  3. Select Empty Views Activity.

  4. Enter the project name: StudentCRUDApp.

  5. Select Java as the programming language.

  6. Select your required Minimum SDK.

  7. Click Finish.

Wait for Android Studio to finish building the project.

4. Add RecyclerView Dependency

We will use RecyclerView to display student records.

Open the app-level build.gradle file and add this dependency inside the dependencies block:

implementation 'androidx.recyclerview:recyclerview:1.4.0'

If your project uses build.gradle.kts, use:

implementation("androidx.recyclerview:recyclerview:1.4.0")

Click Sync Now and wait for Gradle synchronization to finish.

5. Create the Student Model Class

First, create a Java class named:

Student.java

This class represents one student record.

package com.example.studentcrudapp;

public class Student {

    private int id;
    private String name;
    private String email;

    public Student(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }
}

Understanding the Code

  • id stores the unique student ID.

  • name stores the student's name.

  • email stores the student's email address.

  • The constructor initializes a student object.

  • Getter methods return the stored values.

The Student class makes it easier to transfer database records into RecyclerView.

6. Create the SQLite Database Helper

Now create another Java class named:

DBHelper.java

This class will manage the database and perform CRUD operations.

package com.example.studentcrudapp;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;

public class DBHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "StudentDB";
    private static final int DATABASE_VERSION = 1;

    private static final String TABLE_NAME = "students";

    private static final String COL_ID = "id";
    private static final String COL_NAME = "name";
    private static final String COL_EMAIL = "email";

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        String query = "CREATE TABLE " + TABLE_NAME + " (" +
                COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_NAME + " TEXT NOT NULL, " +
                COL_EMAIL + " TEXT NOT NULL)";

        db.execSQL(query);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db,
                          int oldVersion,
                          int newVersion) {

        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }

    // CREATE: Insert Student
    public boolean insertStudent(String name, String email) {

        SQLiteDatabase db = getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(COL_NAME, name);
        values.put(COL_EMAIL, email);

        long result = db.insert(TABLE_NAME, null, values);

        return result != -1;
    }

    // READ: Get All Students
    public ArrayList<Student> getAllStudents() {

        ArrayList<Student> studentList = new ArrayList<>();

        SQLiteDatabase db = getReadableDatabase();

        try (Cursor cursor = db.query(
                TABLE_NAME,
                null,
                null,
                null,
                null,
                null,
                COL_ID + " DESC")) {

            while (cursor.moveToNext()) {

                int id = cursor.getInt(
                        cursor.getColumnIndexOrThrow(COL_ID));

                String name = cursor.getString(
                        cursor.getColumnIndexOrThrow(COL_NAME));

                String email = cursor.getString(
                        cursor.getColumnIndexOrThrow(COL_EMAIL));

                Student student = new Student(id, name, email);

                studentList.add(student);
            }
        }

        return studentList;
    }

    // UPDATE: Update Student
    public boolean updateStudent(int id, String name, String email) {

        SQLiteDatabase db = getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(COL_NAME, name);
        values.put(COL_EMAIL, email);

        int result = db.update(
                TABLE_NAME,
                values,
                COL_ID + " = ?",
                new String[]{String.valueOf(id)}
        );

        return result > 0;
    }

    // DELETE: Delete Student
    public boolean deleteStudent(int id) {

        SQLiteDatabase db = getWritableDatabase();

        int result = db.delete(
                TABLE_NAME,
                COL_ID + " = ?",
                new String[]{String.valueOf(id)}
        );

        return result > 0;
    }
}

Understanding the Database Helper

Database creation

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(query);
}

This method creates the students table when the database is created for the first time.

Insert operation

db.insert(TABLE_NAME, null, values);

This statement inserts a new student record into SQLite.

Read operation

ArrayList<Student> studentList = new ArrayList<>();

The ArrayList stores Student objects retrieved from the database.

Update operation

db.update(
    TABLE_NAME,
    values,
    COL_ID + " = ?",
    new String[]{String.valueOf(id)}
);

This updates only the student whose ID matches the supplied ID.

Delete operation

db.delete(
    TABLE_NAME,
    COL_ID + " = ?",
    new String[]{String.valueOf(id)}
);

This deletes the selected student record.

Using selection arguments keeps user-supplied values separate from the SQL statement.

Important: The onUpgrade() method above drops the existing table and recreates it. This is only a simple demonstration strategy. A real application should use database migrations to preserve existing records.

7. Design the Main Activity Layout

Open:

activity_main.xml

Replace the existing layout with the following code:

<?xml version="1.0" encoding="utf-8"?>

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Student Management App"
        android:textSize="24sp"
        android:textStyle="bold"
        android:gravity="center"
        android:padding="12dp" />

    <EditText
        android:id="@+id/etName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Student Name"
        android:inputType="textPersonName" />

    <EditText
        android:id="@+id/etEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Student Email"
        android:inputType="textEmailAddress" />

    <Button
        android:id="@+id/btnAdd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add Student" />

    <Button
        android:id="@+id/btnUpdate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Update Student"
        android:enabled="false" />

    <Button
        android:id="@+id/btnClear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Clear Fields" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Student Records"
        android:textSize="20sp"
        android:textStyle="bold"
        android:paddingTop="12dp"
        android:paddingBottom="8dp" />

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

</LinearLayout>

Understanding the Layout

  • etName accepts the student's name.

  • etEmail accepts the student's email.

  • btnAdd inserts a new student.

  • btnUpdate updates the selected student.

  • btnClear clears the input fields.

  • recyclerView displays the saved student records.

The Update button is disabled initially because no student has been selected.

8. Create the Student Item Layout

RecyclerView needs a separate layout for each student item.

Create a new layout resource file:

item_student.xml

Add this code:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="12dp"
    android:layout_marginBottom="8dp"
    android:background="#EEEEEE">

    <TextView
        android:id="@+id/tvId"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ID: 1"
        android:textStyle="bold"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/tvName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Name: Rahul"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/tvEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Email: rahul@gmail.com"
        android:textSize="14sp" />

    <Button
        android:id="@+id/btnDelete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Delete" />

</LinearLayout>

Each student item displays the ID, name, email, and a Delete button.

9. Create the RecyclerView Adapter

Now create a Java class named:

StudentAdapter.java

The adapter connects the student data with the RecyclerView item layout.

package com.example.studentcrudapp;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {

    private ArrayList<Student> studentList;

    private OnStudentClickListener listener;

    public interface OnStudentClickListener {

        void onStudentClick(Student student);

        void onDeleteClick(Student student);
    }

    public StudentAdapter(ArrayList<Student> studentList,
                          OnStudentClickListener listener) {

        this.studentList = studentList;
        this.listener = listener;
    }

    public static class StudentViewHolder
            extends RecyclerView.ViewHolder {

        TextView tvId, tvName, tvEmail;
        Button btnDelete;

        public StudentViewHolder(@NonNull View itemView) {
            super(itemView);

            tvId = itemView.findViewById(R.id.tvId);
            tvName = itemView.findViewById(R.id.tvName);
            tvEmail = itemView.findViewById(R.id.tvEmail);

            btnDelete = itemView.findViewById(R.id.btnDelete);
        }
    }

    @NonNull
    @Override
    public StudentViewHolder onCreateViewHolder(
            @NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_student, parent, false);

        return new StudentViewHolder(view);
    }

    @Override
    public void onBindViewHolder(
            @NonNull StudentViewHolder holder, int position) {

        Student student = studentList.get(position);

        holder.tvId.setText("ID: " + student.getId());

        holder.tvName.setText("Name: " + student.getName());

        holder.tvEmail.setText("Email: " + student.getEmail());

        holder.itemView.setOnClickListener(v ->
                listener.onStudentClick(student));

        holder.btnDelete.setOnClickListener(v ->
                listener.onDeleteClick(student));
    }

    @Override
    public int getItemCount() {
        return studentList.size();
    }
}

Understanding the Adapter

ViewHolder

The ViewHolder stores references to the views inside each student item.

onCreateViewHolder()

This method creates a new item view using item_student.xml.

onBindViewHolder()

This method displays the selected student's ID, name, and email.

It also handles two user actions:

  • Clicking the student item sends the selected student to MainActivity for editing.

  • Clicking Delete requests deletion of that student.

getItemCount()

This method returns the total number of student records in the list.

10. Implement CRUD Operations in MainActivity.java

Now open:

MainActivity.java

Replace the existing code with:

package com.example.studentcrudapp;

import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    EditText etName, etEmail;

    Button btnAdd, btnUpdate, btnClear;

    RecyclerView recyclerView;

    DBHelper dbHelper;

    StudentAdapter adapter;

    ArrayList<Student> studentList;

    int selectedStudentId = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        etName = findViewById(R.id.etName);
        etEmail = findViewById(R.id.etEmail);

        btnAdd = findViewById(R.id.btnAdd);
        btnUpdate = findViewById(R.id.btnUpdate);
        btnClear = findViewById(R.id.btnClear);

        recyclerView = findViewById(R.id.recyclerView);

        dbHelper = new DBHelper(this);

        recyclerView.setLayoutManager(
                new LinearLayoutManager(this));

        loadStudents();

        // ADD STUDENT
        btnAdd.setOnClickListener(v -> {

            String name = etName.getText().toString().trim();

            String email = etEmail.getText().toString().trim();

            if (!validateInput(name, email)) {
                return;
            }

            boolean inserted = dbHelper.insertStudent(name, email);

            if (inserted) {

                Toast.makeText(this,
                        "Student Added Successfully",
                        Toast.LENGTH_SHORT).show();

                clearFields();
                loadStudents();

            } else {

                Toast.makeText(this,
                        "Unable to Add Student",
                        Toast.LENGTH_SHORT).show();
            }
        });

        // UPDATE STUDENT
        btnUpdate.setOnClickListener(v -> {

            String name = etName.getText().toString().trim();

            String email = etEmail.getText().toString().trim();

            if (selectedStudentId == -1) {

                Toast.makeText(this,
                        "Please Select a Student",
                        Toast.LENGTH_SHORT).show();

                return;
            }

            if (!validateInput(name, email)) {
                return;
            }

            boolean updated = dbHelper.updateStudent(
                    selectedStudentId,
                    name,
                    email
            );

            if (updated) {

                Toast.makeText(this,
                        "Student Updated Successfully",
                        Toast.LENGTH_SHORT).show();

                clearFields();
                loadStudents();

            } else {

                Toast.makeText(this,
                        "Update Failed",
                        Toast.LENGTH_SHORT).show();
            }
        });

        // CLEAR FIELDS
        btnClear.setOnClickListener(v -> clearFields());
    }

    // LOAD STUDENTS INTO RECYCLERVIEW
    private void loadStudents() {

        studentList = dbHelper.getAllStudents();

        adapter = new StudentAdapter(
                studentList,
                new StudentAdapter.OnStudentClickListener() {

                    @Override
                    public void onStudentClick(Student student) {

                        selectedStudentId = student.getId();

                        etName.setText(student.getName());

                        etEmail.setText(student.getEmail());

                        btnUpdate.setEnabled(true);

                        btnAdd.setEnabled(false);
                    }

                    @Override
                    public void onDeleteClick(Student student) {

                        boolean deleted = dbHelper.deleteStudent(
                                student.getId());

                        if (deleted) {

                            Toast.makeText(MainActivity.this,
                                    "Student Deleted Successfully",
                                    Toast.LENGTH_SHORT).show();

                            if (selectedStudentId == student.getId()) {
                                clearFields();
                            }

                            loadStudents();

                        } else {

                            Toast.makeText(MainActivity.this,
                                    "Delete Failed",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                }
        );

        recyclerView.setAdapter(adapter);
    }

    // VALIDATE INPUT
    private boolean validateInput(String name, String email) {

        if (name.isEmpty()) {

            etName.setError("Enter Student Name");

            return false;
        }

        if (email.isEmpty()) {

            etEmail.setError("Enter Student Email");

            return false;
        }

        if (!android.util.Patterns.EMAIL_ADDRESS
                .matcher(email).matches()) {

            etEmail.setError("Enter a Valid Email");

            return false;
        }

        return true;
    }

    // CLEAR INPUT FIELDS
    private void clearFields() {

        etName.setText("");
        etEmail.setText("");

        selectedStudentId = -1;

        btnUpdate.setEnabled(false);
        btnAdd.setEnabled(true);
    }

    @Override
    protected void onDestroy() {

        if (dbHelper != null) {
            dbHelper.close();
        }

        super.onDestroy();
    }
}

Important: If your application has a different package name, replace com.example.studentcrudapp in all Java files with your actual package name.

11. Understand How the Complete App Works

Now let's understand the application workflow.

Add Student

When the user enters a name and email and clicks Add Student:

  1. MainActivity reads the input fields.

  2. The application validates the input.

  3. insertStudent() sends the data to DBHelper.

  4. SQLite saves the new record.

  5. loadStudents() retrieves the updated list.

  6. RecyclerView displays the new record.

View Student Records

The loadStudents() method retrieves all saved records:

studentList = dbHelper.getAllStudents();

The adapter receives this list and displays each student using item_student.xml.

Select a Student for Update

When the user clicks a student item:

selectedStudentId = student.getId();

etName.setText(student.getName());

etEmail.setText(student.getEmail());

The selected student's ID is stored separately, and the existing information is displayed in the input fields.

The Update button becomes enabled, while the Add button is disabled.

Update Student

When the user clicks Update Student:

dbHelper.updateStudent(
        selectedStudentId,
        name,
        email
);

The database updates the record using its unique ID.

Delete Student

When the user clicks the Delete button:

dbHelper.deleteStudent(student.getId());

The selected record is removed from SQLite, and the RecyclerView is refreshed.

12. Run and Test the Application

Now run your application on an Android emulator or a real Android phone.

Follow these testing steps.

Test 1: Add Students

Enter the following information:

Name: Rahul Sharma
Email: rahul@gmail.com

Click Add Student.

Now add another record:

Name: Amit Kumar
Email: amit@gmail.com

Both records should appear in RecyclerView.

Test 2: Update Student

  1. Click the Rahul Sharma record.

  2. The existing name and email will appear in the input fields.

  3. Change the name to Rahul Verma.

  4. Change the email to rahulverma@gmail.com.

  5. Click Update Student.

The updated information should appear in RecyclerView.

Test 3: Delete Student

  1. Find the Amit Kumar record.

  2. Click its Delete button.

  3. The record will be removed from SQLite.

  4. RecyclerView will refresh automatically.

Test 4: Verify Data Persistence

  1. Add a student record.

  2. Close the application.

  3. Open the application again.

  4. Check the RecyclerView.

The saved student record should still be available because SQLite stores the data locally.

13. View Database Records Using Database Inspector

Android Studio provides Database Inspector to inspect the application's database.

Follow these steps:

  1. Run your application on an emulator or supported device.

  2. Open View.

  3. Select Tool Windows.

  4. Open App Inspection.

  5. Select Database Inspector.

  6. Find the StudentDB database.

  7. Expand the students table.

You can execute this SQL query:

SELECT * FROM students;

It displays the student records stored in SQLite.

14. Common Errors and Solutions

Error 1: RecyclerView Is Not Displaying Records

Possible reason: The adapter is not connected to RecyclerView.

Solution: Check whether recyclerView.setAdapter(adapter) is called inside loadStudents().

Error 2: Add Student Button Is Not Working

Possible reason: The input fields are empty or validation is failing.

Solution: Enter a valid student name and email address.

Error 3: Update Student Is Not Working

Possible reason: No student has been selected.

Solution: Click a student item before updating its information.

Error 4: Delete Button Is Not Working

Possible reason: The student ID is incorrect or the record does not exist.

Solution: Check the selected Student object and its ID.

Error 5: Database Changes Are Not Displaying

Possible reason: RecyclerView has not been refreshed.

Solution: Call loadStudents() after a successful insert, update, or delete operation.

15. Important Development Best Practices

When building a real-world CRUD application, remember these points:

  1. Validate all user inputs before saving them.

  2. Use unique primary keys to identify database records.

  3. Use selection arguments for update and delete queries.

  4. Keep database operations separate from RecyclerView adapter code.

  5. Refresh the displayed list after database changes.

  6. Close database resources when they are no longer needed.

  7. Perform potentially long-running database operations on background threads.

  8. Use database migrations when changing an existing database schema.

  9. Consider Room for new applications that need a higher-level abstraction over SQLite.

16. Conclusion

In this tutorial, you learned how to build a complete CRUD Android application using Java and SQLite.

You created a Student model class, implemented SQLite database operations, designed an Android interface, and connected student records to RecyclerView using a custom adapter.

You also implemented Add, View, Update, and Delete functionality and tested database persistence.

This project demonstrates how Android applications can manage structured data locally without requiring an external database server.

Practice Task: Extend the Student Management App by adding a phone number field. Update the database table, Student model, input layout, adapter, and CRUD methods to support phone numbers.

←
Post 23 of 40
→