ListView 點擊事件回傳的 position 僅為視圖位置,非資料庫主鍵 ID。本文針對您使用 SimpleCursorAdapter 的場景,詳細講解如何正確獲取資料庫 _id,並解析您自行找到的解決方案。
您的原始代碼:
@Override
public void onListItemClick(ListView parent, View view, int position, long id) {
Intent intent = new Intent(this, VSDetailsActivity.class);
intent.putExtra("com.manager.boot.r1223." + BaseColumns._ID, position); // 錯誤:傳遞 position
startActivity(intent);
}
position 是列表可見項目索引 (0-based),會隨排序、過濾、刪除而變化。_id 是資料庫主鍵,唯一且穩定。
您找到的解決方案完全正確:
@Override
public void onListItemClick(ListView parent, View view, int position, long id) {
Cursor cursor = (Cursor) adapter.getItem(position); // 關鍵:獲取該位置的 Cursor
Intent intent = new Intent(this, VSDetailsActivity.class);
intent.putExtra("com.manager.boot.r1223." + BaseColumns._ID,
cursor.getInt(cursor.getColumnIndex("_id"))); // 獲取真實 _id
startActivity(intent);
}
adapter.getItem(position):CursorAdapter 重寫此方法回傳對應位置的 Cursor (已移動到該行)cursor.getColumnIndex("_id"):獲取 _id 欄位索引 (建議用常數 BaseColumns._ID)cursor.getInt(...):讀取長整數主鍵值前提:您的 Cursor 查詢必須包含 _id 欄位,且 Adapter 建構時正確關聯:
// 查詢必須包含 _id
String[] from = { "name", "desc", "status", "path", "folder", BaseColumns._ID };
// Adapter 會自動將 _id 映射到 id 參數
// 於是 onListItemClick 的 long id 即為 _id 值
@Override
public void onListItemClick(ListView parent, View view, int position, long id) {
Intent intent = new Intent(this, VSDetailsActivity.class);
intent.putExtra("com.manager.boot.r1223." + BaseColumns._ID, id); // 直接使用
startActivity(intent);
}
這是 CursorAdapter 設計意圖:id 參數即為 Cursor 中 _id 欄位值。
檢查您的查詢:
String[] from = { "name", "desc", "status", "path", "folder", BaseColumns._ID };
這看起來是正確的。可能原因:
_id (別名不對、查詢語句漏選)CursorAdapter 子類 (但您用的是 VSsimplecursoradapter 繼承 SimpleCursorAdapter)建議加入防禦性檢查:
Cursor cursor = (Cursor) adapter.getItem(position);
if (cursor != null && !cursor.isClosed()) {
int idIndex = cursor.getColumnIndex(BaseColumns._ID);
if (idIndex >= 0) {
long realId = cursor.getLong(idIndex);
// 使用 realId
}
}
ListActivity、SimpleCursorAdapter、startManagingCursor 均已棄用。現代架構:
// Room Dao
@Query("SELECT * FROM mfs ORDER BY name")
Flow> getAllItems();
// Fragment/ViewModel
itemsFlow.collect { items ->
adapter.submitList(items)
}
// Adapter 點擊
adapter.setOnItemClickListener(item -> {
Intent intent = new Intent(context, DetailActivity.class);
intent.putExtra("ITEM_ID", item.id); // 直接用資料類別的 id
startActivity(intent);
});
獲取 ListView 項目真實 ID 的標準做法:
adapter.getItem(position) 獲取 Cursor,再讀取 _id 欄位 (您的解決方案)onListItemClick 的 long id 參數您的自行解決方案正確且符合當時 API 設計模式。建議新專案直接採用現代架構,從根本消除此類問題。