我想在LiveData-Object上更新我的Repository中对象的成员变量。问题是,如果我调用getValue()方法,我会继续得到NullPointerException,尽管我的Room-Library中存在该值。
我现在的问题是,如何在不调用observe()方法的情况下从LiveData对象中获取值? (我无法在我的存储库中调用observe方法,因为该方法要求我输入LifeCycleOwner-引用,这在我的存储库中不存在。)
有没有办法从LiveData对象中获取值?
我的架构看起来像这样: ViewModel - >存储库 - >道
答案 0 :(得分:2)
你需要在ViewModel中初始化LiveData对象,然后在Activity / Fragment中观察它,就像这样
<强> ProductViewModel.java 强>
public ProductViewModel(DataRepository repository, int productId) {
mObservableProduct = repository.loadProduct(mProductId);
}
public LiveData<ProductEntity> getObservableProduct() {
return mObservableProduct;
}
此处observableProduct是用于观察产品详细信息的LiveData,它在构造函数中初始化并使用getObservableProduct()方法获取
然后你可以像这样观察Activity / Fragment中的LiveData
<强> MainActivity.java 强>
productViewModel.getObservableProduct().observe(this, new Observer<ProductEntity>() {
@Override
public void onChanged(@Nullable ProductEntity productEntity) {
mProduct = productEntity;
}
});
正如您已经设置的代码架构一样 LiveData的流程是
DAO - &gt;存储库 - &gt; ViewModel - &gt;片段强>
您无需在存储库中观察LiveData,因为您无法从那里更新UI。从Activity中观察它并从那里更新UI。
正如你所说它在getValue()上给出null,请确保你正在更新db并从DAO的单个实例获取db,因为我使用DAO它不会将一个DAO实例的db update通知给第二个DAO实例LiveData
你也可以按照@Martin Ohlin的建议观察.Forever,但它不会识别生命周期并可能导致崩溃。在永远观察之前检查您的要求
请参阅此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中调用它,而不使用 this 参数,如您提到的存储库中缺少的
答案 1 :(得分:0)
我不确定你要在这里完成什么,但是如果你使用的话,可以在没有LifeCycleOwner的情况下观察 observeForever代替observe。
答案 2 :(得分:0)
为了使LiveData对象正常工作,您需要使用watch方法。也就是说,如果您要使用getValue()方法并期望得到非null的响应,则需要使用observe方法。确保按照@ adityakamble49在他的回答中所述初始化ViewModel中的LiveData对象。为了初始化对象,可以传递在存储库中创建的LiveData对象的引用:
ViewModel.java
private LiveData<Client> clientLiveData;
private ClientRepository clientRepo;
public ViewModel(ClientRepository clientRepo) {
this.clientRepo = clientRepo;
clientLiveData = clientRepo.getData();
}
然后,您必须在Activity中观察ViewModel,并在ViewModel中调用要更新的方法(或Repo,但要记住Repo与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);
}
});
希望对您有帮助。
答案 3 :(得分:0)
Livedata用于观察数据流。如果您要调用get,则获取存储在实时数据中的实体的列表。这样的事情可能会有所帮助。
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();
}
}
});
}
}
答案 4 :(得分:0)
还有另一件事-对于其他有类似问题的人-请注意,只有在有实时观察者(即查看监听更新)的情况下,实时数据查询才会执行。它不会仅仅通过“放置”在声明中来填充自身,就像这样:
val myLiveData = repository.readSomeLiveData ()
因此,请确保在视图中或通过“转换”观察LiveData对象的某个位置。