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

Android Activity 傳值給內部類陣列的初始化時機陷阱

     編輯:程式設計疑難解答

在 Android 開發中,Activity 透過 Bundle 接收數據後,若直接用於初始化成員變量陣列(含內部類實例),常因初始化時機導致數據為 null。本文深度剖析此經典陷阱並給出正確模式。

問題場景重現

public class ActivityB extends AppCompatActivity {
    String A, B, C; // 從 Bundle 獲取
    Map mMap = new HashMap<>();
    
    // 內部類
    class Util { String a, b, c; ... }
    class Util2 { String a, b, c; ... }
    
    // 成員變量陣列:類加載時初始化,此時 A/B/C 尚為 null
    public Util[] u = { new Util(A, B, C), ... }; 
    public Util2[] u2 = { new Util2("a", "b", "c"), ... };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        receive(); // 此時賦值 A/B/C
        setArray(); // 遍歷陣列,u 陣列內容為 null
    }
}

根因分析

  • Java 成員變量初始化順序:靜態變量/塊 → 實例變量/塊 → 構造函數
  • u 陣列作為實例變量,在 onCreate() 執行前(構造函數階段)已完成初始化
  • 此時 A/B/C 仍為預設值 null,導致 Util 構造函數接收到 null
  • Util2 使用字面量 "a" 而非變量,故不受影響

正確解決方案

方案一:將陣列改為局部變量,在數據就緒後初始化(推薦)

private void setArray() {
    // 此時 A/B/C 已賦值
    Util[] u = { new Util(A, B, C), new Util(A, B, C), ... };
    Util2[] u2 = { new Util2("a", "b", "c"), ... };
    
    for (Util util : u) { ... }
    for (Util2 util2 : u2) { ... }
}

方案二:使用懶加載 / getter 模式

private Util[] getUArray() {
    if (u == null) {
        u = new Util[] { new Util(A, B, C), ... };
    }
    return u;
}

方案三:在 onCreate 中重新賦值陣列元素


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    receive();
    // 重新構建陣列元素
    u = new Util[] { new Util(A, B, C), new Util(A, B, C), ... };
    setArray();
}

最佳實踐總結

  1. 依賴 Bundle 數據的對象/陣列,勿作為成員變量初始化
  2. 在 onCreate / onStart 等生命週期方法中,確保數據就緒後再構建
  3. 內部類若需外部類數據,優先透過構造函數參數傳遞,而非捕獲成員變量
  4. 使用 lateinit (Kotlin) 或 @Nullable 註解輔助靜態分析

理解 Java 初始化時機與 Android 生命週期的交互,是避免此類「明明有值卻取不到」問題的關鍵。

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