I am using ViewModel
in android to obtain an object and then pass it to a fragment to update UI components. I am trying to obtain the value of the object asynchronously and then pass the object to the fragment from the callback function. I already have a non-null value of the object in the callback and in the asynchronous task. I just am having trouble sending the object to the fragment by calling the function in the fragment java code. Here's the code snippet
Code snippet of the ViewModel
EventViewModel.java
class EventViewModel extends AndroidViewModel {
private OnEventListener mListener;
Obj obj;
//setting the listener
public void registerOnEventListener(OnEventListener mListener){
this.mListener = mListener;
}
public void getObj(){
new Thread(new Runnable() {
@Override
public void run() {
//code to obtain non-null value of object
//& obtains non-null value here
obj = some-non-null-value
if(mListener != null){
//invoke the callback
mListener.onEvent();
}
}
});
}
interface OnEventListener(){
Obj onEvent();
}
class A implements OnEventListener {
@Override
public Obj onEvent() {
System.out.println(obj.property1); //obj is non-null here
//....
return obj;
}
}
}
Code snippet of the fragment
to which I want to send the object
EventFragment.java
public class EventFragment extends Fragment {
private EventViewModel vm;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
vm = ViewModelProviders.of(this).get(EventViewModel.class);
EventViewModel.OnEventListener mListener = vm. new A();
vm.registerOnEventListener(mListener);
vm.getObj();
Obj o = mListener.getEvent() //shows error as 'Incompatible Types'
//so o is also null
}
}
Now I know that I cannot return obj
directly in the getObj()
method, it gets returned before obj
is given a non-null value, i.e. before the asynchronous task is over. On trying the above method, object o in the EventFragment
remains null always. So, please tell a way to send the object to the fragment EventFragment.java
. Please point if I need to post any more code. Thanks in advance.
Use LiveData
:
class EventViewModel extends AndroidViewModel {
private MutableLiveData<Obj> liveObjects = new MutableLiveData<>();
LiveData<Obj> getObjects() {
return liveObjects;
}
public void loadObject(){
new Thread(new Runnable() {
@Override
public void run() {
Obj object = // TODO get the value
liveObjects.postValue(object);
}
}).start();
}
}
public class EventFragment extends Fragment {
private EventViewModel vm;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
vm = ViewModelProviders.of(this).get(EventViewModel.class);
vm.getObjects().observe(this, new Observer<Obj>() {
@Override
public void onChanged(@Nullable final Obj newValue) {
// TODO something useful
}
});
}
Then, when appropriate, call loadObject()
on the EventViewModel
to trigger the background work and delivery of the new object.