Detailed Android context abstract class _android

Source: Internet
Author: User
Tags instance method serialization

The first thing we should know about the context:
(1) It describes the information of an application environment, that is, the context.
(2) The class is an abstract (abstract class) class, and Android provides the specific implementation class for that abstract class (we'll talk about the Contextiml class later).
(3) through which we can obtain the resources and classes of the application, as well as some application-level operations, such as: Start an activity, send a broadcast, accept intent information, etc...

We can then use the context object to build the application level operation (Application-level operations).
inheritance relationship of context-related classes

Related class Introduction:
Context Classpath:/frameworks/base/core/java/android/content/context.java
Description: An abstract class that provides a common set of APIs. The source code (partial) is as follows:

Public abstract class Context { 
   ... 
   Public abstract Object Getsystemservice (String name); Obtain system level service public 
   abstract void startactivity (Intent Intent);   Start activity public 
   abstract componentname startservice (Intent service) via a Intent;//Start service 
   // Gets the Sharedpreferences object public 
   abstract sharedpreferences getsharedpreferences (String name,int mode) according to the filename; 
   ... 
} 

&NBSP
Contextiml.java class   path:/frameworks/base/core/java/android/app/contextimpl.java
Description: The implementation class of the context class is CONTEXTIML, which implements the function of the context class. Note that most of the functions of this function are called directly on their properties mpackageinfo to complete, as we'll see later.     source code (part) is as follows:

/** * Common Implementation of context APIs, which provides the base * Context Object 
 For the activity and the other application components. * * Class Contextimpl extends context{//All application programs common one Mpackageinfo object/*package*/MP 
   
  Ackageinfo; @Override public Object Getsystemservice (String name) {... else if (activity_service.equals (name)) {R 
    Eturn Getactivitymanager (); 
    else if (input_method_service.equals (name)) {return inputmethodmanager.getinstance (this); @Override public void StartActivity (Intent Intent) {...//start an activity mmainthread.getinst 
  Rumentation (). Execstartactivity (Getoutercontext (), mmainthread.getapplicationthread (), NULL, NULL, intent,-1); } 
} 

Contextwrapper class Path: \frameworks\base\core\java\android\content\contextwrapper.java
Description: Like its name, the class is just a wrapper over the context class, whose constructor contains a real context reference, the Contextiml object. The source code (partial) is as follows:

The public class Contextwrapper extends the context 
  mbase;//This property points to a CONTEXTIML instance, typically creating application, Service, Assigning values 
   
  //Creating application, Service, and activity during an activity calls this method to assign a value to the Mbase property 
  protected void Attachbasecontext (context Base) { 
    if (mbase!= null) { 
      throw new IllegalStateException ("base context already set"); 
    } 
    Mbase = base; 
  } 
  @Override public 
  void StartActivity (Intent Intent) { 
    mbase.startactivity (Intent);//Invoke Mbase instance method 
  } 
} 

Contextthemewrapper class Path:/frameworks/base/core/java/android/view/contextthemewrapper.java
Description: The class contains the interface associated with the subject (Theme), which is specified by the Android:theme property. Only the activity needs the theme, the service does not need the subject, so the service inherits directly from the Contextwrapper class.
The source code (partial) is as follows:

 public class Contextthemewrapper extends Contextwrapper {//This property points to a Contextiml instance, which is typically created 
  Build application, Service, activity when assign value private context mbase; 
      The Mbase assignment also has two public contextthemewrapper (the context base, int themeres) {super (base); 
      Mbase = base; 
   Mthemeresource = Themeres; 
      } @Override protected void Attachbasecontext (context newbase) {super.attachbasecontext (newbase); 
   Mbase = Newbase; } 
} 

Activity class, service class, application class is essentially a context subclass, more information you can refer to the source code to understand.
 
Two, when to create a context instance  
 
After familiarity with the inheritance relationship What do we do next to analyze where the application needs to create the context object? The application creates a context instance when
(1) Creates a Application object, and the entire app altogether has a Application object
(2) When the service object is created
(3)
&NBSP
When the activity object is created:
 
Total Context instances = Number of Service + activity number + 1 (application corresponding context instance)
 
The timing of the specific creation:
 
1, time to create Application object
&NBSP
The Application object is created the first time each application starts. If it is clear to start an activity (startactivity) process for an application, the time to create application is in the Create Handlebindapplication () method, which is located in the Activitythread.java class, as follows:

CONTEXTIML instance 
private final void handlebindapplication (Appbinddata data) { 
  ... 
  that was created while creating application. Create Application Object 
  Application app = Data.info.makeApplication (Data.restrictedbackupmode, null); 
  ... 
} 
 
Public Application Makeapplication (Boolean forcedefaultappclass, instrumentation instrumentation) { 
  ... 
  try { 
    Java.lang.ClassLoader cl = getClassLoader (); 
    Contextimpl appcontext = new Contextimpl ();  Create a Contextimpl object instance 
    appcontext.init (this, null, mactivitythread);//Initialize the associated properties of the CONTEXTIML instance 
    /// Create a new Application object  
    app = MActivityThread.mInstrumentation.newApplication ( 
        cl, Appclass, appcontext); 
    Appcontext.setoutercontext (APP); Pass the application instance to the Contextimpl instance      
  } ... 
} 

2, the opportunity to create an Activity object  
When an activity is started by startactivity () or Startactivityforresult () If system detection requires a new activity object to be created, the Handlelaunchactivity () method is called back, and the method then calls the Performlaunchactivity () method to create an activity instance. And the callback OnCreate (), the OnStart () method, and so on, the functions are all located in the Activitythread.java class, as follows:

 


3, the opportunity to create service objects
by StartService or Bindservice, if the system detects that a new service instance needs to be created, it will callback the Handlecreateservice () method and complete the relevant data operations. The Handlecreateservice () function is located in the Activitythread.java class, as follows:

Create a service instance while creating a Contextiml instance 
private final void Handlecreateservice (Createservicedata data) { 
  ... 
  Create a service instance 
  service service = NULL; 
  try { 
    Java.lang.ClassLoader cl = Packageinfo.getclassloader (); 
    Service = (Service) cl.loadclass (data.info.name). newinstance (); 
  catch (Exception e) { 
  } ... 
  Contextimpl context = new Contextimpl (); Create a Contextimpl object instance 
  context.init (PackageInfo, NULL, this);  Initializes the related properties of the CONTEXTIML instance 
  //Gets the Application object information we created earlier 
  application app = Packageinfo.makeapplication (False, minstrumentation); 
  Pass the service information to the Contextimpl instance 
  context.setoutercontext (service); 
  ... 
} 

 
In addition, it is important to emphasize that, through the analysis of Contextimp, most of the operations of its method are directly related to the method of calling its property mpackageinfo (the attribute class
type is PackageInfo). This shows that Contextimp is a lightweight class, and that PackageInfo is the real heavyweight class. And the
all CONTEXTIML instances in an app correspond to the same PackageInfo object.
           
Three, Use context to get the Sharedpreferences class
for you to analyze the use of the context to obtain Sharedpreferences class, Sharedpreferences class must have been used, The general acquisition
method is to obtain the Sharedpreferences object based on the relevant information by invoking the Getsharedpreferences () method. The specific process is as follows:
1, call   getsharedpreferences () get the corresponding file, the function implements the following function:

The context class static data collection, with key value pairs to save all the data sets that are formed after reading the XML file private static final Hashmap<file, sharedpreferencesimpl>  
 
Ssharedprefs = new Hashmap<file, sharedpreferencesimpl> (); @Override public sharedpreferences getsharedpreferences (String name, int mode) {//its corresponding Sharedpreferencesimpl object, which has a  
   A hashmap set preserves our Sharedpreferencesimpl SP for serialization of the file; File f = getsharedprefsfile (name); If there is a corresponding file under the package, there is no existing to create a new synchronized (ssharedprefs) {//whether the file has been read, is directly returned to the Sharedpreferences object sp = Ssharedpre 
     Fs.get (f); 
       if (SP!= null &&!sp.hasfilechanged ()) {//log.i (TAG, "returning existing prefs" + name + ":" + sp); 
     return SP; 
   The XML file is serialized, while the data is written to the map collection in the map map = null; 
       if (f.exists () && f.canread ()) {try {str = new FileInputStream (f); 
       Map = Xmlutils.readmapxml (str); 
     Str.close (); 
    
   }  
     ... 
   } 
     Synchronized (ssharedprefs) {if (sp!= null) {  LOG.I (TAG, "Updating existing prefs" + name + "" + SP + ":" + map);  Sp.replace (map); 
       Update data Collection} else {sp = Ssharedprefs.get (f); if (sp = = null) {//Create a new Sharedpreferencesimpl object and set its associated property SP = new Sharedpreferencesimpl (f, mode, map  
         ); 
       Ssharedprefs.put (f, SP); 
   } return SP; 
 } 
}


2, Sharedpreferences is just an interface, it defines a number of ways to manipulate the XML file, the real implementation of the class is Sharedpreferencesimpl, the class is CONTEXTIML internal class, the class is as follows:

Soga, this form we have contacted in the analysis of the context Contextiml  
//sharedpreferences is just an interface, its real implementation class is Sharedpreferencesimpl class 
private Static Final class Sharedpreferencesimpl implements sharedpreferences{ 
   private Map mMap//Save the result of serialization of the file, the key value pairs form c4/>//gets the corresponding value value by key value public 
   string getString (String key, String defvalue) { 
     synchronized (this) { 
       String v = (string) mmap.get (key); 
       Return v!= null? V:defvalue 
     } 
   } 
   ... 
   Obtain the corresponding Edito class of the Sharedpreferencesimpl object, manipulate the data public 
   final class Editorimpl implements Editor { 
     private Final map<string, object> mmodified = Maps.newhashmap (); The set of changes to the key value was saved 
   } 
} 


Basically get the Sharedpreferences object is so.

Iv. getting the application context at any location
1. Get the application context at any location
when accessing resources in an Android program, you need to provide context, and in general it is only possible to use the API in a variety of component (activity, provider, and so on) to access the language; people who like programming know that Writing a tool class can be useful for code reuse, and some of the tools in Android are confusing to write, such as: we need to get sharedpreferences in the tool class, which requires context support.

To solve this problem with the context, we can customize a application class to implement this functionality.

Import android.app.Application;

public class ContextUtil extends application {
  private static ContextUtil instance;

  public static ContextUtil getinstance () {return
    instance;
  }

  @Override public
  void OnCreate () {
    //TODO auto-generated method Stub
    super.oncreate ();
    instance = this;
  }


Then add Android:name= "MyPackage" in the manifest <application>. ContextUtil "so that we can get the context under any class, for example: Context c=contextutil.getinstance ();

2, Context considerations:

The context can do a lot of things in Android, but the main function is to load and access resources. There are two kinds of context in Android, one is the application, the other is the context of activity, and we usually pass the activity context among various classes and methods.
such as the oncreate of an activity:

protected void OnCreate (Bundle state) {
    super.oncreate (state);

    TextView label = new TextView (this); Pass context to view Control
    Label.settext ("Leaks are bad");

    Setcontentview (label);


Passing the activity context to view means that the view has a reference to the activity, which in turn refers to the resources the activity occupies: view hierachy, Resource, and so on.
This will reveal a lot of memory if there is a memory leak in the context.
The leak here means that the GC has no way to reclaim the activity's memory.

The activity of leaking an entire is very easy.

When the screen rotates, the system destroys the current activity, saves state information, and creates a new one.

For example, we write an application, it needs to load a large picture, we do not want to rotate the screen every time we destroy the picture, reload. The simple idea of implementing this requirement is to define a static drawable so that the activity class creates and destroys it and is always saved in memory.
Implement similar:

public class MyActivity extends activity {
    private static drawable Sbackground;
    protected void OnCreate (Bundle state) {
        super.oncreate (state);

        TextView label = new TextView (this);
        Label.settext ("Leaks are bad");

        if (Sbackground = = null) {
            Sbackground = getdrawable (R.drawable.large_bitmap);
        }
    Label.setbackgrounddrawable (sbackground);//drawable attached to a view

    setcontentview (label);
    }


The program looks simple, but it's a big problem. There is a leak when the screen rotates (that is, the GC cannot destroy the activity).
We have just said that the system destroys the current activity when the screen rotates. However, when drawable is associated with the view, Drawable saves the reference of the view, that is, Sbackground holds the reference to the label, and the label holds the reference to the activity. Since drawable cannot be destroyed, neither the reference nor the indirect reference can be destroyed, so that the system has no way to destroy the current activity, resulting in a memory leak. The GC is powerless for this type of memory leak.

The way to avoid this memory leak is to avoid the lifecycle of any object in the activity and to avoid the activity being destroyed as a result of the object's reference to the activity. We can use the application context. The application context accompanies the life of application, irrespective of the lifecycle of the activity. The application context can be obtained by Context.getapplicationcontext or Activity.getapplication methods.

To avoid a context-related memory leak, keep the following points in mind:
(1) Do not allow long-lived objects to refer to the activity context, that is, to ensure that the object referencing the activity is the same as the activity's life cycle
(2) for long life cycle objects, you can use the application context
(3) Avoid non-static internal classes, use static classes as much as possible, avoid life cycle problems, and pay attention to life cycle changes caused by internal classes to external object references

3, get the other package context

The concept of a context in Android must be known to all. The context can do a lot of things, open activity, send broadcasts, open folders and databases under this package, get classloader, get resources, and so on. If we get a context object for a package, then we can basically do most of the things that the package can do on its own.
The context has a Createpackagecontext method that can create another package, which is different from its own instance, but has the same functionality.


This method has two parameters:
(1) PackageName package name, to get the package name of the context
(2) Flags sign bit, there are context_include_code and context_ignore_security two options. Context_include_code means to include code, which means you can execute the code inside the package. Context_ignore_security means ignoring security warnings, if you do not add this flag, some features are not used, there will be security warnings.


Here's a small example of how to execute a class in another package. The package name for another package is Chroya.demo, class name Main, method name print, and the code is as follows:

Package Chroya.demo; 
 
Import android.app.Activity; 
Import Android.os.Bundle; 
Import Android.util.Log; 
 
Class Main extends Activity { 
   
  @Override the public 
  void OnCreate (Bundle savedinstancestate) { 
    super.oncreate ( savedinstancestate); 
  } 
   
  public void print (String msg) { 
    log.d ("Main", "msg:" + msg); 
  } 

Package Chroya.demo; 
 
Import android.app.Activity; 
Import Android.os.Bundle; 
Import Android.util.Log; 
 
Class Main extends Activity { 
   
  @Override public 
  void OnCreate (Bundle savedinstancestate) { 
    Super.oncreate (savedinstancestate); 
  } 
   
  public void print (String msg) { 
    log.d ("Main", "msg:" + msg); 
  } 
 

The code block of the call main's print method for this package is as follows:

Context C = Createpackagecontext ("Chroya.demo", Context.context_include_code | context.context_ignore_security); 
Load this class 
clazz = C.getclassloader (). LoadClass ("Chroya.demo.Main"); 
Creates a new instance 
Object Owner = clazz.newinstance (); 
Gets the print method, passing in the parameter and executing 
Object obj = Clazz.getmethod ("print", String.class). Invoke (owner, "Hello"); 

Context C = Createpackagecontext ("Chroya.demo", Context.context_include_code | context.context_ignore_security); 
Load this class 
clazz = C.getclassloader (). LoadClass ("Chroya.demo.Main"); 
Creates a new instance 
Object Owner = clazz.newinstance (); 
Gets the print method, passing in the parameter and executing 
Object obj = Clazz.getmethod ("print", String.class). Invoke (owner, "Hello"); 

OK, so we call the print method of the main class of the Chroya.demo package, execute the result, and print out hello.

Related Article

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.