第十八天,你已經成功完成了第一個 MVVM 專案,並體驗了 ViewModel 如何解決螢幕旋轉時資料流失的問題。
但你可能會發現,在 MainActivity 中,每次點擊按鈕後,我們還是需要手動地呼叫 setText() 來更新 TextView。
如果我們希望 View 能夠自動感知到 ViewModel 裡面的資料有變化,然後自動更新畫面,該怎麼辦呢?這時,我們就需要今天的終極武器:LiveData。
LiveData?LiveData 就是一個 「有魔法的包裹」。
View,就像是一個「觀察者」,它會一直盯著這個包裹。只要包裹裡面的資料一變,View 就會立刻更新畫面。LiveData 裡的資料改變時,它會自動通知所有觀察者。LiveData 知道 Activity 的生命週期。它只會向處於活躍狀態的 View (例如:畫面正在顯示) 發送通知,避免記憶體洩漏。今天,我們要修改昨天的計數器 App,用 LiveData 來實現畫面的自動更新。
CounterViewModel.java打開你的「智慧助理」檔案 CounterViewModel.java。我們要將原本的 int counter 改成 LiveData。
`import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; // 新增匯入 MutableLiveData
import androidx.lifecycle.ViewModel;
public class CounterViewModel extends ViewModel {
// 這是我們「智慧助理」要管理的資料,使用 MutableLiveData
private MutableLiveData<Integer> _counter = new MutableLiveData<>();
// 這是給 View 觀察的公開版本
public LiveData<Integer> counter = _counter;
// 建構子,設定初始值
public CounterViewModel() {
_counter.setValue(0);
}
// 增加數字的方法
public void incrementCounter() {
// 從包裹中取出舊值
int currentValue = _counter.getValue() != null ? _counter.getValue() : 0;
// 增加後,再把新值設定回包裹
_counter.setValue(currentValue + 1);
}
}
MutableLiveData:這是一個可以改變資料的 LiveData 版本。我們用它來修改計數器的值。LiveData:這是一個只讀的 LiveData 版本。我們將它公開給 View 觀察,這樣 View 只能看,不能直接修改資料,保證了資料的安全。_counter.setValue(...):這是改變 LiveData 裡面資料的方法。MainActivity.java (View)打開你的「被動」角色檔案 MainActivity.java。這次,我們不再需要手動更新 TextView 了。
`import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.Observer; // 新增匯入 Observer
public class MainActivity extends AppCompatActivity {
private CounterViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 取得 ViewModel 實例
viewModel = new ViewModelProvider(this).get(CounterViewModel.class);
// 2. 找到 View 元件
TextView counterTextView = findViewById(R.id.counterTextView);
Button incrementButton = findViewById(R.id.incrementButton);
// 3. 讓 View 開始「觀察」ViewModel 的資料
viewModel.counter.observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer newCounterValue) {
// 當 ViewModel 裡的數字改變時,這裡的程式碼會自動執行
// 我們只需要在這裡更新畫面即可
counterTextView.setText(String.valueOf(newCounterValue));
}
});
// 4. 設定按鈕點擊事件
incrementButton.setOnClickListener(v -> {
// 點擊後,我們只需要告訴 ViewModel 執行邏輯
// 不用手動更新 View 了!
viewModel.incrementCounter();
});
}
}
viewModel.counter.observe(...):這就是讓 View 成為「觀察者」的關鍵程式碼。它會盯著 viewModel.counter 這個「包裹」。onChanged(...):當 counter 的值發生改變時,這個方法會自動被呼叫,並把新值傳進來。我們只需要在這裡更新 TextView 即可。MainActivity 的程式碼,你會發現我們在按鈕點擊事件裡,沒有任何一行更新畫面的程式碼!這就是 LiveData 的強大之處。今天我們成功地將 LiveData 應用在 MVVM 模式中,我們學會了:
LiveData 是什麼,以及它如何讓 View 自動觀察資料變化。ViewModel 中使用 MutableLiveData 來管理可變的資料。View 中使用 observe() 方法來觀察 LiveData。你已經掌握了 MVVM 的核心精髓!從明天開始,我們將進入一個更進階的挑戰,讓你將這些概念應用在更複雜的 App 中!
明天見!