Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get a ViewModel without ViewModelProviders class?

Relating to the past question How to get a ViewModel?, and examples I've found, it does not solve my case. I don't have permission to comment there, so I have to ask again. I don't have the ViewModelProviders class which I would like to use the "of" method as in all the examples and documentation I've found, like

model = ViewModelProviders.of(this).get(Something.class);

In Android Studio, I do not find "android.arch.lifecycle:extensions" to add as a dependency. It says "nothing to show" when I search. I am at API 27. So, trying to use the non-deprecated elements, I have this in the Fragment:

public class EventDetailsFragment extends Fragment
{
EventViewModel viewModel;

@Override
public void onActivityCreated (Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);
    ViewModelProvider.Factory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication());
    // HERE IS THE ISSUE: Seems not good practice to have to create a new ViewModelProvider every time this Fragment is created. 
    // Perhaps I should just create a singleton ViewModelProvider in the Activity or Application, 
    // so here could call getActivity().getViewModelProvider(this, factory).
    ViewModelProvider viewModelProvider = new ViewModelProvider(this, factory);
    viewModel = viewModelProvider.get(EventViewModel.class);
...
}

What should I do?

like image 370
ozzylee Avatar asked Aug 15 '18 22:08

ozzylee


People also ask

What alternative do you have if you do not have the ViewModel class?

The alternative to a ViewModel is a plain class that holds the data you display in your UI.

How do you instantiate a ViewModel in Java?

To instantiate such basic viewmodel, create a ViewModelProvider with current activity/fragment reference and invoke get method with ViewModel's class.


2 Answers

Open app/build.gradle, find the dependencies block and add the lifecycle dependency manually to the list:

dependencies {
    implementation 'android.arch.lifecycle:extensions:1.1.1'

    // ... 
}

Sync the project and you should be able to get an instance of ViewModel afterwards.

like image 88
Andy Res Avatar answered Oct 18 '22 20:10

Andy Res


Try to learn some MVVM architecture if u have better knowledge of Android and Java. Put this code into some baseFragment method and then make:

abstract class BaseFragment extends Fragment() {
    //kotlin
    fun <T : ViewModel?> getViewModel(activity: FragmentActivity, modelClass: Class<T>): T {
        return ViewModelProviders.of(this, ViewModelFactory(activity)).get(modelClass)
    }

    //bytecode to java is this :/
    public final ViewModel obtainViewModel(@NotNull FragmentActivity activity, @NotNull Class modelClass) {
          return ViewModelProviders.of((Fragment)this, (Factory)(new 
          ViewModelFactory((Activity)activity))).get(modelClass);
       }
}

also dont put this code into onViewCreated rather than to onActivityCreated

// kotlin
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    viewModel = obtainViewModel(requireActivity(), KebabFragmentViewModel::class.java)
}

// java bytecode
public void onViewCreated(@NotNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    this.viewModel = (RollerFragmentViewModel)this.obtainViewModel(getFragmentActivity(), RollerFragmentViewModel.class); 
}

and now u need observer for something from viewModel place in onViewCreated mby for some maybe network operation or something what can take longer period of time

// kotlin
viewModel.list.observe(this, Observer { list ->
    list?.let {
        viewModel.myKebabAdapter.updateList(list)
    }
})

//java
this.viewModel.getErrorMessage().observe((LifecycleOwner)this, (Observer)(new Observer() {
    ...
    public final void onChanged(@Nullable List list) {
        this.viewModel.myKebabAdapter.updateKebabList(list)
    }
}

and in viewModel u got our lovely variables for observing on activity/fragment

// kotlin
var list: MutableLiveData<MutableList<User>> = MutableLiveData()

// java variable and getter
@NotNull
private MutableLiveData userList;

@NotNull
public final MutableLiveData getUserList() {
   return this.userList;
}

Now u need dependency app/build.gradle in dependencies{} block

//lifecycle
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation "android.arch.lifecycle:viewmodel:1.1.1"

// RxJava
implementation "io.reactivex.rxjava2:rxkotlin:2.2.0"
implementation "io.reactivex.rxjava2:rxandroid:2.0.0"
implementation "io.reactivex.rxjava2:rxjava:2.1.10"

Find some blog tutorials how to properly do it. I personally dont like https://developer.android.com/ it used to be hard to follow. Try Medium.

GL. And Java code is mostly decompiled so hope it works.

like image 24
Kebab Krabby Avatar answered Oct 18 '22 19:10

Kebab Krabby