I am following this tutorial to learn ViewModel and LiveData. In my case, instead of getting data from network, I am simply generating random string on button click and trying to update a textview. The problem is that the textview does not get updated when the data is changed by button click, but only gets updated when orientation is toggled.
Activity Class (extends LifecycleActivity)
public class PScreen extends BaseActivity {
#Override protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.places_screen);
final UserModel viewModel = ViewModelProviders.of(this).get(UserModel.class);
viewModel.init();
viewModel.getUser().observe(this, new Observer<User>() {
#Override public void onChanged(#Nullable User user) {
((TextView) findViewById(R.id.name)).setText(user.getName());
}
});
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
final MutableLiveData<User> data = new MutableLiveData<>();
User user = new User();
user.setName(String.valueOf(Math.random() * 1000));
data.postValue(user);
viewModel.setUser(data); // Why it does not call observe()
}
});
}
}
ViewModel Class
package timsina.prabin.tripoptimizer.model;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.ViewModel;
public class UserModel extends ViewModel {
private LiveData<User> user;
public void init() {
if (this.getUser() != null) {
return;
}
this.user = new LiveData<User>() {
#Override protected void setValue(User value) {
value.setName("Fresh New Name");
super.setValue(value);
}
};
}
public LiveData<User> getUser() {
return user;
}
public void setUser(LiveData<User> user) {
this.user = user;
}
}
You are creating a new LiveData instance each time! You are not supposed to do that. If you do that all previous observers will be ignored.
In this case you could replace your setUSer(LiveData<User>) method on your ViewModel to setUser(User u) (taking a User instead of a LiveData) and then do user.setValue(u) inside it.
Of course, will have to initialize the LiveData member in your ViewModel class, like this:
final private LiveData<User> user = new MutableLiveData<>();
It will work then because it will notify the existing observers.
I was somehow able to resolve this by using MutableLiveData instead of LiveData.
Model class
private MutableLiveData<User> user2;
public void init() {
if (user2 == null) {
user2 = new MutableLiveData<>();
}
}
public MutableLiveData<User> getUser2() {
return user2;
}
public void setUser2(final User user) {
user2.postValue(user);
}
Activity
viewModel.getUser2().observe(this, new Observer<User>() {
#Override public void onChanged(#Nullable User user) {
((TextView) findViewById(R.id.name)).setText(user.getName());
}
});
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
User user = new User();
viewModel.getUser().postValue(user);
}
});
You replace the reference to the object inside UserModel, try to swap the lines of code
data.postValue(user);
viewModel.setUser(data); // Why it does not call observe()
replace on
viewModel.setUser(data); // Why it does not call observe()
data.postValue(user);
Try to modify your code as #niqueco mentioned, set your updated method inside setUser() method and change your onclick() listener in the activity to send the new user data info only. Other works the LiveData will help u.
public class UserModel extends ViewModel {
private LiveData<User> user;
public void init() {
if (this.getUser() != null) {
return;
}
this.user = new LiveData<User>() {
#Override protected void setValue(User value) {
value.setName("Fresh New Name");
super.setValue(value);
}
};
}
public LiveData<User> getUser() {
return user;
}
public void setUser(LiveData<User> user) {
this.user.setValue(user); //the live data will help u push data
}
}
Activity Class
public class PScreen extends BaseActivity {
#Override protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.places_screen);
final UserModel viewModel = ViewModelProviders.of(this).get(UserModel.class);
viewModel.init();
viewModel.getUser().observe(this, new Observer<User>() {
#Override public void onChanged(#Nullable User user) {
((TextView) findViewById(R.id.name)).setText(user.getName());
}
});
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
//final MutableLiveData<User> data = new MutableLiveData<>();
User user = new User();
user.setName(String.valueOf(Math.random() * 1000));
//data.postValue(user);
viewModel.setUser(user); // Why it does not call observe()
}
});
}
}
Related
Even though I am using ViewModel, whenever the device is rotated, the data in the Recyclerview disappears. I had to put the makeSearch() method inside the onClick() method because I need to get the text that the button grabs and use it as the search parameter. Is there a better way I can handle this to avoid this problem? My code is right here:
SearchActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
// What happens when the search button is clicked
materialButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Objects.requireNonNull(textInputEditText.getText()).toString().isEmpty()) {
textInputEditText.setError("Type a search query");
} else {
mSearchInput = Objects.requireNonNull(textInputEditText.getText()).toString();
textInputEditText.setText("");
makeSearch();
}
}
});
}
// Gets the ViewModel, Observes the Question LiveData and delivers it to the Recyclerview
private void makeSearch() {
final SearchAdapter searchAdapter = new SearchAdapter();
SearchViewModel mSearchViewModel = new ViewModelProvider(this,
new CustomSearchViewModelFactory(new SearchRepository())).get(SearchViewModel.class);
mSearchViewModel.setQuery(mSearchInput);
mSearchViewModel.getQuestionLiveData().observe(this, new Observer<List<Question>>() {
#Override
public void onChanged(List<Question> questions) {
mQuestions = questions;
searchAdapter.setQuestions(questions);
}
});
mRecyclerView.setAdapter(searchAdapter);
searchAdapter.setOnClickListener(mOnClickListener);
}
SearchViewModel:
public class SearchViewModel extends ViewModel {
private SearchRepository mSearchRepository;
private MutableLiveData<String> mSearchLiveData = new MutableLiveData<>();
private LiveData<List<Question>> mQuestionLiveData = Transformations.switchMap(mSearchLiveData, (query) -> {
return mSearchRepository.getQuestions(query);
});
SearchViewModel(SearchRepository searchRepository) {
this.mSearchRepository = searchRepository;
}
public LiveData<List<Question>> getQuestionLiveData() {
return mQuestionLiveData;
}
public void setQuery(String query) {
mSearchLiveData.setValue(query);
}
}
SearchRepository:
public class SearchRepository {
//private String inTitle;
private MutableLiveData<List<Question>> mQuestions = new MutableLiveData<>();
public SearchRepository() {
//getQuestionsWithTextInTitle();
}
private void getQuestionsWithTextInTitle(String inTitle) {
ApiService apiService = RestApiClient.getApiService(ApiService.class);
Call<QuestionsResponse> call = apiService.getQuestionsWithTextInTitle(inTitle);
call.enqueue(new Callback<QuestionsResponse>() {
#Override
public void onResponse(Call<QuestionsResponse> call, Response<QuestionsResponse> response) {
QuestionsResponse questionsResponse = response.body();
if (questionsResponse != null) {
mQuestions.postValue(questionsResponse.getItems());
//shouldShowData = true;
} else {
Log.d("SearchRepository", "No matching question");
//shouldShowData = false;
}
}
#Override
public void onFailure(Call<QuestionsResponse> call, Throwable t) {
//shouldShowData = false;
t.printStackTrace();
}
});
}
public LiveData<List<Question>> getQuestions(String inTitle) {
getQuestionsWithTextInTitle(inTitle);
return mQuestions;
}
}
Your approach of passing the search input in through your CustomSearchViewModelFactory and into the constructor for the ViewModel and into the constructor for your SearchRepository isn't going to work in any case. While the first time you search your CustomSearchViewModelFactory creates the ViewModel, the second time you hit search, your SearchViewModel is already created and your factory is not invoked a second time, meaning you never get the second query.
Instead, you should file the ViewModel Overview documentation, and use Transformations.switchMap() to convert your input (the search string) into a new LiveData<List<Question>> for that given query.
This means that your ViewModel would look something like
public class SearchViewModel extends ViewModel {
private SearchRepository mSearchRepository;
private MutableLiveData<String> mSearchLiveData = new MutableLiveData<String>();
private LiveData<List<Question>> mQuestionLiveData =
Transformations.switchMap(mSearchLiveData, (query) -> {
return mSearchRepository.getQuestions(query);
});
public SearchViewModel() {
mSearchRepository = new SearchRepository();
}
public void setQuery(String query) {
mSearchLiveData.setValue(query);
}
public LiveData<List<Question>> getQuestionLiveData() {
return mQuestionLiveData;
}
}
You'd then update your Activity to:
Always observe the getQuestionLiveData() (note that you won't get a callback to your Observer until you actually set the first query)
Call setQuery() on your SearchViewModel in your makeSearch()
Remove your CustomSearchViewModelFactory entirely (it would no longer be needed).
I have a doubt.If i have a method that make asynchronous call to an api and converts the results of it to livedata object and in another place i am updating my recyclerview when data changes, then every time call to this method will update recyclerview or ,for eg:if url stays same then it won't update the recyclerview;Pls help.
Here is the code for observing data in Mainactivity onCreate method.
JsonViewModel model = new ViewModelProvider(this).get(JsonViewModel.class);
model.getData("top_rated").observe(this, data -> {
mRecyclerView.setAdapter(new MovieRecyclerViewAdapter(this,data));
});
Here is the JsonViewModel class
public class JsonViewModel extends AndroidViewModel {
private JsonLivedata data;
public JsonViewModel(#NonNull Application application) {
super(application);
data=new JsonLivedata();
}
public LiveData<List<Movie>> getData(String path) {
data.loadData(path);
return data;
}
}
Here is the JsonLivedata class
public class JsonLivedata extends LiveData<List<Movie>> {
private static final String TAG = "JsonLivedata";
public JsonLivedata() {
}
public void loadData(String path){
Log.d(TAG, "loadData: Called");
new AsyncTask<String,Void,List<Movie>>(){
#Override
protected List<Movie> doInBackground(String... path) {
List<Movie> allTopMovies= JsonResponseFetcher.makeAsyncQueryForMovies(path[0]);
return allTopMovies;
}
#Override
protected void onPostExecute(List<Movie> movies) {
setValue(movies);
}
}.execute(path);
}
}
And here is the method that call livedata loaddata method
changeBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
model.getData("popular");
}
});
Or I am doing things wrongly.Can anyone suggest
First create adapter instance & set to RecyclerView
JsonViewModel model = new ViewModelProvider(this).get(JsonViewModel.class);
MovieRecyclerViewAdapter movieRecyclerViewAdapter = new MovieRecyclerViewAdapter(this, dataList)
mRecyclerView.setAdapter(movieRecyclerViewAdapter);
Then do this on data changes
model.getData("top_rated").observe(this, data -> {
dataList.clear();
dataList.addAll(data);
movieRecyclerViewAdapter.notifyDataSetChanged();
});
I have a Login Fragment which uses API call to login. I use mvvm and databinding to bind views with viewmodel. In viewmodel Login Response via retrofit is observed in viewmodel which uses RxJava.
I need to observe the retrofit response in the loginFragment, which is not get observed when retrofit response came. Following are the fragment and viewmodel code. I need retrofit response to pass to fragment or fragment get automatically observe response.
public class LoginFragment extends Fragment {
private LoginViewModel mLoginViewModel;
private Observable<LoginResult> dataObservable;
public static String TAG = LoginFragment.class.getSimpleName();
public Disposable disposable;
public static Fragment LoginFragmentInstance() {
Log.e(TAG, "LoginFragmentInstance: " );
Fragment fragment = new LoginFragment();
return fragment;
}
public LoginFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
FragmentLoginBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false);
mLoginViewModel = new LoginViewModel(getActivity());
//setViewModel method name changes based on variable name declared in XML
//mLoginViewModel.loginResult.observeO
dataObservable= mLoginViewModel.loginResult;
disposable = dataObservable.subscribe(new Consumer<LoginResult>() {
#Override
public void accept(LoginResult result) throws Exception {
Log.d("TAG", result.toString());
}
});
binding.setViewModel(mLoginViewModel);
return binding.getRoot();
}
#Override
public void onDestroy() {
mLoginViewModel.destroy();
disposable.dispose();
super.onDestroy();
}
}
ViewModel File
public class LoginViewModel {
private static final String TAG = "LoginViewModel";
public ObservableField<String> userName = new ObservableField<>();
public ObservableField<String> password = new ObservableField<>();
public ObservableField<String> email = new ObservableField<>();
public ObservableField<String> userNameErr = new ObservableField<>();
public ObservableField<String> passwordErr = new ObservableField<>();
public ObservableField<String> emailErr = new ObservableField<>();
public Observable<LoginResult> loginResult = new Observable<LoginResult>() {
#Override
protected void subscribeActual(Observer<? super LoginResult> observer) {
}
};
public ObservableField<Boolean> enableLogin;
private CompositeDisposable myCompositeDisposable = new CompositeDisposable();
private HashMap<String, String> loginApiParams;
public Action signIn;
public Context context;
public LoginViewModel(final Context context) {
this.context = context;
Observable result = Observable.combineLatest(FieldUtils.toObservable(userName), FieldUtils.toObservable(password),
new BiFunction() {
#Override
public Object apply(Object userName, Object password) throws Exception {
int failCount = 0;
if (!InputValidator.validateMobileno(userName.toString())) {
++failCount;
userNameErr.set(context.getResources().getString(R.string.mobileno_incorrect));
} else {
userNameErr.set("");
}
if (!InputValidator.validatePassword(password.toString())) {
++failCount;
passwordErr.set(context.getResources().getString(R.string.password_incorrect));
} else {
passwordErr.set("");
}
return failCount == 0;
}
});
enableLogin = FieldUtils.toField(result);
signIn = new Action() {
#Override
public void run() throws Exception {
Log.d(TAG, "signIn button clicked");
loginCall();
}
};
}
private void loginCall() {
loginApiParams = new HashMap<>();
// loginApiParams.put(, paymentType.toString())
loginApiParams.put(ApiParameterKeyConstants.MOBILE,userName.get());
loginApiParams.put(ApiParameterKeyConstants.PASSWORD, password.get());
UserApi usersService = ApiService.INSTANCE.apiCall();
Disposable disposable = usersService.getLogin(loginApiParams)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<LoginResult>() {
#Override
public void accept(LoginResult result) throws Exception {
loginResult = Observable.just(result);
//loginResult.subscribe()
//loginResult = result ;
//Log.d(TAG, "Login Successfull");
}
}, new Consumer<Throwable>()
{
#Override
public void accept(Throwable throwable) throws Exception {
Log.d(TAG, "Login Failed");
}
});
myCompositeDisposable.add(disposable);
}
}
It seems like you are re-assigning the loginResult an Observable in your loginCall method of the ViewModel instead of passing the result to its Observers.
You should try calling loginResult.onNext(result) or loginResult.onComplete(result) instead of loginResult = Observable.just(result);
This is my first time using MVVM architecture.I am also using LiveData. I simply retrieve data from server using Retrofit.So upon clicking a button in the View(MainActivity.class) I invoke the ViewModel class's method(handleRetrofitcall()) to take up the duty of Api calling from the Model class(Retrofit Handler.class).The Model class upon retrieving the data informs the ViewModel of the data(which is actually the size of items).I set the size to LiveData and try to listen for it.Unfortunately I couldn't.For detailed analysis please go through the code.
Model...
RetrofitHandler.class:
public class RetrofitHandler {
private ApiInterface apiInterface;
private SimpleViewModel viewModel;
public void getData(){
apiInterface= ApiClient.getClient().create(ApiInterface.class);
Call<Unknownapi> call=apiInterface.doGetListResources();
call.enqueue(new Callback<Unknownapi>() {
#Override
public void onResponse(Call<Unknownapi> call, Response<Unknownapi> response) {
List<Unknownapi.Data> list;
Unknownapi unknownapi=response.body();
list=unknownapi.getData();
viewModel=new SimpleViewModel();
viewModel.postValue(list.size());
Log.e("Size",Integer.toString(list.size()));
}
#Override
public void onFailure(Call<Unknownapi> call, Throwable t) {
}
});
}
}
ViewModel....
SimpleViewModel.class:
public class SimpleViewModel extends ViewModel {
private RetrofitHandler retrofitHandler;
private int size;
private MutableLiveData<Integer> mutablesize=new MutableLiveData<>();
public SimpleViewModel() {
super();
}
#Override
protected void onCleared() {
super.onCleared();
}
public void handleRetrofitcall(){
retrofitHandler=new RetrofitHandler();
retrofitHandler.getData();
}
public void postValue(int size){
this.size=size;
mutablesize.postValue(this.size);
Log.e("lk","f");
}
public MutableLiveData<Integer> getObject() {
return mutablesize;
}
}
View.....
MainActivity.class:
public class MainActivity extends AppCompatActivity {
private TextView status;
private SimpleViewModel viewModel;
private Observer<Integer> observer;
private MutableLiveData<Integer> mutableLiveData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
status=findViewById(R.id.status);
viewModel=ViewModelProviders.of(MainActivity.this).get(SimpleViewModel.class);
observer=new Observer<Integer>() {
#Override
public void onChanged(#Nullable Integer integer) {
Log.e("lk","f");
status.setText(Integer.toString(integer));
}
};
viewModel.getObject().observe(MainActivity.this,observer);
findViewById(R.id.retrofit).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewModel.handleRetrofitcall();
}
});
}
#Override
protected void onDestroy() {
if (observer!=null){
viewModel.getObject().removeObserver(observer);
}
super.onDestroy();
}
}
You're creating a new ViewModel in the RetrofitHandler, so nothing is observing that viewmodel. Instead of having the RetrofitHandler rely on a ViewModel internally, it's probably safer to handle the Retrofit callback inself, and post data there.
public void handleRetrofitcall(){
retrofitHandler=new RetrofitHandler();
retrofitHandler.getData(new Callback<List<Unknownapi.Data>> {
// add actual callback implementation here
); // add a callback here, so that the data is available in the view model. Then post the results from here.
}
Edit: More clarification.
In the Activity, you're correctly creating a ViewModel and observing it (we'll call that ViewModel A). ViewModel A is then creating a RetrofitHandler and calling getData on that Retrofithandler. The issue is that RetrofitHandler is creating a new ViewModel in getData (which I'm going to call ViewModel B).
The issue is that the results are being posted to ViewModel B, which nothing is observing, so it seems like nothing is working.
Easy way to avoid this issue is to make sure that only an Activity/Fragment is relying on (and creating) ViewModels. Nothing else should know about the ViewModel.
Edit 2: Here's a simple implementation. I haven't tested it, but it should be more or less correct.
// shouldn't know anything about the view model or the view
public class RetrofitHandler {
private ApiInterface apiInterface;
// this should probably pass in a different type of callback that doesn't require retrofit
public void getData(Callback<Unknownapi> callback) {
// only create the apiInterface once
if (apiInterface == null) {
apiInterface = ApiClient.getClient().create(ApiInterface.class);
}
// allow the calling function to handle the result
apiInterface.doGetListResources().enqueue(callback);
}
}
// shouldn't know how retrofit handler parses the data
public class SimpleViewModel extends ViewModel {
private RetrofitHandler retrofitHandler = new RetrofitHandler();
// store data in mutableSize, not with a backing field.
private MutableLiveData<Integer> mutableSize = new MutableLiveData<>();
public void handleRetrofitCall() {
// handle the data parsing here
retrofitHandler.getData(new Callback<Unknownapi>() {
#Override
public void onResponse(Call<Unknownapi> call, Response<Unknownapi> response) {
Unknownapi unknownapi = response.body();
int listSize = unknownapi.getData().size;
// set the value of the LiveData. Observers will be notified
mutableSize.setValue(listSize); // Note that we're using setValue because retrofit callbacks come back on the main thread.
Log.e("Size", Integer.toString(listSize));
}
#Override
public void onFailure(Call<Unknownapi> call, Throwable t) {
// error handling should be added here
}
});
}
// this should probably return an immutable copy of the object
public MutableLiveData<Integer> getObject() {
return mutableSize;
}
}
public class MainActivity extends AppCompatActivity {
private TextView status;
// initialize the view model only once
private SimpleViewModel viewModel = ViewModelProviders.of(MainActivity.this).get(SimpleViewModel.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
status = findViewById(R.id.status);
// observe the view model's changes
viewModel.getObject().observe(this, new Observer<Integer>() {
#Override
public void onChanged(#Nullable Integer integer) {
// you should handle possibility of interger being null
Log.e("lk","f");
status.setText(Integer.toString(integer));
}
});
findViewById(R.id.retrofit).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// call the view model's function
viewModel.handleRetrofitCall();
}
});
}
}
i am working on a project in which i am trying to implement Android architecture components with data binding.
I have an activity, viewmodel and repository and i am crating a login page right now.
I have to make two repository functions to make the user login, the first function will return the uid and by passing this uid, the second function will return the details. once everything is done then only i want to redirect the user to inside page. I have tried with Transformations.switchMap, which is not working.
Please help...
public class LoginViewModel extends ViewModel {
private final VendorRepository vendorRepository;
private final ResourceProvider resourceProvider;
public MutableLiveData<String> error = new MutableLiveData<>();
public MutableLiveData<Boolean> loading = new MutableLiveData<>();
private MutableLiveData<Resource<String>> vendorId = new MutableLiveData<>();
public LiveData<Resource<Vendor>> vendor;
public LoginViewModel() {
this.vendorRepository = VendorRepository.getInstance();
this.resourceProvider = ResourceProvider.getInstance();
/*vendor = Transformations.switchMap(vendorId, new Function<Resource<String>, LiveData<Resource<Vendor>>>() {
#Override
public LiveData<Resource<Vendor>> apply(Resource<String> input) {
if (input!=null&&input.status.equals(Status.SUCCESS))
return vendorRepository.getVendor(vendorId.getValue().data);
else return null;
}
});*/
}
/**
* called when a user clicks on the login button
* if the inputs are valid, will call the login function
*
* #param email entered email
* #param password entered password
*/
public void onClickLogin(String email, String password) {
//loading.setValue(true);
if (validInputs(email, password)) {
vendorId = vendorRepository.login(
email, password
);
} else loading.setValue(false);
}}
This is my viewmodel
public class VendorRepository {
private static VendorRepository INSTANCE;
private FirebaseAuth firebaseAuth;
private FirebaseFirestore firebaseFirestore;
public static VendorRepository getInstance() {
if (INSTANCE == null)
INSTANCE = new VendorRepository();
return INSTANCE;
}
private VendorRepository() {
this.firebaseAuth = FirebaseAuth.getInstance();
this.firebaseFirestore = FirebaseFirestore.getInstance();
}
public MutableLiveData<Resource<String>> login(String email, String password) {
final MutableLiveData<Resource<String>> data = new MutableLiveData<>();
data.setValue(Resource.<String>loading(null));
firebaseAuth
.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
data.postValue(Resource.success(task.getResult().getUser().getUid()));
} else {
data.postValue(Resource.<String>error(task.getException().getMessage(), null));
}
}
});
return data;
}
public LiveData<Resource<Vendor>> getVendor(String id) {
final MutableLiveData<Resource<Vendor>> data = new MutableLiveData<>();
data.postValue(Resource.<Vendor>loading(null));
firebaseFirestore
.collection(DB_VENDOR)
.document(id)
.get()
.addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
Vendor vendor = task.getResult().toObject(Vendor.class);
data.postValue(Resource.success(vendor));
} else {
data.postValue(Resource.<Vendor>error(task.getException().getMessage(), null));
}
}
});
return data;
} }
This is my repo
You need to add an observer of the vendorId livedata somewhere in your activity, possibly in onCreate(Bundle) after you have initialized the viewModel.
Your code will look something like this.
public final class MyActivity extends AppCompatActivity {
...
LoginViewModel mViewModel;
#Override protected final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
mViewModel = ViewModelProviders.of(this)
.get(LoginViewModel.class);
//make vendorId public in the viewModel
mViewModel.vendorId.observe ( this, new Observer<String> (){
#Override public void onChanged(#Nullable final String vendorId) {
VendorRepository.getInstance().getVendor(vendorId);
}
});
//Similarly, add observer for the vendor live data
}
}