Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to parse the details of Android Context

2025-03-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article shows you how to analyze the various details of Android Context, the content is concise and easy to understand, can definitely brighten your eyes, through the detailed introduction of this article, I hope you can get something.

Context believes that almost all Android developers come into contact with it every day because it is so common. But that doesn't mean there's nothing to talk about about Context. In fact, there are too many small details in Context that go unnoticed, so today let's learn about the details you don't know.

Context Typ

We know that Android applications are written in the Java language, so you can think about, an Android program and a Java program, what is the biggest difference? What is the demarcation line? In fact, simple analysis, Android program is not like Java program, casually create a class, write a main () method can run, but to have a complete Android engineering environment, in this environment, we have such as Activity, Service, BroadcastReceiver and other system components, and these components are not like an ordinary Java object new can create instances, but to have their own context, that is, we discuss here Context. It can be said that Context is a core functional class that keeps the components of the Android program working properly.

Let's take a look at Context's inheritance structure:

The inheritance structure of Context is a little more complex. As you can see, there are two direct subclasses, one is ContextWrapper and the other is ContextImpl. As can be seen from the name, ContextWrapper is the wrapper class of the context function, while ContextImpl is the implementation class of the context function. ContextWrapper has three direct subclasses, ContextThemeWrapper, Service, and Application. Where ContextThemeWrapper is a wrapper class with a theme, and it has a direct subclass called Activity.

So we see at least a few familiar faces here, Activity, Service, and Application. From this, in fact, we can come to the conclusion that there are three types of Context, which are Application, Activity and Service. Although these three classes play different roles, they all belong to a kind of Context, and their specific Context functions are realized by the ContextImpl class.

So what exactly can Context do? This is just too much. Context is needed to pop up Toast, start Activity, start Service, send broadcasts, manipulate databases, and so on. Because the specific capabilities of Context are implemented by the ContextImpl class, in most scenarios, the three types of Context, Activity, Service, and Application, are universal. However, there are several special scenarios, such as starting Activity and popping up Dialog. For security reasons, Android does not allow Activity or Dialog to appear out of thin air, and the startup of one Activity must be based on another Activity, that is, the return stack formed by it. Dialog must pop up on an Activity (unless it is a Dialog of type System Alert), so in this scenario, we can only use a Context of type Activity, otherwise there will be an error.

Number of Context

So how many Context are there in an application? In fact, according to the above Context type, we can already get the answer. There are three types of Context: Application, Activity, and Service, so the formula for calculating the number of Context in an application can be written as follows:

Number of Context = number of Activity + number of Service + 1

The 1 above represents the number of Application, because there can be multiple Activity and multiple Service in an application, but only one Application.

The design of Application Context

Basically every application has its own Application and inherits it from the system's Application class, and then encapsulates some common operations in its own Application class. In fact, this is not a practice recommended by Google, because we only use Application as a general utility class, and we can actually use a simple singleton class to achieve the same function. But according to my observation, too many projects use Application in this way. Of course, this practice does not have any side effects, but it just shows that there are still many people who lack understanding of Application. So here we first analyze the design of Application, talk about some details that we don't know, and then take a look at the usual use of Application.

First create a new MyApplication and have it inherit from Application, and then specify the MyApplication in the AndroidManifest.xml file, as follows:

.

After the specification is completed, the Android system will create an instance of MyApplication when our program starts, and an instance of Application will be created by default if not specified here.

Public class MainActivity extends Activity {@ Overrideprotected void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); MyApplication myApp = (MyApplication) getApplication (); Log.d ("TAG", "getApplication is" + myApp);}}

As you can see, the code is very simple. You only need to call the getApplication () method to get an instance of our custom Application. The printed result is as follows:

So in addition to the getApplication () method, there is actually a getApplicationContext () method. These two methods seem to be a little related, so what's the difference between them? Let's modify the code:

Public class MainActivity extends Activity {@ Overrideprotected void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); MyApplication myApp = (MyApplication) getApplication (); Log.d ("TAG", "getApplication is" + myApp); Context appContext = getApplicationContext (); Log.d ("TAG", "getApplicationContext is" + appContext);}}

Again, we printed out the results of getApplicationContext (), and now rerun the code, as shown in the following figure:

Huh? It seems that the printed result is the same, even the back memory address is the same, it seems that they are the same object. In fact, this result is also easy to understand, because as mentioned earlier, Application itself is a Context, so the result of getting getApplicationContext () here is an instance of MyApplication itself.

So some friends may ask, since the results of these two methods are the same, why should Android provide two methods of duplicating functions? In fact, there is a big difference between the two methods in scope. The semantics of the getApplication () method is so strong that it is obvious at a glance that it is used to get Application instances, but this method can only be called in Activity and Service. So maybe in most cases we use Application in Activity or Service, but if you also want to get an instance of Application in some other scenarios, such as BroadcastReceiver, you can use the getApplicationContext () method, as shown below:

Public class MyReceiver extends BroadcastReceiver {@ Overridepublic void onReceive (Context context, Intent intent) {MyApplication myApp = (MyApplication) context.getApplicationContext (); Log.d ("TAG", "myApp is" + myApp);}}

In other words, the scope of the getApplicationContext () method is broader, and any instance of Context can get our Application object by calling the getApplicationContext () method.

So more careful friends will find that in addition to these two methods, there is actually a getBaseContext () method, what is this baseContext? Let's verify it by printing:

Oh? This time you get a different object, and the getBaseContext () method gets a ContextImpl object. Does this ContextImpl feel like deja vu? Go back and take a look at the inheritance structure diagram of Context. ContextImpl is the implementation class of the context function. In other words, classes such as Application and Activity will not specifically implement the functions of Context, but only do a layer of interface encapsulation, and the specific functions of Context are completed by the ContextImpl class. So how on earth is this design realized? Let's take a look at the source code. Since Application, Activity, and Service all inherit directly or indirectly from ContextWrapper, let's look directly at the source code of ContextWrapper, as shown below:

/ * * 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. * / public class ContextWrapper extends Context {Context mBase; / * * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. * * @ param base The new base context for this wrapper. * / protected void attachBaseContext (Context base) {if (mBase! = null) {throw new IllegalStateException ("Base context already set");} mBase = base;} / * * @ return the base context as set by the constructor or setBaseContext * / public Context getBaseContext () {return mBase;} @ Override public AssetManager getAssets () {return mBase.getAssets () } @ Override public Resources getResources () {return mBase.getResources ();} @ Override public ContentResolver getContentResolver () {return mBase.getContentResolver ();} @ Override public Looper getMainLooper () {return mBase.getMainLooper ();} @ Override public Context getApplicationContext () {return mBase.getApplicationContext () } @ Override public String getPackageName () {return mBase.getPackageName ();} @ Override public void startActivity (Intent intent) {mBase.startActivity (intent);} @ Override public void sendBroadcast (Intent intent) {mBase.sendBroadcast (intent);} @ Override public Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter) {return mBase.registerReceiver (receiver, filter) @ Override public void unregisterReceiver (BroadcastReceiver receiver) {mBase.unregisterReceiver (receiver);} @ Override public ComponentName startService (Intent service) {return mBase.startService (service);} @ Override public boolean stopService (Intent name) {return mBase.stopService (name) } @ Override public boolean bindService (Intent service, ServiceConnection conn, int flags) {return mBase.bindService (service, conn, flags);} @ Override public void unbindService (ServiceConnection conn) {mBase.unbindService (conn);} @ Override public Object getSystemService (String name) {return mBase.getSystemService (name);}.}

Since there are still a lot of methods in ContextWrapper, I did some filtering and only posted some of them. So I believe all of you are very familiar with the above methods. GetResources (), getPackageName (), getSystemService () and so on are all the methods we often use. So what is the implementation of all these methods? In fact, the implementation of all methods in ContextWrapper is very uniform, that is, it calls the method in the mBase object that corresponds to the preceding legal name.

So what is this mBase object? Let's take a look at the attachBaseContext () method on line 16, which passes in a base parameter and assigns this parameter to the mBase object. The attachBaseContext () method is actually called by the system, it will pass the ContextImpl object as a parameter to the attachBaseContext () method, thus assigning a value to the mBase object, and then all the methods in ContextWrapper are actually specifically implemented by ContextImpl through this delegate mechanism, so it is very accurate to say that ContextImpl is the implementation class of the context function.

Then take a look at the getBaseContext () method we just printed, on line 26. This method has only one line of code and just returns the mBase object, and the mBase object is actually the ContextImpl object, so the print result just now is confirmed.

Problems with using Application

Although the use of Application is indeed very simple, there are a lot of scenarios of misuse of Application in our usual development work, so let's take a look at what are easy to make mistakes that we should pay attention to.

Application is one of the types of Context, so does that mean that as long as it is an instance of Application, you can use various methods of Context at any time? Let's do an experiment and we'll find out:

Public class MyApplication extends Application {public MyApplication () {String packageName = getPackageName (); Log.d ("TAG", "package name is" + packageName);}}

This is a very simple custom Application, and we get the package name of the current application in the constructor of MyApplication and print it out. Getting the package name uses the getPackageName () method, which is provided by Context. So does the above code work properly? Just run and you will see the results shown below:

The application crashed as soon as it started, reporting a null pointer exception. It seems like a simple piece of code, how can it become a null pointer? But if you try to change the code to the following, you will find that everything is fine:

Public class MyApplication extends Application {@ Overridepublic void onCreate () {super.onCreate (); String packageName = getPackageName (); Log.d ("TAG", "package name is" + packageName);}}

The running result is as follows:

The method that calls Context in the constructor crashes, and the method that calls Context in the onCreate () method is fine, so what happens between the two methods? Let's review the source code of the ContextWrapper class. There is an attachBaseContext () method in ContextWrapper, which assigns a Context parameter passed in to the mBase object, and then the mBase object has a value. We also know that all Context methods call the mBase object's method of the same name, that is, if you call any method in the Context without the mBase object being assigned, a null pointer exception will occur, as is the case in the above code. The execution order of the methods in Application is shown in the following figure:

It is recommended to initialize various global variable data in the onCreate () method in Application, but if you want to advance the initialization time to the extreme, you can also override the attachBaseContext () method, as shown below:

Public class MyApplication extends Application {@ Overrideprotected void attachBaseContext (Context base) {/ / the method of calling Context here will crash super.attachBaseContext (base); / / the method of Context can be called normally}} here

The above is one of the points that we need to pay attention to when using Application. Here is another common misuse of Application.

In fact, Android officially does not recommend us to use custom Application. Basically, we only need to use custom Application when we need to do some global initialization, as described in the official document:

But as far as my observation is concerned, the use of custom Application can basically reach 100%, that is, we may not use it when we write our own test demo, and almost all formal projects use custom Application. However, for use and use, there are many projects that do not have the right use of custom Application. As stated in the official documents, most projects just regard custom Application as a general tool class, and this function does not need to be achieved with Application, so using singletons may be a more standard way.

However, custom Application does not have any side effects, it can achieve the same function as singleton mode, but I have seen some projects that mix custom Application with singleton mode, which is amazing. A very typical example is as follows:

Public class MyApplication extends Application {private static MyApplication app;public static MyApplication getInstance () {if (app = = null) {app = new MyApplication ();} return app;}}

Just like the singleton pattern, a getInstance () method is provided to get an instance of MyApplication, with which you can call various tool methods in MyApplication.

But is this the right way to write? This way of writing is very wrong! Because we know that Application belongs to the system component, and the instance of the system component is created by the system, if we go to new an instance of MyApplication, it is just an ordinary Java object, and does not have any ability of Context. A lot of people have reported to me that the null pointer error occurred when using LitePal is actually due to this reason, because what you provide to LitePal is a normal Java object, which cannot be used for Context operations.

So if you really want to provide a way to get an instance of MyApplication, what is the more standard way to write it? In fact, we just need to keep in mind that there is only one global Application, and it is already a singleton, so there is no need to use singleton mode to protect it with multiple instances. The code is as follows:

Public class MyApplication extends Application {private static MyApplication app;public static MyApplication getInstance () {return app;} @ Overridepublic void onCreate () {super.onCreate (); app = this;}}

The getInstance () method can be provided as usual, but don't make any logical judgments in it, just return the app object directly, but what is the app object? In the onCreate () method, we assign the app object to this,this, which is the instance of the current Application, so app is the instance of the current Application.

The above content is how to analyze the details of Android Context. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report