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

Android 利用反射遍歷 R.raw、R.drawable 等資源 ID 的方法與風險提示

     編輯:程式設計綜合問答

反射遍歷代碼


public void listRawResources() {
    Field[] fields = R.raw.class.getDeclaredFields();
    for (Field field : fields) {
        try {
            int resId = field.getInt(null); // static field, object 參數為 null
            String resName = field.getName();
            Log.d("RAW_RES", "Name: " + resName + ", ID: 0x" + Integer.toHexString(resId));
            // 使用資源
            // InputStream is = getResources().openRawResource(resId);
        } catch (IllegalAccessException e) {
            Log.e("RAW_RES", "Access failed: " + field.getName(), e);
        }
    }
}

關鍵點

  • R.xxx.class.getDeclaredFields() 獲取所有靜態字段(資源 ID)。
  • field.getInt(null) 讀取靜態 int 值,傳 null 而非實例。
  • 同理可遍歷 R.drawable、R.string、R.layout 等內部類。

實際輸出示例


D/RAW_RES: Name: song, ID: 0x7f040000
D/RAW_RES: Name: background_music, ID: 0x7f040001

⚠️ 重大風險與不推薦理由

  1. 資源 ID 不穩定:每次構建(尤其是清理重建)ID 可能變化,不可持久化存儲。
  2. 混淆/壓縮影響:R8/ProGuard 可能重命名/移除未直接引用的資源,導致反射獲取不到。
  3. 性能開銷:反射慢於直接引用,主線程大量遍歷會卡頓。
  4. 語義模糊:失去編譯期檢查,拼寫錯誤只能運行時發現。
  5. 違背資源系統設計初衷:資源本意是靜態聲明、編譯期綁定。

推薦替代方案

需求正規做法
動態播放多個 raw 音頻將檔名存入 assets/playlist.json 或 res/values/arrays.xml,讀取名稱後 getResources().getIdentifier(name, "raw", getPackageName()) 獲取 ID
批量加載 drawable命名規律(如 img_01...img_20)循環 getIdentifier,或使用 TypedArray 定義 <array name="imgs"><item>@drawable/img_01</item>...</array>
運行時列出所有資源極少見真實需求,若確需,構建期腳本生成索引文件打包進 assets

總結

反射遍歷 R 類技術上可行,但屬於「技術債」,生產環境嚴禁使用。善用 getIdentifier、TypedArray、資產文件索引等正規機制,保證構建穩定與可維護性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved