Can you access a ViewModel from a custom class (non-activity/fragment)

Viewed 467

I am creating a Listener class that a couple instances of a custom button in different Activities/Fragments are using. This class has listener methods that will update the respective ViewModel for that Activity/Fragment.

How do you define a ViewModel in a non-activity/fragment class? The documentation says to implement ViewModelStoreOwner, but I'm not really sure on how and what I should be implementing. I'm assuming if I don't implement it correctly, I'll have some sort of memory leak...

public class Listeners implements View.OnClickListener, ViewModelStoreOwner {

  @NonNull
  @org.jetbrains.annotations.NotNull
  @Override
  public ViewModelStore getViewModelStore() {
    return // what do I do here, and how do I tell it to close the scope appropriately
    // when the context is destroyed?
  }

  // Implement OnClick...
}

Am I just trying to abstract too much here? Does Android really just revolve around Activities and Fragments thus requiring me to have annoyingly long files? The above class is my attempt to reduce redundant implementations of a button listener between two activity/fragments

EDIT: Is it wrong to just pass the store owner of the activity that this listener instance will eventually reside in? For example:

// Custom class constructor
public Listeners(ViewModelStoreOwner storeOwner) {
  mModel = new ViewModelProvider(storeOwner).get(Model.class);
}
// Calling/parent activity/fragment/context
Listeners listeners = new Listeners(this);
mButton.setOnClickListener(listeners);
1 Answers

Unless someone posts an answer to this that says otherwise (and that this is a bad idea), I ended up utilizing the latter solution I updated my question with.

I passed the store owner into the custom Listener class as a parameter, then used this value to initialize my ViewModelProvider inside the custom class.

I believe this is safe, since the class is instantiated within the scope of that parent Fragment/Activity anyway.

So for instance, if you were calling this class from an activity/fragment:

// Calling from Activity
Listeners listeners = new Listeners(this);

// Calling from Fragment
Listeners listeners = new Listeners(requireActivity());

And the relevant class definition:

public Listeners(ViewModelStoreOwner storeOwner) {
  mModel = new ViewModelProvider(storeOwner).get(Model.class);
}
Related