web-dev-qa-db-ja.com

getValue()が呼び出された後、LiveDataオブジェクトがnullのままになる

LiveDataオブジェクトのリポジトリ内のオブジェクトのメンバー変数を更新したい。問題は、getValue()メソッドを呼び出すと、Room- Library内に値が存在するにもかかわらず、NullPointerExceptionが発生し続けることです。

私の質問は、observe()メソッドを呼び出さずにLiveDataオブジェクトから値を取得するにはどうすればよいですか? (リポジトリ内でobserveメソッドを呼び出すことができません。そのメソッドが、リポジトリ内に存在しないLifeCycleOwner-参照の入力を要求するためです)。

LiveDataオブジェクトから値を取得する方法はありますか?

私のアーキテクチャは次のようになります:ViewModel->リポジトリ-> Dao

6
romaneso

このようにアクティビティ/フラグメントで監視する前に、ViewModelでLiveDataオブジェクトを初期化する必要があります

ProductViewModel.Java

_public ProductViewModel(DataRepository repository, int productId) {
    mObservableProduct = repository.loadProduct(mProductId);
}
public LiveData<ProductEntity> getObservableProduct() {
    return mObservableProduct;
}
_

ここで、observableProductは、コンストラクタで初期化され、getObservableProduct()メソッドを使用してフェッチされる製品の詳細を監視するためのLiveDataです。

次に、このようにアクティビティ/フラグメントでLiveDataを観察できます

MainActivity.Java

_ productViewModel.getObservableProduct().observe(this, new Observer<ProductEntity>() {
    @Override
    public void onChanged(@Nullable ProductEntity productEntity) {
        mProduct = productEntity;
    }
});
_

Flow of LiveDataのようなコードアーキテクチャをすでにセットアップしているので、

DAO->リポジトリ-> ViewModel->フラグメント

リポジトリからUIを更新できないため、リポジトリ内のLiveDataを監視する必要はありません。代わりにアクティビティからそれを観察し、そこからUIを更新します。

GetValue()でnullを与えると言っているように、dbを更新して、DAOの単一インスタンスからdbをフェッチしていることを確認します。

また、@ Martin Ohlinの提案に従ってForeverを観察できますが、ライフサイクルに対応していないため、クラッシュにつながる可能性があります。永久に観察する前に要件を確認してください

フルLiveDataフローについては、これを参照してください

DAOの問題については、これを参照してください

編集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)を明示的に呼び出して、以前のケースのLifecycleOwnerで自動的に行われたLiveDataの監視を停止する必要があります。ドキュメントに従って

このLiveDataの監視を停止するには、removeObserver(Observer)を手動で呼び出す必要があります。 LiveDataにはそのようなオブザーバーの1つがありますが、アクティブと見なされます。

これはLifecycleOwnerを必要としないので、リポジトリで欠落しているようにthisパラメータを使用せずにこれをリポジトリで呼び出すことができます。

2
adityakamble49

LiveDataオブジェクトが適切に機能するためには、observeメソッドを使用する必要があります。つまり、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();
}

次に、アクティビティからViewModelを観察し、ViewModel(またはRepo)で更新するメソッドを呼び出す必要がありますが、RepoはUIを使用してViewModelおよびViewModelと接続していることを覚えておいてください 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);
        }
    });

お役に立てば幸いです。

1
Josue B.

ここで何を達成しようとしているのか正確にはわかりませんが、 observe の代わりに observeForever を使用すると、LifeCycleOwnerがなくても監視できます。

0
Martin Ohlin

もう1つ-同様の問題を抱えている他の人のために-ライブデータクエリは、ライブオブザーバー(つまり、更新をリッスンするビュー)が存在する場合にのみ実行されることに注意してください。次のように、宣言に「置く」だけではそれ自体は埋められません。

val myLiveData = repository.readSomeLiveData ()

そのため、ビュー内または変換を介して、LiveDataオブジェクトのどこかを監視していることを確認してください。

0
daneejela

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

    }
}
0
Vishal Kumar