首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android ListView 傳遞數據到 onItemClick:CursorAdapter 最佳實踐與現代遷移

     編輯:程式設計綜合問答

問題場景

SimpleCursorAdapter 綁定 Cursor,點擊項目需獲取 gotoURL 字段傳遞給下一個 Activity。

錯誤做法:直接在 Adapter 持有 Cursor 並暴露字段


// Adapter 中暴露靜態字段 (極差實踐)
public static String gotoURL; // 多線程不安全、數據錯亂、記憶體洩漏

方案一:在 onItemClick 中通過 Cursor 獲取 (傳統修正)


lv.setOnItemClickListener((parent, view, position, id) -> {
    // 關鍵:移動 Cursor 到點擊位置
    Cursor cursor = (Cursor) parent.getItemAtPosition(position);
    if (cursor != null) {
        int urlIndex = cursor.getColumnIndex("gotoURL");
        String url = cursor.getString(urlIndex);
        
        Intent intent = new Intent(List_AC.this, DocView.class);
        intent.putExtra("url", url);
        startActivity(intent);
    }
});

注意:parent.getItemAtPosition(position) 返回的是 Cursor,需先 moveToPosition (SimpleCursorAdapter 內部已處理)。

方案二:提取數據模型,使用 ArrayList + BaseAdapter (推薦傳統)


// 1. 定義數據模型
class AdvisoryItem {
    String label, title, description, gotoURL;
}

// 2. 查詢數據庫轉為 List
List items = new ArrayList<>();
Cursor cursor = db.rawQuery("SELECT * FROM AC_list ORDER BY label ASC", null);
while (cursor.moveToNext()) {
    AdvisoryItem item = new AdvisoryItem();
    item.label = cursor.getString(cursor.getColumnIndex("label"));
    item.title = cursor.getString(cursor.getColumnIndex("title"));
    item.description = cursor.getString(cursor.getColumnIndex("description"));
    item.gotoURL = cursor.getString(cursor.getColumnIndex("gotoURL"));
    items.add(item);
}
cursor.close();

// 3. 自定義 Adapter
class AdvisoryAdapter extends BaseAdapter {
    private List items;
    // ... getView 中綁定 items.get(position)

    @Override
    public AdvisoryItem getItem(int position) {
        return items.get(position);
    }
}

// 4. 點擊獲取模型對象
lv.setOnItemClickListener((parent, view, position, id) -> {
    AdvisoryItem item = (AdvisoryItem) parent.getItemAtPosition(position);
    Intent intent = new Intent(List_AC.this, DocView.class);
    intent.putExtra("url", item.gotoURL);
    startActivity(intent);
});

方案三:RecyclerView + ListAdapter + DiffUtil (現代標準)


// Adapter
class AdvisoryAdapter extends ListAdapter 
    extends ListAdapter(DIFF_CALLBACK) {

    static final DiffUtil.ItemCallback DIFF_CALLBACK = 
        new DiffUtil.ItemCallback() {
            @Override boolean areItemsTheSame(AdvisoryItem old, AdvisoryItem n) {
                return old.gotoURL.equals(n.gotoURL); // 唯一標識
            }
            @Override boolean areContentsTheSame(AdvisoryItem old, AdvisoryItem n) {
                return old.equals(n);
            }
        };

    // ViewHolder 綁定...
    // Activity 中點擊可用 OnItemTouchListener 或 ViewHolder 內部點擊
}

核心原則總結

  1. 不要在 Adapter 中暴露靜態/公共字段存儲數據:並發不安全、生命周期混亂
  2. 優先提取純數據模型 (POJO/Entity):解耦視圖與數據庫、便於測試、支援 DiffUtil
  3. 點擊回調中從 Adapter 獲取模型對象:adapter.getItem(position) 或 parent.getItemAtPosition(position)
  4. 新專案直接用 RecyclerView + ListAdapter:自動動畫、局部刷新、支援異步列表更新
  5. 異步查詢數據庫:Room + LiveData/Flow 自動在後台線程查詢,主線程觀察結果
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved