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
- Giữ tham chiếu đến
ArrayListvàArrayAdapterlàm field của Activity. - Sau khi insert/update/delete, gọi
dataList.clear(),addAll()rồiadapter.notifyDataSetChanged(). - 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".