我想在LiveData-Object上更新我的Repository中的对象的成员变量。问题是,如果我调用getValue()方法,我会继续得到NullPointerException,尽管我的Room-Library中存在该值。
我现在的问题是,如何在不调用observe()方法的情况下从LiveData对象获取值? (我无法在我的存储库中调用observe方法,因为该方法要求我输入LifeCycleOwner-引用,这在我的存储库中不存在)。
有没有办法从LiveData对象中获取价值?
我的架构看起来像这样:ViewModel - > Repository - > Dao
您需要在ViewModel中初始化LiveData对象,然后在Activity / Fragment中观察它,就像这样
product view model.Java
public ProductViewModel(DataRepository repository, int productId) {
mObservableProduct = repository.loadProduct(mProductId);
}
public LiveData<ProductEntity> getObservableProduct() {
return mObservableProduct;
}
这里observableProduct是用于观察产品细节的LiveData,它在构造函数中初始化并使用getObservableProduct()方法获取
然后你可以像这样在Activity / Fragment中观察LiveData
main activity.Java
productViewModel.getObservableProduct().observe(this, new Observer<ProductEntity>() {
@Override
public void onChanged(@Nullable ProductEntity productEntity) {
mProduct = productEntity;
}
});
正如您已经设置了像LiveData的Flow这样的代码体系结构
DAO - > Repository - > ViewModel - > Fragment
您不需要在存储库中观察LiveData,因为您无法从那里更新UI。从Activity中观察它并从那里更新UI。
正如你所说它在getValue()上给出null,请确保你正在更新db并从DAO的单个实例获取db,因为我使用DAO它不会通过LiveData将一个DAO实例的db update通知给第二个DAO实例
您也可以按照@Martin Ohlin的建议观察.Forever,但它不会识别生命周期并可能导致崩溃。在永远观察之前检查您的要求
有关Full LiveData Flow的信息,请参阅此处
有关DAO issues的信息,请参阅此处
编辑1 - 不使用LifecycleOwner
您可以使用void observeForever (Observer<T> observer)
(reference)方法观察LiveData,而不提供任何LifecycleOwner
,正如我在上面的示例中使用此上下文所提供的那样。
这是您可以在不提供任何LifecycleOwner的情况下观察LiveData并观察存储库本身的LiveData的方法
private void observeForeverProducts() {
mDatabase.productDao().loadAllProducts().observeForever(new Observer<List<ProductEntity>>() {
@Override
public void onChanged(@Nullable List<ProductEntity> productEntities) {
Log.d(TAG, "onChanged: " + productEntities);
}
});
}
但是你需要明确地调用removeObserver(Observer)
来停止观察LiveData,这是在LifecycleOwner之前的情况下自动完成的。所以根据文件
您应该手动调用
removeObserver(Observer)
以停止观察此LiveData。虽然LiveData有一个这样的观察者,但它将被视为活跃的。
由于这不需要LifecycleOwner,您可以在Repository中调用它,而不使用您提到的存储库中缺少的此参数
我不确定你要在这里完成什么,但是如果你使用observeForever而不是observe,可以在没有LifeCycleOwner的情况下观察。
为了使LiveData对象运行良好,您需要使用observe方法。也就是说,如果要使用getValue()方法并期望非null响应,则需要使用observe方法。确保在ViewModel中初始化LiveData对象,@ adityakamble49在他的回答中说。要初始化对象,可以传递在Repository中创建的LiveData对象的引用:
view model.Java
private LiveData<Client> clientLiveData;
private ClientRepository clientRepo;
public ViewModel(ClientRepository clientRepo) {
this.clientRepo = clientRepo;
clientLiveData = clientRepo.getData();
}
然后你必须从Activity观察你的ViewModel并在你的ViewModel中调用你想要更新的方法(或Repo,但要记住Repo与ViewModel和ViewModel一起使用UI:https://developer.android.com/jetpack/docs/guide):
activity.Java
viewModel.getClient().observe(this, new Observer<Client>() {
@Override
public void onChanged(@Nullable Client client) {
viewModel.methodWantedInViewModel(client);
}
});
我希望它有所帮助。
Livedata用于观察数据流。如果您想要调用获取存储在实时数据中的实体列表。这样的事情会很有帮助。
public class PoliciesTabActivity extends AppCompatActivity {
private PolicyManualViewModel mViewModel;
private List<PolicyManual> policyManualList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaves_tab_manager);
mViewModel = ViewModelProviders.of(PoliciesTabActivity.this).get(PolicyManualViewModel.class);
//Show loading screen untill live data onChanged is triggered
policyManualList = new ArrayList<>();
mViewModel.getAllPolicies().observe(this, new Observer<List<PolicyManual>>() {
@Override
public void onChanged(@Nullable List<PolicyManual> sections) {
//Here you got the live data as a List of Entities
policyManualList = sections;
if (policyManualList != null && policyManualList.size() > 0) {
Toast.makeText(PoliciesTabActivity.this, "Total Policy Entity Found : " + policyManualList.size(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(PoliciesTabActivity.this, "No Policy Found.", Toast.LENGTH_SHORT).show();
}
}
});
}
}