Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách cập nhật ListView sau khi chèn dữ liệu vào SQLite Android

Vấn đề thường gặp

Sau khi thêm dữ liệu vào SQLite, ListView không tự động cập nhật. Cần gọi notifyDataSetChanged() trên adapter sau khi nạp lại dữ liệu từ cursor.

Quy trình thực hiện

Bước 1: Tạo dự án mới

Bước 2: activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText android:id="@+id/name" android:layout_width="match_parent"
        android:hint="Nhập tên" android:layout_height="wrap_content"/>
    <EditText android:id="@+id/salary" android:layout_width="match_parent"
        android:inputType="numberDecimal" android:hint="Nhập lương"
        android:layout_height="wrap_content"/>

    <LinearLayout android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <Button android:id="@+id/save" android:text="Lưu"
            android:layout_width="wrap_content" android:layout_height="wrap_content"/>
        <Button android:id="@+id/refresh" android:text="Làm mới"
            android:layout_width="wrap_content" android:layout_height="wrap_content"/>
    </LinearLayout>

    <ListView android:id="@+id/listView"
        android:layout_width="match_parent" android:layout_height="wrap_content"/>
</LinearLayout>

Bước 3: MainActivity.java - Logic cập nhật ListView

package com.example.listviewupdatedemo;

import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    Button save, refresh;
    EditText name, salary;
    ListView listView;
    ArrayAdapter<String> adapter;
    ArrayList<String> dataList;
    DatabaseHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        helper = new DatabaseHelper(this);
        dataList = helper.getAllContacts();

        name = findViewById(R.id.name);
        salary = findViewById(R.id.salary);
        listView = findViewById(R.id.listView);

        adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, dataList);
        listView.setAdapter(adapter);

        findViewById(R.id.refresh).setOnClickListener(v -> refreshList());

        findViewById(R.id.save).setOnClickListener(v -> {
            String n = name.getText().toString().trim();
            String s = salary.getText().toString().trim();
            if (!n.isEmpty() && !s.isEmpty()) {
                if (helper.insert(n, s)) {
                    Toast.makeText(this, "Đã thêm", Toast.LENGTH_SHORT).show();
                    refreshList(); // Cập nhật ngay sau khi insert
                    name.setText("");
                    salary.setText("");
                } else {
                    Toast.makeText(this, "Thêm thất bại", Toast.LENGTH_SHORT).show();
                }
            } else {
                name.setError("Nhập tên");
                salary.setError("Nhập lương");
            }
        });
    }

    private void refreshList() {
        dataList.clear();
        dataList.addAll(helper.getAllContacts());
        adapter.notifyDataSetChanged(); // Quan trọng: báo cho ListView biết dữ liệu thay đổi
    }
}

Bước 4: DatabaseHelper.java

package com.example.listviewupdatedemo;

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;

class DatabaseHelper extends SQLiteOpenHelper {
    static final String DB_NAME = "salaryDatabase";
    static final String TABLE = "SalaryDetails";

    DatabaseHelper(Context context) {
        super(context, DB_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + TABLE + "(id INTEGER PRIMARY KEY, name TEXT, salary TEXT)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int old, int n) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE);
        onCreate(db);
    }

    boolean insert(String name, String salary) {
        SQLiteDatabase db = getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("name", name);
        cv.put("salary", salary);
        return db.insert(TABLE, null, cv) != -1;
    }

    ArrayList<String> getAllContacts() {
        ArrayList<String> list = new ArrayList<>();
        SQLiteDatabase db = getReadableDatabase();
        Cursor c = db.rawQuery("SELECT * FROM " + TABLE, null);
        if (c.moveToFirst()) {
            do {
                list.add(c.getString(c.getColumnIndexOrThrow("name")));
            } while (c.moveToNext());
        }
        c.close();
        return list;
    }
}

Điểm then chốt

  1. Giữ tham chiếu đến ArrayList và ArrayAdapter làm field của Activity.
  2. Sau khi insert/update/delete, gọi dataList.clear(), addAll() rồi adapter.notifyDataSetChanged().
  3. Không tạo adapter mới mỗi lần - chỉ cập nhật dữ liệu bên trong list hiện có.

Mở rộng: Sử dụng CursorAdapter (LoaderManager)

Đối với ứng dụng phức tạp, nên dùng CursorAdapter kết hợp LoaderManager để tự động theo dõi thay đổi cơ sở dữ liệu và cập nhật UI mà không cần nút "Làm mới".