Basically, each application will have its own Application, which inherits from the Application class of the system, and then encapsulates some common operations in its own Application class. In fact, this is not a recommended practice for Google, because we just use Application as a general tool class, and in fact use a simple singleton class can achieve the same function. But according to observation, there are too many projects using Application in this way. Of course, this approach does not have any side effects, but it just shows that many people still have some deficiencies in understanding the application. So here we will first analyze the design of Application, tell some details that you do not know, and then look at the usual use of Application.
<application android:name=".MyApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > ...... </application
When the assignment is completed, when our program starts, the Android system creates an instance of MyApplication, and if it is not specified here, an instance of Application will be created by default.
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 very simple, just call the getApplication() method to get an example of our custom Application. The print result is as follows:
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); } }
Similarly, we print out the result of getApplicationContext() and now rerun the code as shown in the following figure:
So why does Android offer two ways to duplicate functionality, since the results of both methods are the same? In fact, the two methods are quite different in scope. The getApplication() method is very semantical, and it is known to be used to obtain application instances at first glance, but this method can only be invoked in Activity and Service. Maybe in most cases we use Application in Activity or Service, but if we want to get an instance of Application in some other scenarios, such as Broadcast Receiver, we can use the getApplicationContext() method, as follows:
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { MyApplication myApp = (MyApplication) context.getApplicationContext(); Log.d("TAG", "myApp is " + myApp); } }
In other words, the getApplicationContext() method has a wider scope. Any instance of a Context can get our Application object by calling the getApplicationContext() method.
ContextWrapper1 /** 2 * Proxying implementation of Context that simply delegates all of its calls to 3 * another Context. Can be subclassed to modify behavior without changing 4 * the original Context. 5 */ 6 public class ContextWrapper extends Context { 7 Context mBase; 8 9 /** 10 * Set the base context for this ContextWrapper. All calls will then be 11 * delegated to the base context. Throws 12 * IllegalStateException if a base context has already been set. 13 * 14 * @param base The new base context for this wrapper. 15 */ 16 protected void attachBaseContext(Context base) { 17 if (mBase != null) { 18 throw new IllegalStateException("Base context already set"); 19 } 20 mBase = base; 21 } 22 23 /** 24 * @return the base context as set by the constructor or setBaseContext 25 */ 26 public Context getBaseContext() { 27 return mBase; 28 } 29 30 @Override 31 public AssetManager getAssets() { 32 return mBase.getAssets(); 33 } 34 35 @Override 36 public Resources getResources() { 37 return mBase.getResources(); 38 } 39 40 @Override 41 public ContentResolver getContentResolver() { 42 return mBase.getContentResolver(); 43 } 44 45 @Override 46 public Looper getMainLooper() { 47 return mBase.getMainLooper(); 48 } 49 50 @Override 51 public Context getApplicationContext() { 52 return mBase.getApplicationContext(); 53 } 54 55 @Override 56 public String getPackageName() { 57 return mBase.getPackageName(); 58 } 59 60 @Override 61 public void startActivity(Intent intent) { 62 mBase.startActivity(intent); 63 } 64 65 @Override 66 public void sendBroadcast(Intent intent) { 67 mBase.sendBroadcast(intent); 68 } 69 70 @Override 71 public Intent registerReceiver( 72 BroadcastReceiver receiver, IntentFilter filter) { 73 return mBase.registerReceiver(receiver, filter); 74 } 75 76 @Override 77 public void unregisterReceiver(BroadcastReceiver receiver) { 78 mBase.unregisterReceiver(receiver); 79 } 80 81 @Override 82 public ComponentName startService(Intent service) { 83 return mBase.startService(service); 84 } 85 86 @Override 87 public boolean stopService(Intent name) { 88 return mBase.stopService(name); 89 } 90 91 @Override 92 public boolean bindService(Intent service, ServiceConnection conn, 93 int flags) { 94 return mBase.bindService(service, conn, flags); 95 } 96 97 @Override 98 public void unbindService(ServiceConnection conn) { 99 mBase.unbindService(conn); 100 } 101 102 @Override 103 public Object getSystemService(String name) { 104 return mBase.getSystemService(name); 105 } 106 107 ...... 108 }
Since there are still many methods in ContextWrapper, I did some screening and only posted some of them. So these methods are very familiar to everyone, getResources(), getPackageName(), getSystemService(), and so on are the methods we often use. So what are the implementations of all these methods? In fact, all the implementations of methods in ContextWrapper are very uniform, that is, the method corresponding to the previous method name in the mBase object is called.
So what is this mBase object? Look at the attachBaseContext() method in line 16, which passes in a base parameter and assigns it to the mBase object. The attachBaseContext() method is actually called by the system. It passes the ContextImpl object as a parameter to the attachBaseContext() method and assigns the value to the mBase object. Then all the methods in ContextWrapper are actually implemented by the ContextImpl through this delegation mechanism, so Cont. ExtImpl is an implementation class of context functionality that is very accurate.