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

问题描述 投票:5回答:4

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

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

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

我的架构看起来像这样:ViewModel - > Repository - > Dao

android-room android-livedata android-mvvm
4个回答
2
投票

您需要在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中调用它,而不使用您提到的存储库中缺少的此参数


0
投票

我不确定你要在这里完成什么,但是如果你使用observeForever而不是observe,可以在没有LifeCycleOwner的情况下观察。


0
投票

为了使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);
        }
    });

我希望它有所帮助。


0
投票

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

    }
}
© www.soinside.com 2019 - 2024. All rights reserved.