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

Android TextView 跨 Activity 顯示數據:Intent Extra 傳遞 vs 共享 ViewModel 方案

     編輯:程式設計綜合問答

原問題嘗試在 Activity A 中通過 findViewById 直接操作 Activity C 的 TextView,這違反 Android 組件生命週期:非當前顯示的 Activity 其視圖層級可能未創建、已銷毀、或根本不存在。正確做法是傳遞數據而非控件引用。

錯誤認知


// ❌ 錯誤:嘗試在 Activity A 直接訪問 Activity C 的 View
TextView tv = (TextView) findViewById(R.id.showmsg); // 這裡的 R.id 屬於當前 Activity 佈局
tv.setText("data"); // 即使不崩潰,也操作的是 Activity A 自己的 View

方案一:Intent Extra 傳遞基礎數據(最簡單)


// Activity A (發送方)
Intent intent = new Intent(this, ActivityC.class);
intent.putExtra("USER_NAME", "張三");
intent.putExtra("USER_ID", 1001);
startActivity(intent);

// Activity C (接收方) - onCreate 中
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_c); // 先 setContentView
    
    TextView tv = findViewById(R.id.showmsg); // 再 findViewById
    String name = getIntent().getStringExtra("USER_NAME");
    int id = getIntent().getIntExtra("USER_ID", -1);
    tv.setText("歡迎 " + name + " (ID: " + id + ")");
}

方案二:SharedPreferences/DataStore 持久化配置(跨啟動保持)


// 寫入 (任意位置,如登錄成功後)
Context context = getApplicationContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putString("USER_NAME", "張三").apply();

// 讀取 (Activity C onCreate)
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String name = prefs.getString("USER_NAME", "訪客");
findViewById(R.id.showmsg).setText(name);

方案三:共享 ViewModel (Jetpack 推薦,數據與 UI 分離)


// SharedViewModel (Application 或 Activity 作用域)
class UserViewModel : ViewModel() {
    val userName = MutableLiveData()
    
    fun updateName(name: String) {
        userName.value = name
    }
}

// Activity A (更新數據)
val viewModel: UserViewModel by viewModels() // 或 activityViewModels()
viewModel.updateName("張三")
startActivity(Intent(this, ActivityC::class.java))

// Activity C (觀察數據)
val viewModel: UserViewModel by activityViewModels() // 共享同一實例
viewModel.userName.observe(this, { name ->
    findViewById(R.id.showmsg).text = name ?: "訪客"
})

方案四:Application 單例持有數據(簡單但需防洩漏)


class MyApp : Application() {
    var currentUser: User? = null
}

// 任意處存取
(MyApp)getApplication().currentUser = user
val name = ((MyApp)getApplication()).currentUser?.name

核心原則總結

原則錯誤做法正確做法
數據與視圖分離跨 Activity 直接操作 View傳遞數據模型,各 Activity 綁定自己的 View
生命週期安全持有其他 Activity/View 引用用 Intent/ViewModel/存儲傳遞不可變數據
單一職責Activity 既負責導航又負責數據存儲ViewModel 處理數據,Activity 僅負責 UI 渲染

調試技巧

  1. 在 XML 中預設 android:text="TEST" 驗證 View 可見性。
  2. 用 Log.d(TAG, "Extra: " + getIntent().getStringExtra("KEY")) 確認數據到達。
  3. 斷點檢查 findViewById 是否返回 null(通常是 setContentView 前調用、或 ID 錯誤)。

記住:Activity 之間傳遞的是「數據」,不是「控件」。這是 Android 組件化設計的基石。

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