Android Jetpack ViewModel+LiveData 的 Java 使用指南‌

Android Jetpack ViewModel+LiveData 的 Java 使用指南‌


一、环境配置‌
添加依赖

build.gradle 中引入 ViewModel 和 LiveData 库:

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.6.1"
    implementation "androidx.lifecycle:lifecycle-livedata:2.6.1"
}

(Java 项目无需 KTX 扩展,直接使用原生库)


二、创建 ViewModel 与 LiveData‌
1. 定义 ViewModel‌
  • 继承 ViewModel 类,内部通过 MutableLiveData 封装数据,对外暴露只读的 LiveData
public class UserViewModel extends ViewModel {
    private MutableLiveData<String> userName = new MutableLiveData<>();

    public LiveData<String> getUserName() {
        return userName;
    }

    public void updateUserName(String name) {
        userName.setValue(name); // 主线程更新
    }

    public void fetchUserAsync() {
        new Thread(() -> {
            String name = loadFromNetwork(); // 模拟网络请求
            userName.postValue(name); // 子线程更新
        }).start();
    }
}

说明:MutableLiveData 用于内部修改,外部通过 LiveData 观察数据变化

2. ‌ViewModel 初始化‌‌
  • 在 Activity/Fragment 中通过 ViewModelProvider 获取实例:
public class MainActivity extends AppCompatActivity {
    private UserViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(this).get(UserViewModel.class);
    }
}

注意:ViewModel 实例与 Activity/Fragment 生命周期绑定,配置变化时数据保留


三、观察 LiveData 更新‌
1. 绑定观察者‌
  • 使用 observe() 方法监听数据变化,仅在活跃生命周期状态(如 STARTEDRESUMED)触发回调:
viewModel.getUserName().observe(this, new Observer<String>() {
    @Override
    public void onChanged(String name) {
        updateTextView(name); // 更新 UI
    }
});

说明:无需手动解除观察,LiveData 自动感知生命周期,避免内存泄漏

2. 处理粘性事件‌
  • 若需避免旧数据重复触发,可通过 Event 包装类标记事件消费状态:
public class Event<T> {
    private T content;
    private boolean hasBeenHandled = false;

    public Event(T content) { this.content = content; }

    public T getContentIfNotHandled() {
        if (hasBeenHandled) return null;
        hasBeenHandled = true;
        return content;
    }
}

应用场景:弹窗、导航等一次性事件

四、LiveData 的主要子类

LiveData 是一个抽象类,其子类主要用于扩展数据管理能力。常见的子类及工具类包括:

1. MutableLiveData‌
  • 定义‌:LiveData 的‌可变子类‌,允许通过 setValue()(主线程)或 postValue()(后台线程)修改数据。
  • 用途‌:用于 ViewModel 中存储可变数据,对外暴露不可变的 LiveData 以保护数据安全。
class MyViewModel extends ViewModel {
    private MutableLiveData<Integer> counter = new MutableLiveData<>();
    public LiveData<Integer> getCounter() { return counter; }
    public void increment() { counter.setValue(counter.getValue() + 1); }
}
2. MediatorLiveData‌

MediatorLiveData 通过 addSource() 实现多数据源监听与合并,结合 Java 语法可灵活应对复杂业务场景。

  • 核心概念‌‌‌
    MediatorLiveData 是 LiveData 的子类,允许合并多个 LiveData 源,并在任意源数据变化时触发统一回调。适用于需要‌多数据源联动更新‌的场景,例如:

    • 同时监听网络请求状态和本地数据库数据
    • 组合多个 UI 状态(如加载状态 + 数据结果)
  • 基础使用步骤‌‌‌

    • 创建 MediatorLiveData 对象‌
      在 ViewModel 中初始化 MediatorLiveData,并定义合并逻辑:
    public class MyViewModel extends ViewModel {  
        private MutableLiveData<Integer> sourceA = new MutableLiveData<>();  
        private MutableLiveData<String> sourceB = new MutableLiveData<>();  
        private MediatorLiveData<String> mediatorData = new MediatorLiveData<>();  
    
        public MediatorLiveData<String> getMediatorData() {  
            return mediatorData;  
        }  
    
        // 初始化时添加数据源  
        public MyViewModel() {  
            // 监听 sourceA  
            mediatorData.addSource(sourceA, value -> {  
                String combined = "A:" + value + ", B:" + sourceB.getValue();  
                mediatorData.setValue(combined);  
            });  
    
            // 监听 sourceB  
            mediatorData.addSource(sourceB, value -> {  
                String combined = "A:" + sourceA.getValue() + ", B:" + value;  
                mediatorData.setValue(combined);  
            });  
        }  
    
        // 更新源数据  
        public void updateSourceA(int value) {  
            sourceA.setValue(value);  
        }  
    
        public void updateSourceB(String value) {  
            sourceB.setValue(value);  
        }  
    }  
    

    说明:通过 addSource() 添加监听源,任一源变化时触发合并逻辑

    • 在 UI 层观察数据‌
      Activity/Fragment 中观察 MediatorLiveData 的变化:
    viewModel.getMediatorData().observe(this, new Observer<String>() {  
        @Override  
        public void onChanged(String combinedData) {  
            updateUI(combinedData); // 统一处理合并后的数据  
        }  
    });  
    

    特点:自动管理生命周期,无需手动移除观察者

  • 高级场景示例‌

    • ‌动态切换数据源‌
      根据条件动态添加或移除 LiveData 源:
    // 添加新数据源  
    LiveData<Integer> dynamicSource = new MutableLiveData<>();  
    mediatorData.addSource(dynamicSource, value -> {  
        mediatorData.setValue("Dynamic:" + value);  
    });  
    
    // 移除数据源  
    mediatorData.removeSource(dynamicSource);  
    

    应用场景:分页加载时切换数据源

    • 多条件同步更新‌
      当多个数据源需同时满足条件时触发逻辑:
    mediatorData.addSource(sourceA, value -> {  
    if (value != null && sourceB.getValue() != null) {  
        mediatorData.setValue(processData(value, sourceB.getValue()));  
    }  
    });  
    
    mediatorData.addSource(sourceB, value -> {  
        if (value != null && sourceA.getValue() != null) {  
            mediatorData.setValue(processData(sourceA.getValue(), value));  
        }  
    });  
    

    说明:避免因异步更新导致逻辑不一致

  • 注意事项‌

    • 线程安全‌
      主线程更新数据使用 setValue(),子线程使用 postValue()
    • 避免内存泄漏‌
      动态添加的源需在不需要时通过 removeSource() 移除。
    • ‌粘性事件处理‌
      MediatorLiveData 继承自 LiveData,同样具有粘性特性,需通过 Event 包装处理一次性事件
3. Transformations 核心方法‌
  • map转换
    将原始 LiveData 的值转换为另一种类型,适用于‌一对一数据映射‌
    MutableLiveData<Integer> sourceLiveData = new MutableLiveData<>();  
    LiveData<String> mappedLiveData = Transformations.map(sourceLiveData, new Function<Integer, String>() {  
        @Override  
        public String apply(Integer input) {  
            return "Value: " + input;  
        }  
    });  
    
    说明:原始数据变更时自动触发转换逻辑
  • switchMap转换
    根据原始 LiveData 的值动态切换数据源,适用于‌链式依赖数据加载‌(如根据 ID 查询详情)。
    MutableLiveData<String> queryLiveData = new MutableLiveData<>();  
    LiveData<List<String>> resultLiveData = Transformations.switchMap(queryLiveData, new Function<String, LiveData<List<String>>>() {  
        @Override  
        public LiveData<List<String>> apply(String query) {  
            return repository.search(query); // 返回新的 LiveData  
        }  
    });  
    
    特点:自动取消前一次未完成的异步操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值