7

我想在 LiveDataObject 上更新我的存储库中的对象的成员变量。问题是,如果我调用 getValue() 方法,我会不断收到 NullPointerException,尽管该值确实存在于我的 Room-Library 中。

我现在的问题是,如何在不调用 observe() 方法的情况下从 LiveData 对象中获取值?(我无法在我的存储库中调用观察方法,因为该方法要我输入一个 LifeCycleOwner 引用,该引用不存在于我的存储库中)。

有没有办法从 LiveData- 对象中获取值?

我的架构是这样的:ViewModel --> Repository --> Dao

4

5 回答 5

3

在像这样在 Activity/Fragment 中观察它之前,您需要在 ViewModel 中初始化 LiveData 对象

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 -> 存储库 -> ViewModel -> 片段

您无需在存储库中观察 LiveData,因为您无法从那里更新 UI。而是从 Activity 观察它并从那里更新 UI。

正如您所说,它在 getValue() 上给出 null,请确保您正在更新 db 并按照我使用 DAO 的方式从单个 DAO 实例中获取 db 它不会使用 LiveData 通知一个 DAO 实例到第二个 DAO 实例的 db 更新

您也可以按照@Martin Ohlin 的建议观察Forever,但它不会感知生命周期并可能导致崩溃。在永久观察之前检查您的要求

有关完整的 LiveData 流程,请参阅此内容

有关DAO 问题,请参阅this

编辑 1 - 不使用 LifecycleOwner

您可以使用void observeForever (Observer<T> observer)参考)方法来观察 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 中调用它,而无需使用您提到的存储库中缺少的此参数

于 2018-01-05T05:42:12.017 回答
1

In order for the LiveData object works well you need to use the observe method. That is if you want to use the getValue() method and expecting a non-null response you need to use the observe method. Make sure initialize the LiveData object in your ViewModel as @adityakamble49 said in his answer. For initialize the object, you can pass the reference of your LiveData object which was created in your Repository:

ViewModel.java

private LiveData<Client> clientLiveData;
private ClientRepository clientRepo;
public ViewModel(ClientRepository clientRepo) {
    this.clientRepo = clientRepo;
    clientLiveData = clientRepo.getData();
}

Then you have to observe your ViewModel from the Activity and call the method that you want to update in your ViewModel (or Repo, but remember that Repo conects with the ViewModel and ViewModel with the 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);
        }
    });

I hope it helps.

于 2019-04-29T21:07:15.653 回答
0

我不确定您究竟想在这里完成什么,但是如果您使用 observeForever而不是observe ,则可以在没有 LifeCycleOwner 的情况下进行观察

于 2018-01-02T13:04:14.927 回答
0

还有一件事-对于其他有类似问题的人-请注意,只有在有实时观察者时才会执行实时数据查询(即视图侦听更新)。它不会仅仅通过在声明中“放置”来填充自己,如下所示:

val myLiveData = repository.readSomeLiveData ()

因此,请确保您正在某个地方观察您的 LiveData 对象,无论是在视图中还是通过转换。

于 2019-10-11T20:40:55.863 回答
0

Livedata is used to observe the data streams. In case you want to call the get a list of your entities stored within the Live Data. Something like this can be helpful.

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();
                }
            }
        });

    }
}
于 2019-06-26T13:21:26.673 回答