I'm so interested in getContext() method and how it works. For example, I wrote recycleView
#Override
public RecycleView.ViewHolder onCreateViewHolder(ViewGroup parent ,int viewtype)
{
View view =LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,parent,false);}
and I call it on my fragment class defined to MainActivity.
My question here how does getContext() method return MainActivity? How does getContext() is understood?
I look at that method into the Android Studio, but I didn't understand it as well.
For the ultimate reference: Context | Android Developers
Long story short, the View class, and thus all of it's subclasses (like ViewGroup), have a defined function called getContext() which returns a Context object. This class is abstract and the implementation is provided by the Android system, which is why the actual functionality is not easy to understand. It allows you to access global information about an application's environment, such as themes, resources, etc. It is pretty magical, but that magical aspect can be costly if you aren't careful. It is very easy to leak a Context object, which can quickly eat up RAM on the device.
Related
This is what the documentation for ContextWrapper states:
Proxying implementation of Context that simply delegates all of its
calls to another Context. Can be subclassed to modify behavior without
changing the original Context.
I'm having a hard time understanding this, does it just implement methods of Context in another class?
This is an incredibly powerful capability. It does exactly what AtomaticallyBeyond writes, that is, it simply delegates method calls to another Context. So, you might say, big deal! But if you write another class that that extends ContextWrapper, that class can override the some of the method of the delegate context. For example, getAssets or getResources. Most applications have no need to do that, but for some more sophisticated applications, I go back to my first comment, that's an incredible powerful capability.
I am new to Android development and I made a research about Context. I understand what it is and why is usefull. But I see that android handles context for me in activities for example, I have to extends a class that inherits from context and thats it. However in some situations I have to manually add context to a thing. For example when creating a new instance of a view from kotlin. I have to pass a context to the view constructor, for example: Button(this)
Why do I have to tell a view instance that it is part of an activity explicitly?
I am defining it inside the activity after all.
I understand that context it's like a bridge between my app and external resources and system tools but setting it manually sometimes confuses me.
True, theoretically, that could have been done only when attaching the view to a parent, and then if the parent is attached to the activity root it has context, if not - when attaching a view, Android could have gone over its descendants and set their Context.
However:
It is inconvenient to implement. It's easy to have autonomous views with each already set to its context.
There are some things that are in the context and are necessary for manipulating the view. E.g. constraint system, metrics... many bits and bolts. Views also listen to events and can provide some services that require Context before they are attached to another view.
What if you have several contexts. You want to be able to choose which context to refer to. Say, you got an always-on-too floating button that is managed by some service and views managed by the activity.
It is highly recommended to peek in Android sources. You will find cool facts inside, and it's an excellent way to learn.
I found this article: https://www.101apps.co.za/index.php/articles/all-about-using-android-s-context-class.html
I think that explains very well why do we need to pass context manually to view instances.
"Passing the context to the view when it is being constructed, gives
you the flexibility to use a different context to construct the view,
as the one used by the activity, for example. This gives the view
access to resources other than those used by the activity."
Android could set context automatically but it gives you freedom to choose another one. That could be useful.
This is because there can many other parameters for this.
We set the context because we let the Button base class(or any other you're using) that the declared variable is instance of Button but not the other classes available all over!
I was implementing MVP in my new application, then I came across a problem. I needed to call a method of View, inside View (Activity) itself. It is by definition of MVP code separation, wrong thing to do.
By definition:
The Presenter is in charge of the the orchestration between the Model and the View. It basically receive events from both and act consequently. The Presenter is the only component that knows others. It has a reference to the View and a another to the Model. (source)
In the same article it was mentioned that View does not reacts to user interactions, it passes control to Presenter to do the job. I have also read this SOF post about dependency rules.
In my case, I am using custom AppTheme. AppTheme needs to be set before setContent() call, what I am doing is create a method in View interface called setAppTheme() which my Activity implements, and there is code to apply theme. Now the problem is, this is called within the app, which makes calling of a View method inside its implementation.
To sum up, what my understanding of MVP either one of the following
should be true:
Do call View method inside Activity, because setTheme() wont work after setContent() and our presenter.setView() is in
onResume(), but will this satisfy MVP separation of M-V-P ?
Do not make interface method for setAppTheme(), instead create a private method in Activity which sets theme. This method will have
nothing to do with any layer of MVP. But question is, if project is
using MVP pattern, is this practice valid?
Here is my MVP:
public class AboutUsMVP
{
public interface Model
{
String getFbLink();
String getTwitterLink();
String getEmailLink();
String getCompanyLink();
}
public interface Presenter
{
void setView( View view );
void fbButtonClicked();
void twitterButtonClicked();
void emailButtonClicked();
void imageButtonClicked();
}
public interface View
{
void showFacebookPage();
void showTwitterPage();
void showEmailIntent();
void showCompanyWebsite();
void setAppTheme();
void setCustomActionBar();
}
}
Please do point out mistakes where I missed them.
From what I know, same case can be argued in the light of
setActionBar() and setOnClickListener() methods, although these
may require their separate post, but they are more relevant here and
new post for either of them will be duplicate.
Please note that my Activity implements View interface.
EDIT: More explanation
My View is actually Activity class. This is View of MVP, not Android API's View class. The thing is, there is a method setAppTheme() which only related to View of MVP, (Activity of Android). This call is not in the Contract (AboutUsMVP.java) which by Google convention should be AboutUsContract.java, this setAppTheme() is not in Contract, and it cant be, so does this violate MVP principle?
There is no possible alternative, one can say make an interface of setAppTheme(), if I do so, it will not work because:
setAppTheme() is called just after super() method, if not it is useless. And MVP's presenter starts working in onResume. If an interface is made, and setAppTheme() is brought into MVP's jurisdiction, it will have no effect.
Indeed, Views in an MVP are supposed to be dumb. This is: they don't contain any logic. Just receive the event generated by the user and immediately delegate its work to the presenter. The View can also inform the presenter that some events have happened (the view has been created, the screen rotate, etc)
This can lead to some confusions. Who is responsible of calling some methods? As you said the View has to perform some actions like setOnClickListener but the presenter is responsible of handling the event. Just have this in mind:
The View is just an interface. This means that you can use anything that implements that interface
Right now you're making a mobile app. But if you wanted to code a console or a desktop app, the presentation logic doesn't change. Anything that is specific to the "View technology" (android, desktop, etc) should be performed inside the code specific to that technology. This way your code will be loosely coupled to your tech stack
I believe #Pelocho answer is correct and you should mark it as the right one. But I would like to present my answer (that agrees with his) but from an alternative point-of-view. On for this different POV I would like to debate your on definition of presenter:
The Presenter is in charge of the the orchestration between the Model
and the View
So the question I propose here is: "what is this model that the presenter interacts with?". And my answer to it is to look into the classic "note-taking" application and argue that the model is text and associated meta-data, usually stored in some DB that the presenter will read, parse and push to the view.
Nowhere in this "model" the application theme is relevant. Theme is purely a function of the view. Theme is only associated to the final on-screen looks of it. Just like the view is the one in charge of layouting the content on screen, or to know what font size to use.
And that means even if those layouting, size, colors can be changed from a user settings option, it still falls outside the responsibility of the presenter and the model, as they're only interested in the content.
tl;dr:
Just read the theme on the Activity.onCreate (before super.onCreate) directly from the SharedPreferences and do not involve the Presenter on it.
I'm about creating a simple app with MVP implementation, and trying to make a permission request in a presenter. To make a permission request, I need to pass Context like this.
// Location permission has not been granted yet, request it.
ActivityCompat.requestPermissions(fragmentActivity, new String[]{permission}, requestId);
I've read several articles and they mention that using Context in a presenter is not a good exercise. So, I'm just wondering how people are handling a permission request with MVP. And I don't really know why using Context in a presenter is not good practice.
Please, help me to understand how I should handle a permission request and why using context is not good practice.
Thanks
You must never send any object related to Android to the presenter layer, and they must be fully decoupled.
to do these things I always remember a good sentence and that goes Do not inject objects, inject operations and behavior.
it so simple dont inject your context into your presenter which is a wrong practice. instead in your view contract (view interface) add a function called getPermission() then in your view implement that method along with other methods of your contract, then call that method whenever you need the permission.
thats the best way. trust me ;)
There are multiple flavors of MVP out there in practice. I am not here to start a debate which one is right and which one is wrong. As long as a particular flavor works for your scenario, it shall be used.
Instead, I will try to explain why the context in Presenter should be avoided and one of the ways I have avoided in my code.
One of the major reason you should not have a context in the presenter, there might be references to presenter which could leak the activity. In places where I had to deal with a context within the activity, I have accessed through Views.
interface View {
Context getContext();
}
interface Presenter {
void setView(View view);
}
So PresenterImpl implements a view, onCreate of the activity and resets it onDestroy of the activity. So the presenter never directly holds the context. But it holds the view, which has knowledge about the View.
In my android project I have some activity classes, and also simples java classes. There are some of them are independent of contextes and views totally, but in others duly I need it for to access a particular method of context.
I have read about it, and some people says they pass the context of some activity to every class that need its methods; others that pass a view and then get the context or that this classes have to extend of Activity... ¬¬
But for example, I have a class where it only calls once a method of context like:
getSharedPreferences(configNameFile, 0);
getString(R.string.text);
...
Therefore I would like to know what pattern do you use to do this always.
My personal favorite ways to do this is:
Dependency injection
using RoboGuice
or
Make sure you don't need the context
If possible, try to avoid using the context in other files then your activity. If it is really needed, I write a wrapper most of the time. E.g. for Settings, I write a Settings interface that is able to do it with shared preferences. Whenever you want to change your settings implementation later, it is easily done by swapping the implementation of your interface. If you really need it, I'd prefer using a static Application context
Also, you could make that method accept a Context paramerter, for example:
public void getPrefs(Context context){
context.getSharedPreferences(configNameFile, 0);
context.getString(R.string.text);
}
Then in your Activity pass the current context to it:
public void getPrefs(this);