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

Android 跨 Activity 共享 TextView 數據:SharedPreferences 實現非啟動 Activity 也能讀寫

     編輯:程式設計綜合問答

需求:Activity A 寫入文本,Activity C 未啟動時也能讀取該文本。核心誤區:嘗試跨 Activity 直接操作 TextView (視圖引用),正確模式是數據持久化 + 各自綁定。

錯誤嘗試


// ❌ Activity A 嘗試操作 Activity C 的 View
TextView tv = findViewById(R.id.showmsg); // 這是 Activity A 自己的 View!
tv.setText("data");

方案:SharedPreferences 統一存取

Activity A (寫入方) - 實時保存


public class ActivityA extends AppCompatActivity {
    private EditText inputEdit;
    private static final String PREFS_NAME = "shared_text_prefs";
    private static final String KEY_TEXT = "shared_text_key";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        inputEdit = findViewById(R.id.inputEdit);
        
        // 方案 1: 文本變化即時保存 (適用於輸入框)
        inputEdit.addTextChangedListener(new TextWatcher() {
            @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
                saveText(s.toString());
            }
            @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override public void afterTextChanged(Editable s) {}
        });
        
        // 方案 2: 按鈕點擊保存 (適用於表單提交)
        findViewById(R.id.btnSave).setOnClickListener(v -> 
            saveText(inputEdit.getText().toString())
        );
    }

    private void saveText(String text) {
        getSharedPreferences(PREFS_NAME, MODE_PRIVATE)
            .edit()
            .putString(KEY_TEXT, text)
            .apply(); // 異步寫入,不阻塞主線程
    }
}

Activity C (讀取方) - 啟動時加載


public class ActivityC extends AppCompatActivity {
    private TextView displayText;
    private static final String PREFS_NAME = "shared_text_prefs";
    private static final String KEY_TEXT = "shared_text_key";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_c);
        displayText = findViewById(R.id.showmsg);
        
        // 讀取保存的文本,默認值 "默認文本"
        String savedText = getSharedPreferences(PREFS_NAME, MODE_PRIVATE)
            .getString(KEY_TEXT, "默認文本");
        displayText.setText(savedText);
    }
}

進階:DataStore 替代 SharedPreferences (現代首選)


// 依賴
implementation "androidx.datastore:datastore-preferences:1.0.0"

// 定義鍵
val SHARED_TEXT_KEY = stringPreferencesKey("shared_text_key")
val Context.dataStore: DataStore by preferencesDataStore("shared_text_prefs")

// Activity A 寫入 (協程)
lifecycleScope.launch {
    dataStore.edit { it[SHARED_TEXT_KEY] = inputEdit.text.toString() }
}

// Activity C 讀取 (Flow 自動觀察)
val savedTextFlow = dataStore.data.map { it[SHARED_TEXT_KEY] ?: "默認文本" }
savedTextFlow.distinctUntilChanged().collectIn(lifecycleScope) { text ->
    displayText.text = text
}

方案對比

方案適用場景優點缺點
SharedPreferences簡單鍵值、小數據、舊專案API 簡單、同步讀取快主線程磁盤 I/O 風險、無類型安全、無變更通知
DataStore (Preferences)新專案首選、Flow 響應式異步、協程、Flow、類型安全、事務性需學習協程/Flow、稍多樣板代碼
DataStore (Proto)複雜結構化數據Schema 定義、序列化高效需編寫 .proto 文件
ViewModel + Repository業務邏輯複雜、多源數據架構清晰、可測試、單一職責過度設計簡單場景

核心原則

  1. 數據與視圖分離:Activity 只負責「讀數據→綁定視圖」「寫視圖→存數據」。
  2. 單一事實來源:SharedPreferences/DataStore 是跨組件共享數據的權威來源。
  3. 生命週期無關:數據持久化存儲不依賴 Activity 是否啟動/銷毀。
  4. 默認值兜底:讀取時必須提供合理默認值,避免 null 導致崩潰。

這是 Android 「數據驅動 UI」思想的最基礎實踐:UI 只是數據的投影,數據才是核心。

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