Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ViewModel in a fragment?

I'm using the MVVM architecture. I have an activity and a few fragments, I would like to make a request in the API in the activity, and then using ViewModel, thanks to the obtained data, to display them in the fragment. How should I do this? My current solution that doesn't work:

Activity:

viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();

Fragment:

viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.getRoutes().observe(getActivity(), new Observer<List<RoutesResponse>>() {
    @Override
    public void onChanged(List<RoutesResponse> routes) {

                //Show data
    }
});

Repository:

public class RemoteRepository {

private ApiRequest apiRequest;
private MutableLiveData<List<RoutesResponse>> routes = new MutableLiveData<>();

public RemoteRepository() {
    apiRequest = RetrofitRequest.getInstance().create(ApiRequest.class);
}

public MutableLiveData<List<RoutesResponse>> getRoutes() {

    apiRequest.getRoutes()
            .enqueue(new Callback<List<RoutesResponse>>() {
                @Override
                public void onResponse(Call<List<RoutesResponse>> call, Response<List<RoutesResponse>> response) {

                    if (response.isSuccessful())
                        routes.setValue(response.body());
                }

                @Override
                public void onFailure(Call<List<RoutesResponse>> call, Throwable t) {
                    Log.i("Failure", "Fail!");
                }
            });

        return routes;
    }
}

ViewModel:

public class ViewModelRoutesFragment extends AndroidViewModel {

private RemoteRepository remoteRepository;
private LiveData<List<RoutesResponse>> routes;

public ViewModelRoutesFragment(@NonNull Application application) {
    super(application);
}

public void init() {
    remoteRepository = new RemoteRepository();
    routes = remoteRepository.getRoutes();
}

public LiveData<List<RoutesResponse>> getRoutes() {
        return routes;
    }
}

Currently getting a null error. How can I avoid it properly?

java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)' on a null object reference
like image 265
mikoxy Avatar asked Aug 23 '20 14:08

mikoxy


People also ask

How do I view ViewModel in fragment?

Use activity's scope to create an instance of the ViewModel in fragment so that all the fragments and activity now has a common ViewModel and have access to the same ViewModelStore . If the activity is re-created, it and all its fragments receive the same ViewModel instance that was created by the associated activity.

Can a fragment have a ViewModel?

In android, we can use ViewModel to share data between various fragments or activities by sharing the same ViewModel among all the fragments and they can access everything defined in the ViewModel. This is one way to have communication between fragments or activities.

Where do I put ViewModel in fragment?

You should have an instance of fragments inside the activity. Your fragment already holding a reference to the ViewModel. Delete these line from the activity -> : viewModelRoutesFragment = new ViewModelProvider(this).


Video Answer


1 Answers

Basically, we are trying to share the viewmodel across the activity and fragment. so while during the activity creation we have to create the instance of viewmodel

viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();

In fragment also we need to reuse the ViewModelRoutesFragment so in onViewCreated() get the instance of the ViewModel and observe the live data

viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.getRoutes().observe(getActivity(), new Observer<List<RoutesResponse>>() {
    @Override
    public void onChanged(List<RoutesResponse> routes) {
       // updation of UI
    }
});
like image 96
Guhanmuthu Selvaraj Avatar answered Oct 21 '22 08:10

Guhanmuthu Selvaraj