I am trying to implement MVVM pattern in my android app. I have read that ViewModels should contain no android specific code (to make testing easier), however I need to use context for various things (getting resources from xml, initializing preferences, etc). What is the best way to do this? I saw that AndroidViewModel has a reference to the application context, however that contains android specific code so I'm not sure if that should be in the ViewModel. Also those tie into the Activity lifecycle events, but I am using dagger to manage the scope of components so I'm not sure how that would affect it. I am new to the MVVM pattern and Dagger so any help is appreciated!
You can use an Application context which is provided by the AndroidViewModel, you should extend AndroidViewModel which is simply a ViewModel that includes an Application reference.
For Android Architecture Components View Model,
It's not a good practice to pass your Activity Context to the Activity's ViewModel as its a memory leak.
Hence to get the context in your ViewModel, the ViewModel class should extend the Android View Model Class. That way you can get the context as shown in the example code below.
class ActivityViewModel(application: Application) : AndroidViewModel(application) {
private val context = getApplication<Application>().applicationContext
//... ViewModel methods
}
It's not that ViewModels shouldn't contain Android specific code to make testing easier, since it's the abstraction that makes testing easier.
The reason why ViewModels shouldn't contain an instance of Context or anything like Views or other objects that hold onto a Context is because it has a separate lifecycle than Activities and Fragments.
What I mean by this is, let's say you do a rotation change on your app. This causes your Activity and Fragment to destroy itself so it recreates itself. ViewModel is meant to persist during this state, so there's chances of crashes and other exceptions happening if it's still holding a View or Context to the destroyed Activity.
As for how you should do what you want to do, MVVM and ViewModel works really well with the Databinding component of JetPack.
For most things you would typically store a String, int, or etc for, you can use Databinding to make the Views display it directly, thus not needing to store the value inside ViewModel.
But if you don't want Databinding, you can still pass the Context inside the constructor or methods to access the Resources. Just don't hold an instance of that Context inside your ViewModel.
What I ended up doing instead of having a Context directly in the ViewModel, I made provider classes such as ResourceProvider that would give me the resources I need, and I had those provider classes injected into my ViewModel
Short answer - Don't do this
Why ?
It defeats the entire purpose of view models
Almost everything you can do in view model can be done in activity/fragment by using LiveData instances and various other recommended approaches.
As others have mentioned, there's AndroidViewModel which you can derive from to get the app Context but from what I gather in the comments, you're trying to manipulate #drawables from within your ViewModel which defeats the purpose MVVM.
In general, the need to have a Context in your ViewModel almost universally suggests you should consider rethinking how you divide the logic between your Views and ViewModels.
Instead of having ViewModel resolve drawables and feed them to the Activity/Fragment, consider having the Fragment/Activity juggle the drawables based on data possessed by the ViewModel. Say, you need different drawables to be displayed in a view for on/off state -- it's the ViewModel that should hold the (probably boolean) state but it's the View's business to select the drawable accordingly.
DataBinding makes it quite easy:
<ImageView
...
app:src="#{viewModel.isOn ? #drawable/switch_on : #drawable/switch_off}"
/>
If you have more states and drawables, to avoid unwieldy logic in the layout file you can write a custom BindingAdapter that translates, say, an Enum value into an R.drawable.* ref, e.g.:
enum class CatType { NYAN, GRUMPY, LOL }
class CatViewModel {
val catType: LiveData<CatType> = ...
// View-tier logic, takes the burden of knowing
// Contexts and R.** refs from the ViewModel
#BindingAdapter("bindCatImage")
fun bindCatImage(view: ImageView, catType: CatType) = view.apply {
val resource = when (value) {
CatType.NYAN -> R.drawable.cat_nyan
CatType.GRUMPY -> R.drawable.cat_grumpy
CatType.LOL -> R.drawable.cat_lol
}
setImageResource(resource)
}
<ImageView
bindCatType="#{vm.catType}"
... />
If you need the Context for some component that you use within your ViewModel -- then, create the component outside the ViewModel and pass it in. You can use DI, or singletons, or create the Context-dependent component right before initialising the ViewModel in Fragment/Activity.
Why bother
Context is an Android-specific thing, and depending on it in ViewModels is unwieldy for unit tests (of course you can use AndroidJunitRunner for android-specific stuff, but it just makes sense to have cleaner code without the extra dependency). If you don't depend on Context, mocking everything for the ViewModel test is easier. So, rule of thumb is: don't use Context in ViewModels unless you have a very good reason to do so.
TL;DR: Inject the Application's context through Dagger in your ViewModels and use it to load the resources. If you need to load images, pass the View instance through arguments from the Databinding methods and use that View context.
The MVVM is a good architecture and It's definitely the future of Android development, but there's a couple of things that are still green. Take for example the layer communication in a MVVM architecture, I've seen different developers (very well known developers) use LiveData to communicate the different layers in different ways. Some of them use LiveData to communicate the ViewModel with the UI, but then they use callback interfaces to communicate with the Repositories, or they have Interactors/UseCases and they use LiveData to communicate with them. Point here, is that not everything is 100% define yet.
That being said, my approach with your specific problem is having an Application's context available through DI to use in my ViewModels to get things like String from my strings.xml
If I'm dealing with image loading, I try to pass through the View objects from the Databinding adapter methods and use the View's context to load the images. Why? because some technologies (for example Glide) can run into issues if you use the Application's context to load images.
Hope it helps!
In Hilt:
#Inject constructor(#ApplicationContext context : Context)
has a reference to the application context, however that contains android specific code
Good news, you can use Mockito.mock(Context.class) and make the context return whatever you want in tests!
So just use a ViewModel as you normally would, and give it the ApplicationContext via the ViewModelProviders.Factory as you normally would.
You should not use Android related objects in your ViewModel as the motive of using a ViewModel is to separate the java code and the Android code so that you can test your business logic separately and you will have a separate layer of Android components and your business logic and data ,You should not have context in your ViewModel as it may lead to crashes
I was having trouble getting SharedPreferences when using the ViewModel class so I took the advice from answers above and did the following using AndroidViewModel. Everything looks great now
For the AndroidViewModel
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.preference.PreferenceManager;
public class HomeViewModel extends AndroidViewModel {
private MutableLiveData<String> some_string;
public HomeViewModel(Application application) {
super(application);
some_string = new MutableLiveData<>();
Context context = getApplication().getApplicationContext();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
some_string.setValue("<your value here>"));
}
}
And in the Fragment
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
public class HomeFragment extends Fragment {
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
final View root = inflater.inflate(R.layout.fragment_home, container, false);
HomeViewModel homeViewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
homeViewModel.getAddress().observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(#Nullable String address) {
}
});
return root;
}
}
Using Hilt
#Module
#InstallIn(SingletonComponent::class)
class AppModule {
#Singleton
#Provides
fun provideContext(application: Application): Context = application.applicationContext
}
Then pass it via constructor
class MyRepository #Inject constructor(private val context: Context) {
...
}
This is a way to get Context in to ViewModel
private val context = getApplication<Application>().applicationContext
you can access the application context from getApplication().getApplicationContext() from within the ViewModel. This is what you need to access resources, preferences, etc..
Finally i got the easiest way to get context in viewModel using MVVM. Suppose we need context in viewmodel class so we can go to dependency injection or using ANDROID_VIEW_MODEL instead of using ViewModel. sample is given below.
class SampleViewModel(app: Application) : AndroidViewModel(app){
private val context = getApplication<Application>().applicationContext
val prefManager = PrefManager(context)
//Now we can call any method which is in PrefManager class like
prefManager.getToken()
}
Use the following pattern:
class NameViewModel(
val variable:Class,application: Application):AndroidViewModel(application){
body...
}
The problem with injecting a Context into the ViewModel is that the Context can change at any time, depending on screen rotation, night mode, or system language, and any returned resources can change accordingly.
Returning a simple resource ID causes problems for extra parameters, like getString substitutions.
Returning a high-level result and moving rendering logic to the Activity makes it harder to test.
My solution is to have the ViewModel generate and return a function that is later run through the Activity's Context. Kotlin's syntactic sugar makes this incredibly easy!
ViewModel.kt:
// connectedStatus holds a function that calls Context methods
// `this` can be elided
val connectedStatus = MutableLiveData<Context.() -> String> {
// initial value
this.getString(R.string.connectionStatusWaiting)
}
connectedStatus.postValue {
this.getString(R.string.connectionStatusConnected, brand)
}
Activity.kt // is a Context
override fun onCreate(_: Bundle?) {
connectionViewModel.connectedStatus.observe(this) { it ->
// runs the posted value with the given Context receiver
txtConnectionStatus.text = this.run(it)
}
}
This allows ViewModel to hold all of the logic for calculating the displayed information, verified by unit tests, with the Activity being a very simple representation with no internal logic to hide bugs.
I created it this way:
#Module
public class ContextModule {
#Singleton
#Provides
#Named("AppContext")
public Context provideContext(Application application) {
return application.getApplicationContext();
}
}
And then I just added in AppComponent the ContextModule.class:
#Component(
modules = {
...
ContextModule.class
}
)
public interface AppComponent extends AndroidInjector<BaseApplication> {
.....
}
And then I injected the context in my ViewModel:
#Inject
#Named("AppContext")
Context context;
Related
I have multiple viewmodels that access a single repository (one activity and the rest fragments).
AdminActivityViewModel
AdminListUsersViewModel
AdminUserTransactionsViewModel
... and a few more
My AdminRepo class has multiple constructors so that I can pass callback methods from the ViewModel
public AdminRepo(Application application, AdminActivityCallback callback) {
this.callback = callback;
BaseApplication baseApplication = (BaseApplication) application;
RetrofitClient client = baseApplication.getRetrofitClient();
adminService = client.getRetrofit().create(AdminService.class);
SharedPrefManager sharedPref = SharedPrefManager.getInstance(application);
AuthHeader authHeader = new AuthHeader(
sharedPref.getIdToken(),
sharedPref.getIdClient(),
sharedPref.getUserEmail()
);
client.setAuthHeader(authHeader);
}
public AdminRepo(Application application, AdminListUsersCallback callback) {
//Exact same code in constructor as above ^
}
public AdminRepo(Application application, AdminUserTransactionsCallback callback) {
//Exact same code in constructor as above ^
}
And in each of the ViewModels I am creating an instance of the AdminRepo (which is probably a bad practice) but I don't know how I can improve this.
public class AdminActivityViewModel extends AndroidViewModel implements AdminActivityCallback
public AdminActivityViewModel(#NonNull Application application) {
super(application);
repo = new AdminRepo(application, this);
}
How can I design my AdminRepo and ViewModels so that they share exactly one repository without creating an expensive AdminRepo class everytime?
I have considered making my AdminRepo class a singleton with a .getInstance() method, but I'm getting SO MANY contradicting posts on how Repository classes SHOULD NOT be static or a singleton, which makes me extremely confused on what I SHOULD do.
https://stackoverflow.com/a/7464235/11110509
If all view models live at the same time then and repository does not keep any state you could share the same instance of repository and provide that instance for each view model. However there's no place for magic here - if you create an instance of repository, you have to keep a reference to that, so you can pass the same object to other view models.
At first you need to make your view model accepting external dependencies (I\d recommend seeing dependency injection pattern)
YourViewModel( /* other dependencies ..., */ AdminRepo adminRepo)
Once you have that, you need to create a view model factory. This post describes it nicely, but long story short: implement ViewModelProvider.Factory that will keep your repository instance and use it in ViewModelProvider to obtain an instance of your view model.
With this setup you will be in control what instance you create and how you create other view models. This could be automated though with the use of dependency injection framework (Koin, dagger, hilt). If you use Dagger or Hilt (recommended by Google), then you can leave your object lifecycle in hands of the framework by providing a proper annotation. Let's try this exaple:
#Singleton
class MyRepository { ...
#HiltViewModel
class MyViewModel {
MyRepository repo;
#Inject MyViewModel(MyRepository repo) { ...
...
This code will make your repository a singleton tied to your application lifecycle. Usually you don't want to do that, because the object will live in the memory even if you move to the screen that deosn't need that. But you could use #ActivityScoped so your repository lives as long the activity.
Now if those view models have different lifecycles and they don't overlap, it would be completely fine to create a new insance for each one of them. You wouldn't want to keep unnecessary objects in the memory while you don't need them anymore.
I'm doing some codelabs of kotlin fundamentals and I don't really get in android with the ViewModel why sometimes there seems to be a need of creating it through a ViewModelFactory. Here you can see the codelab which talks about this.
They just say to perform the initialization using the factory method pattern but I don't understand the why. Why do we need to use factory pattern? Is it because we need to pass some parameter to the ViewModel? Or is it for some other reason? Is every time we need to create a ViewModelFactory just to pass parameters to the ViewModel?
I've been looking for the answer, trying to confirm whether is just to pass extra parameters or is because of any other reason but still I'm not sure and I haven't found the answer.
There are a few things that need to consider before using ViewModel and ViewModelFactory
ViewModel is LifecycleAware Components.
ViewModel survive configuration changes.
ViewModelProvider' can only instantiateViewModel` with no-args contructor.
Why do we need to use factory pattern?
To instantiate ViewModel with arguments need to use ViewModelFactory. ViewModelProviders Utility can not create an instance of a ViewModel with argument constructor because it does not know how and what objects to pass in the constructor.
Also, you should follow the Dependency Injection principle. A class should not create dependencies it needs. It should be provided rather than creating.
For Example -
public class LogInViewModel extends ViewModel {
private final LogInRepo repo;
public LogInViewModel (LogInRepo repo) {
/* this.repo = new LogInRepo(); Not recommended, It violates DI principle*/
this.repo = repo;
}
}
To define a singleton, should I use Kotlin object declaration or to make an ordinary Kotlin class and inject it using dagger? In my opinion the first option is definitely easier but there may be a reason to use dagger in this situation that I'm not aware of.
Option 1 (notice object keyword):
object SomeUtil {
// object state (properties)
fun someFunction(number: Long) {
// ...
}
}
Option 2 (notice class keyword):
class SomeUtil {
// object state (properties)
fun someFunction(number: Long) {
// ...
}
}
#Module
class AppModule {
#Provides
#Singleton
internal fun provideTheUtil() = SomeUtil()
}
class MainActivity : BaseActivity() {
#Inject internal lateinit var util: SomeUtil
}
UPDATE 2019-07-03
#Blackbelt said in comments that we should prefer option 2 for testability. But libraries like MockK can mock objects too. So do you still think option 2 is the preferred one?
You might want to reconsider the need of NumberFormatUtil being a singleton. It might be cheaper if you use #Reusable with Dagger or even a factory without any scope directly.
If NumberFormatUtil is fairly simple and only provides a few utility methods, no state and no need for mocking in tests, you could use an object implementation, maybe using #JvmStatic for Java-inter-operability. But then you could go for global utility (extension) functions as well:
package xyz
fun formatNumber(number: Long) {
// ...
}
fun Long.format() = formatNumber(this)
You should use option 2.
In software engineering, the singleton pattern is a software design
pattern that restricts the instantiation of a class to one "single"
instance. This is useful when exactly one object is needed to
coordinate actions across the system.
From: Singleton Pattern
So, a singleton is single instance in a scope. In case of Android, it is virtual machine instance running the app. In case you need custom scopes, you have to use option 2 only.
But, if you have only static methods inside the object you want to inject its better to keep them as global methods and even get rid of object. No need to inject anything. It is similar to a java class with only static methods (I mentioned this point as it is a usual way of creating Utility classes).
However, if the object also has some state. I would recommend going dagger way. The object way does not provide with dependency injection. It only creates a Singleton. Your purpose for using dagger is dependency injection.
I confused with MVVM concept that ViewModel should not reference View.
In my usecase , I have to use Databinding and wrapping the Drawable by LiveData and observe its value in xml view.
Base on suggestion from Android I implemented as below
https://developer.android.com/topic/libraries/architecture/viewmodel
If the ViewModel needs the Application context, for example to find a
system service, it can extend the AndroidViewModel class and have a
constructor that receives the Application in the constructor, since
Application class extends Context.
MyViewModel.kt
class MyViewModel(application: Application): AndroidViewModel(application){
private val _showIcon = MutableLiveData<Drawable>
val showIcon: LiveData<Drawable>
get() = _showIcon
fun applyChanged(){
if(condition){
_showIcon.value = AppCompatResources.getDrawable(getApplication(),R.drawable.icon1)
}else{
_showIcon.value = null
}
}
}
main_activity.xml
android:drawableTop="#{viewModel.showIcon}"
Question:
This approach is OK with MVVM concept ? Is there anything I have to do with context inside ViewModel to prevent leak memory problem?
Or any potential problem in my code ?
Thank you so much !
I don't see any need to use databinding or view models for what you want to do. Just refer the drawable directly in xml file. If it is null, it won't be there. This is valid because you are getting the image resource from your own resources. If you were supposed to get any drawable from server or local database your approach would make sense.
My issue with the Android-specific pattern is, if you use their AndroidInjection class, there is no way to members inject other objects besides Activities/Fragments/custom views/adapters, except with the Application Component. This is because you cannot get a reference the the Subcomponent (AndroidInjector) used to inject Activities/Fragments.
This makes injecting Dialogs (if you use DialogFragments).
The AndroidInjection class seems to support just the core Android types.
What follows is not an answer to your question, but an explanation why you shouldn't be asking this question at all.
You should avoid injections into custom Views in general. The reasons for this are listed in this article.
Advantages of using Method Injection in this case [injection into custom Views] are:
Dependencies will need to be propagated from top level component (Activity or Fragment)
Method Injection does not open door to Single Responsibility Principle violation
No dependency on the framework
Better performance
The first advantage might come as a surprise because propagation from
top level component is harder than adding annotation to fields, and
involves more boilerplate code. This is surely a bad thing, right?.
Not in this case. In fact, there are two good aspects associated with
such a propagation of dependencies. First of all, the dependencies
will be visible at the top level component. Therefore, just by looking
at e.g. Fragment‘s fields, the reader of the code will immediately
understand that this Fragment shows images. Such optimizations for
readability makes the system more easily maintainable in the long
term. Secondly, there are not many use cases in which sub-classes of
View need additional dependencies. The fact that you need to actually
work in order to provide these dependencies will give you a bit of
time to think about whether providing them is a good design decision
to start with.
The second advantage is related to collaborative construction. You
might be very experienced software engineer yourself, but you’ll
probably have also less experienced teammates. Or it is possible that
you’ll leave the project one day, and the guy who will take over will
not be as good as you. By injecting one single dependency using a
framework, you basically open a door for other injections. Imagine
that some data from SharedPreferences becomes required in custom View
in order to e.g. fix a bug. One of the less experienced developers
might decide that it is a good approach to inject SharedPreferences
into custom View directly. Doing this violates Single Responsibility
Principle, but that developer might not even be aware of such a
concept. Therefore, in the long term, such injection “backdoors” can
reduce design quality and lead to long debug sessions.
The third advantage of using Method Injection with custom Views is
that you don’t couple the View to dependency injection framework. Just
imagine that few years from now you (or some other poor guy) need to
replace the framework. The fact that you’ll probably have tens of
Activities and Fragments to start with will make your life miserable.
If you’ll have additional tens or hundreds of custom Views to handle,
then it might bring you into suicidal mood.
The last (but not least) advantage is performance. One screen can
contain one Activity, several Fragments and tens of custom Views.
Bootstrapping this number of classes using dependency injection
framework might degrade application’s performance. It is especially
true for reflection based frameworks, but even Dagger carries some
performance cost.
In addition, I advice to avoid the new injection method that involves AndroidInjection class. It is discussed in this video tutorial.
First, you should think over Vasily's answer.
But let's think for a moment how we did this before Dagger Android?
We built a subcomponent from the component that was taken from the Application class. Later, we could use this subcomponent in order to inject fields, for example, of a custom view.
So, we'll try to do the exact same thing now.
Suppose, our aim is to inject MyAdapter class into a MyButton:
public class MyButton extends AppCompatButton {
#Inject MyAdapter adapter;
public MyButton(Context context) {
super(context);
...
}
}
And let's make the adapter have a dependency on the activity Context, not application Context:
public class MyAdapter {
#Inject
public MyAdapter(#Named("activity") Context context) {
}
}
Let's start with the custom Application class.
MyApplication.java
public class MyApplication extends DaggerApplication {
#Inject
DispatchingAndroidInjector<Activity> dispatchingActivityInjector;
public static MySubcomponent mySubcomponent;
#Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder()
.create(this);
}
}
AppComponent.java:
#Component(modules = {AndroidSupportInjectionModule.class, ActivityBindingModule.class, AppModule.class})
#Singleton
public interface AppComponent extends AndroidInjector<MyApplication> {
#Component.Builder
abstract class Builder extends AndroidInjector.Builder<MyApplication> {
}
}
AppModule.java
#Module
abstract class AppModule {
#Binds
#Singleton
#Named("app")
abstract Context providesContext(Application application);
}
ActivityBindingModule.java
#Module(subcomponents = MySubcomponent.class)
public abstract class ActivityBindingModule {
#Binds
#IntoMap
#ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity>
bindMainActivityInjectorFactory(MySubcomponent.Builder builder);
}
AndroidSupportInjectionModule.java is shipping with dagger itself. If you do not use classes from support package (i.e. android.support.v4.app.Fragment instead of android.app.Fragment), then use AndroidInjectionModule.java.
MySubcomponent.java
#ActivityScope
#Subcomponent(modules = {SubcomponentModule.class/*, other modules here, if needed */})
public interface MySubcomponent extends AndroidInjector<MainActivity> {
void inject(MyButton button);
#Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {
public abstract MySubcomponent build();
}
}
SubcomponentModule.java
#Module
abstract class SubcomponentModule {
#Binds
#ActivityScope
#Named("activity")
abstract Context toContext(MainActivity activity);
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Inject
MySubcomponent subcomponent;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Will inject `subcomponent` field
AndroidInjection.inject(this);
// Saving this component in a static field
// Hereafter you are taking responsibility of mySubcomponent lifetime
MyApplication.mySubcomponent = subcomponent;
super.onCreate(savedInstanceState);
setContentView(new MyButton(this));
}
}
Having all of these, now here's how MyButton will look like:
public class MyButton extends AppCompatButton {
#Inject MyAdapter adapter;
public MyButton(Context context) {
super(context);
MyApplication.mySubcomponent.inject(this);
}
}
I admit that this looks hacky and certainly not an approach to stick to. I'm happy to see a better approach.
This is because you cannot get a reference the the Subcomponent (AndroidInjector) used to inject Activities/Fragments.
You can always just inject the component itself. Just add a field for the component to your Activity / Fragment and let Dagger inject it along with the rest.
// will be injected
#Inject MainActivitySubcomponent component;
The issue of whether the dagger-android classes like AndroidInjector should support injection inside Views or not has been discussed in the following Github issue:
https://github.com/google/dagger/issues/720
Quoting from one of the library authors:
There is both a philosophical point and logistical/implementation point to be made here.
First, it's not fully clear to us that injecting views is the right thing to do. View objects are meant to draw, and not much else. The controller (in a traditional MVC pattern) is the one which can coordinate and pass around the appropriate data to a view. Injecting a view blurs the lines between fragments and views (perhaps a child fragment is really the appropriate construct instead?)
From the implementation perspective, there is also a problem in that there isn't a canonical way to retrieve the View's parent Fragments (if any), or Activity to retrieve a parent component. There have been hacks suggested to build in that relationship, but so far we haven't seen anything that seems to suggest that we could do this correctly. We could just call View.getContext().getApplicationContext() and inject from there, but skipping the intermediate layers without any option for something in between is inconsistent with the rest of our design, and probably confusing to users even if it works.
This reinforces the opinion expressed in Vasily's answer.
To add further, people often seem to want to inject model-layer dependencies inside their custom views. This is a bad idea as it goes against the software engineering principle of separation of concerns.
The correct solution for associating a view and a model is to write an adapter like the adapters for RecyclerView and ListView. You can inject the model-layer dependency at the Fragment or Presenter level and set the adapter there.