调用getValue()后,LiveData对象保持为null

时间:2017-12-29 15:47:27

标签: android-room android-livedata android-mvvm

我想在LiveData-Object上更新我的Repository中对象的成员变量。问题是,如果我调用getValue()方法,我会继续得到NullPointerException,尽管我的Room-Library中存在该值。

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

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

我的架构看起来像这样: ViewModel - >存储库 - >道

5 个答案:

答案 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,但它不会识别生命周期并可能导致崩溃。在永远观察之前检查您的要求

请参阅此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中调用它,而不使用 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对象的某个位置。