Android-context everything.

Source: Internet
Author: User

Type of context

We know that Android applications are written in the Java language, so you can think about an Android program and a Java program, where are their biggest differences? What is the dividing line? In fact, the simple point of analysis, the Android program is not like a 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 like activity, Service, Broadcastreceiver and other system components, which do not create instances like a normal Java object new, but rather have their own context, which is what we are discussing here. As you can tell, the context is a core feature class that maintains the functionality of the components in your Android program.

Let's look at the inheritance structure of the context:

Context of the inheritance structure is a little bit more complex, you can see, the direct subclass has two, one is Contextwrapper, one 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 also has three direct subclasses, Contextthemewrapper, service, and application. Where Contextthemewrapper is a wrapper class with a theme, and it has a direct subclass that is activity.

So here we see at least a few familiar faces, Activity, Service, and application. In fact, we can conclude that there are three types of context, namely application, activity and service. Although each of the three classes undertakes different roles, they are all part of the context, and their specific context functions are implemented by the Contextimpl class.

So what functions can the context achieve? This is really too much, pop toast, start activity, start service, send broadcast, operation database, etc. all need to use the context. Because the specific capabilities of the context are implemented by the Contextimpl class, the three types of context, Activity, service, and application, are universally available in most scenarios. However, there are several scenarios that are special, such as initiating activity and popping dialog. For security reasons, Android does not allow activity or dialog to appear out of thin air, and an activity's start-up must be based on another activity, which is the return stack. The dialog must pop up on an activity (unless it is a System alert type of dialog), so in this scenario, we can only use the activity type context, otherwise there will be an error.

Number of context

So how many context is there in an application? In fact, according to the context type above we can already come to an answer. The context has a total of application, activity, and service three types, so the calculation formula for the number of context in an application can be written like this:

Number of context = number of activity + number of Service + 1  

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

Design of application Context

Basically every application will have its own application, and let it inherit from the application class of the system, and then encapsulate some common operations in its own application class. In fact, this is not a recommended approach by Google, because we are only using application as a generic tool class, and actually using a simple singleton class can also achieve the same functionality. But according to my observations, there are too many projects that use application. Of course, this practice does not have any side effects, but it is still a lot of people to understand application some lack. So here we first to analyze the design of application, to tell some people do not know the details, and then look at the usual use of application problems.

First create a new myapplication and let it inherit from application, and then specify the MyApplication in the Androidmanifest.xml file as follows:

<application      android:name= ". MyApplication "      android:allowbackup=" true "      android:icon=" @drawable/ic_launcher "      android:label=" @ String/app_name "      android:theme=" @style/apptheme "> ...  </application>  

Once specified, the Android system will create an instance of MyApplication when our program is launched, and if not specified here, a application instance will be created by default.

As mentioned earlier, many of the application are now used as generic tool classes, so how do we get to an instance of it as a generic tool class? As shown below:

public class Mainactivity extends Activity {            @Override      protected 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 simple, just call the Getapplication () method to get an instance of our custom application, and the print results are as follows:

So in addition to the Getapplication () method, there is actually a getapplicationcontext () method, the two methods seem to be a bit related, then what is the difference between them? Let's modify the code:

public class Mainactivity extends Activity {            @Override      protected 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 print out the results of the getapplicationcontext (), and now rerun the code, as shown in the following:

Hey? It seems that the printed results are the same, and even the memory addresses behind them are the same, and they appear to be the same object. In fact, this result is also very good understanding, because the previous has said, application itself is a context, so here to get Getapplicationcontext () The result is MyApplication itself instance.

Then some friends may ask, since these two methods get the same results, then why should Android provide two ways to repeat the function? In fact, these two methods are quite different in scope. The semantics of the Getapplication () method is very strong, knowing that it is used to get the application instance, but this method can only be called in the activity and service. So maybe in most cases we use application in activity or service, but if we want to get application instances in some other scenario, like Broadcastreceiver, You can then use the Getapplicationcontext () method, as shown below:

public class Myreceiver extends Broadcastreceiver {        @Override public      void OnReceive (context context, Intent Intent) {          MyApplication myApp = (myapplication) context.getapplicationcontext ();          LOG.D ("TAG", "MyApp is" + MyApp);      }    }  

That is, the scope of the Getapplicationcontext () method is more extensive, any instance of the context, as long as the call Getapplicationcontext () method can get our Application object.

So more careful friends will find that, in addition to these two methods, there is actually a getbasecontext () method, this basecontext is what things? We can still verify this by printing:

Oh? This time we get a different object, and the Getbasecontext () method gets a Contextimpl object. Does this contextimpl feel a bit familiar? Go back to the context of the inheritance structure diagram, Contextimpl is the implementation of the contextual function class. That is to say, like application, activity such classes actually do not go to the specific implementation of the function of the context, but only to do a layer of interface encapsulation, the specific function of the context is by the Contextimpl class to complete. So how is this design going to happen? Let's have a look at the source code, please. Because application, Activity, service are directly or indirectly inherited from Contextwrapper, we will directly see Contextwrapper source code, as follows:

/** * proxying Implementation of the context that simply delegates all of their calls to * another Context.  Can is 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'll then being * 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 illegalstate          Exception ("Base context already set");      } mbase = base; }/** * @return The base context as set by the constructor or Setbasecontext */public context Getba      Secontext () {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);   }        ......  }

Because the method in Contextwrapper is still very much, I have made some filtering, just put out some methods. So the above methods believe that everyone is very familiar with, getresources (), Getpackagename (), Getsystemservice () and so on are the methods we often use. So what is the implementation of all these methods? In fact, the implementation of all the methods in Contextwrapper is very uniform, that is, the method that corresponds to the current method name in the Mbase object is called.

So what is this Mbase object? Let's look at the Attachbasecontext () method in line 16th, which passes in a base parameter and assigns the 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, so as to assign a value to the Mbase object, All the methods in the Contextwrapper are actually implemented by Contextimpl by this mechanism, so it is very accurate to say that Contextimpl is the implementation class of the context function.

Then another look at the Getbasecontext () method We just printed, in line 26th. This method has only one line of code, that is, the return of the Mbase object, and the Mbase object is actually Contextimpl object, so just the printing results have been confirmed.

Questions about using Application

Although the use of application is really very simple, but our usual development work there are a lot of application misuse of the scene, then today to see what is more prone to make mistakes in the place we should pay attention to.

Application is one of the types of the context, then does it mean that as long as it is an instance of application, you can use the various methods of the 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, we get the package name of the current application in the MyApplication constructor, and print it out. The Getpackagename () method is used to get the package name, and this method is provided by the context. Does the code above work? Run for a moment and you'll see the results shown below:

The application crashes immediately when it starts, and a null pointer exception is reported. Looks like a very simple piece of code, how can you become a null pointer? But if you try to change the code to the following wording, you'll see that everything is fine:

public class MyApplication extends application {            @Override public      void OnCreate () {          super.oncreate ();          String PackageName = Getpackagename ();          LOG.D ("TAG", "package name is" + PackageName);      }        }  

The results of the operation are as follows:

The method that calls the context in the constructor method crashes, and the method that calls the context in the OnCreate () method is all right, so what is going on between the two methods? We re-review the source code of the Contextwrapper class, there is a Attachbasecontext () method in Contextwrapper, this method will be passed in a context parameter assigned to the Mbase object, After that, the Mbase object has a value. And we know that all of the context of the method is to invoke the Mbase object of the same name method, so that is, if the Mbase object is not assigned to any of the methods in the context of the call, there will be a null pointer exception, the above code is the case. The execution order of the methods in application is as follows:

It is a recommended practice to initialize various global variable data in the OnCreate () method in application, but if you want to advance the initialization time point to the extreme, you can rewrite the Attachbasecontext () method as follows:

public class MyApplication extends application {            @Override      protected void Attachbasecontext (Context base) {          //The method that calls the context here will crash          Super.attachbasecontext (base);          The method of the context can be called normally here      }        }  

The above is one of the points we should pay attention to when we use application, and then we will introduce another very common application misuse situation.

In fact, the official Android is not very recommended that we use custom application, basically only need to do some global initialization may need to use the custom application, the official document is described as follows:

But as far as my observations are concerned, the use of custom application is now basically 100%, which is that we may not use it when we write our own test demos, and almost all of the formal projects will use custom application. However, there are many projects that use the custom application not in place, as stated in the official documentation, and most projects simply use the custom application as a generic tool class, which does not need to be implemented with application. Using a singleton can be a more standard approach.

However, the custom application also has no side effects, it and the singleton mode two can achieve the same function, but I have seen a number of projects, the custom application and singleton patterns mixed together to use, which makes people surprised. A very typical example is shown below:

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, here is a getinstance () method for getting an instance of MyApplication, and after that, you can invoke the various tool methods in MyApplication.

But is this the right kind of notation? This is a big mistake! Because we know that application belongs to the system component, the system component instance is to be created by the system, if we go to the new one MyApplication instance, it is just a normal Java object, but not the ability of any context. A lot of people are giving me feedback. Null pointer error when using Litepal is because of this, because what you provide to Litepal is just an ordinary Java object that cannot be manipulated by this object.

So if you really want to provide a way to get myapplication instances, what is the standard notation? In fact, we just need to remember that, application global only one, it is already a single case, no need to use a singleton mode to do multi-instance protection, the code is as follows:

public class MyApplication extends application {            private static MyApplication app;            public static MyApplication getinstance () {          return app;      }            @Override public      void OnCreate () {          super.oncreate ();          App = this;      }        }  

The getinstance () method can be provided as usual, but do not make any logical judgments, directly back to the App object, and what is the App object? In the OnCreate () method We assign the App object to This,this is the current instance of application, then the app is the current instance of application.

Android-context everything.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.