fabi
fabi

Reputation: 474

How to get a ViewModel?

I just want to get a reference in my Fragment (extends Fragment) to my ViewModel.class (extends from AndroidViewModel). This is how it is described everywhere:

UserModel userModel = ViewModelProviders.of(getActivity()).get(UserModel.class);

description on Android Developer

..., but ViewModelProviders is deprecated since long ago.

*This class was deprecated in API level 1.1.0. *

I can't import the class with: android.arch.lifecycle.[ViewModelProviders]

it just offers ViewModelProvider and other stuff.


How am I able to get an instance of my UserModel.class?

Upvotes: 3

Views: 9211

Answers (6)

Vanheden
Vanheden

Reputation: 680

After digging around I solved my similiar problem by adding the following method to my Activities:

protected final <T extends ViewModel> T obtainViewModel(@NonNull AppCompatActivity activity, @NonNull Class<T> modelClass) {
    ViewModelProvider.AndroidViewModelFactory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(activity.getApplication());
    return new ViewModelProvider(activity, factory).get(modelClass);
}

And then I did this in my Fragments:

protected final <T extends ViewModel> T obtainFragmentViewModel(@NonNull FragmentActivity fragment, @NonNull Class<T> modelClass) {
    ViewModelProvider.AndroidViewModelFactory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(fragment.getApplication());
    return new ViewModelProvider(fragment, factory).get(modelClass);
}

I already had some abstract super classes for menu purposes so I hid the methods away there so I don't have to repeat it in every activity. That's why they are protected. I believe they could be private if you put them in every activity or fragment that you need them in.

To be as clear as possible I would then call the methods to assign my view model in onCreate() in my activity and it would look something like this

private MyViewModel myViewModel;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    myViewModel = obtainViewModel(this, MyViewModel.class);
}

or in fragment

private MyViewModel myViewModel;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getActivity() != null) {
        myViewModel = obtainFragmentViewModel(getActivity(), MyViewModel.class);
    }
}

Upvotes: 0

SMBiggs
SMBiggs

Reputation: 11726

Kotlin version of BeirDav's answer is

val vm = ViewModelProvider(requireActivity()).get(MyViewModel::class.java)

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1007584

but ViewModelProviders is deprecated since long ago

ViewModelProviders is not deprecated. So, use ViewModelProviders:

ViewModelProviders.of(yourFragment).get(UserModel.class)

There are pieces of ViewModelProviders that are deprecated, such as its constructor, but the class overall is not.

UPDATE: 2020-05-28 Now ViewModelProviders is deprecated. In Kotlin, use by viewModels() and related property delegates. In Java, use new ViewModelProvider(...).get(UserModel.class) (for various values of ... depending on the scope of those viewmodels).

Upvotes: 2

BierDav
BierDav

Reputation: 1424

The class ViewModelProviders is deprecated! Use ViewModelProvider understood.

MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);

Happy coding :)

Upvotes: 0

kjellhaaland
kjellhaaland

Reputation: 166

Using Kotlin with the latest Android architecture components you should use the by viewModels() Kotlin property delegate like so:

class YourFragment : Fragment() {
   private val viewModel by viewModels<YourViewModel>()
}

More info here

Upvotes: 3

Sundus
Sundus

Reputation: 468

Here's how to write a ViewModel

public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
    if (users == null) {
        users = new MutableLiveData<List<User>>();
        loadUsers();
    }
    return users;
}

private void loadUsers() {
    // Do an asynchronous operation to fetch users.
}
}

And then to use it in your actctivity do something like this

public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
    // Create a ViewModel the first time the system calls an activity's onCreate() method.
    // Re-created activities receive the same MyViewModel instance created by the first activity.

    MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
    model.getUsers().observe(this, users -> {
        // update UI
    });
}
}

Upvotes: 1

Related Questions