问题
I want to update a member variable of an object inside my Repository on a LiveData- Object. The problem is, that if I call the getValue() Method, I keep getting an NullPointerException, although the value does exist inside my Room- Library.
My question now is, how do I get the value from the LiveData Object without calling the observe() Method? (I am not able to call the observe method inside my repository, cause that method wants me to enter a LifeCycleOwner- reference, which is not present inside my repository).
Is there any way to get the value out of the LiveData- object?
My architecture looks like that: ViewModel --> Repository --> Dao
回答1:
You need to initialize LiveData object in ViewModel before observing it in Activity/Fragment like this
ProductViewModel.java
public ProductViewModel(DataRepository repository, int productId) {
mObservableProduct = repository.loadProduct(mProductId);
}
public LiveData<ProductEntity> getObservableProduct() {
return mObservableProduct;
}
Here observableProduct is LiveData for observing product details which is initialized in constructor and fetched using getObservableProduct() method
Then you can observe the LiveData in Activity/Fragment like this
MainActivity.java
productViewModel.getObservableProduct().observe(this, new Observer<ProductEntity>() {
@Override
public void onChanged(@Nullable ProductEntity productEntity) {
mProduct = productEntity;
}
});
As you already setup your code architecture like Flow of LiveData is
DAO -> Repository -> ViewModel -> Fragment
You don't need to observe LiveData in repository because you cannot update UI from there. Observe it from Activity instead and update UI from there.
As you are saying its giving null on getValue(), make sure you are updating db and fetching db from single instance of DAO as per I worked with DAO it will not notify db update of one DAO instance to 2nd DAO instance with LiveData
Also you can observeForever as suggested by @Martin Ohlin, but it will not be lifecycle aware and may lead to crashes. Check your requirement before observing forever
Refer to this for Full LiveData Flow
Refer to this for DAO issues
Edit 1 - Without using LifecycleOwner
You can use void observeForever (Observer<T> observer)
(reference) method to observe LiveData without providing any LifecycleOwner
as I provided by using this context in above example.
This is how you can observe LiveData without providing any LifecycleOwner and observe the LiveData in repository itself
private void observeForeverProducts() {
mDatabase.productDao().loadAllProducts().observeForever(new Observer<List<ProductEntity>>() {
@Override
public void onChanged(@Nullable List<ProductEntity> productEntities) {
Log.d(TAG, "onChanged: " + productEntities);
}
});
}
But you need to call removeObserver(Observer)
explicitly to stop observing the LiveData which was automatically done in previous case with LifecycleOwner. So as per documentation
You should manually call
removeObserver(Observer)
to stop observing this LiveData. While LiveData has one of such observers, it will be considered as active.
As this doesn't require LifecycleOwner you can call this in Repository without using this parameter as you mentioned which is missing in your repository
回答2:
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.
回答3:
I'm not sure exactly what you are trying to accomplish here, but it is possible to observe without a LifeCycleOwner if you use observeForever instead of observe.
回答4:
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();
}
}
});
}
}
回答5:
One more thing - for others with a similar problem - be aware that live data queries will execute only if there is a live observer (i.e. view listening for updates). It won't fill itself just by "laying" there in declarations, like this:
val myLiveData = repository.readSomeLiveData ()
So make sure that you are observing somewhere your LiveData object, either in view or through Transformations.
来源:https://stackoverflow.com/questions/48025008/livedata-object-keeps-being-null-after-getvalue-is-called