Have you ever wondered or wondered that we can create an activity or not ???
1 2 |
Activity mActivity = new Activity() |
The answer will be NO? But why??
Android application is using java, but unlike java you can create a class and main () function, then you can run it.
1 2 3 4 5 6 |
public static void main(String[] args) { Random rd = new Random(); // DO Something } |
Android is based on key components including Activity, Service, ContentProvider, and Broadcast receiver. You cannot create a new component simply by using the keyword ‘new’ because all these components have their own context. Activity extended from Context, Service and Application also extend from Context.
For Interface. This is an abstract class where the implementation is provided by the Android system. It allows access to application-specific resources and classes , as well as call-up for application-level operations, like start Activity, broadcasting and receiving intents etc.
From the diagram above. ContextImpl is implementing all of the abstract functions of Context and ContextWrapper wraps all methods from Context and uses implementation from the ContextImpl class. The attachBaseContext method of the ContextWrapper class will make sure that the context is only attached once. ContextThemeWrapper, as the name implies, applies a theme from the application or Acitivty defined via the ‘android: theme’ tag in the AndroidManifest.xml file. Since both the application and the Service don’t need a theme, they inherit directly from ContextWrapper. During operation, the application and service are launched, a new ContextImpl object is created each time the methods in the Context are executed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ContextWrapper</span> <span class="token keyword">extends</span> <span class="token class-name">Context</span> <span class="token punctuation">{</span> <span class="token class-name">Context</span> mBase <span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token class-name">ContextWrapper</span> <span class="token punctuation">(</span> <span class="token class-name">Context</span> base <span class="token punctuation">)</span> <span class="token punctuation">{</span> mBase <span class="token operator">=</span> base <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/** * 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. */</span> <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">attachBaseContext</span> <span class="token punctuation">(</span> <span class="token class-name">Context</span> base <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> mBase <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalStateException</span> <span class="token punctuation">(</span> <span class="token string">"Base context already set"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> mBase <span class="token operator">=</span> base <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> |
How many Context in an Application?
How many contexts are there in an application?
From above, we can conclude that number of contexts Number (Context) = Activity + Service + 1 (Application). For other components like Context Provider, the Broadcast Receiver is not a subclass of Context. So they don’t count, but we need to pass the context object to them when creating a new one.
What Context can do?
Context is incredibly powerful, but it still has some limitations. Since Context is implemented by ContextImpl, in most situations we can use the same Context of activity, service and application. However, in some situations like starting an Activity or show pop up dialog, it must use the context of Activity because the new Activity is based on another Activity to form a stack, the pop-up dialog also needs to show up on top of Activity. Except for some warning dialogs from the system.
- If we use ApplicationContext to start an Activity with standard lauch mode, it will throw expcetion “ndroid.util.AndroidRuntimeException: Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?” This exception is because there is no Activity context present in the activity stack. So, from Service and Application can only use FLAG_ACTIVITY_NEW_TASK (This Activity will become the start of a new task on history stack.) To start an Activity, however this is not recommended?
- Context It can inflate the layout, but will only apply the default android theme, those custom themes won’t be able to apply because only Activity extends ContextThemeWrapper class.
Ways to get Context?
There are ways to getContext:
- view.getContext () which is the Activity context in which the view is stored.
- Activity.getApplicationContext () takes the current application context, when we need it, this global context should first be considered.
- Activity.this when some UI controler needs context or start an Activity. Toast can use ApplicationContext.
Difference between getApplication () and getApplicationContext ()
Difference between getApplication () and getApplicationContext ()
1 2 3 4 5 6 |
<span class="token class-name">Override</span> <span class="token keyword">public</span> <span class="token class-name">Context</span> <span class="token function">getApplicationContext</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> mPackageInfo <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token operator">?</span> mPackageInfo <span class="token punctuation">.</span> <span class="token function">getApplication</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> mMainThread <span class="token punctuation">.</span> <span class="token function">getApplication</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
In fact, both functions return the Application object because Application itself is a context. So why does android provide the above two methods? The reason is because getApplication () can only be used in Activity and Service. In other components like BroadcastReceiver can only use getApplicationContext () to get the Application object.
Improper use of context can easily cause memory leak
Using the wrong context can easily cause memory leaks.
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Singleton</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">Singleton</span> instance <span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">Context</span> mContext <span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">Singleton</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">Singleton</span> <span class="token function">getInstance</span> <span class="token punctuation">(</span> <span class="token class-name">Context</span> context <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> instance <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">synchronized</span> <span class="token punctuation">(</span> <span class="token class-name">Singleton</span> <span class="token punctuation">.</span> <span class="token keyword">class</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> instance <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> instance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Singleton</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> mContext <span class="token operator">=</span> context <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> instance <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Since Singleton will exist for a long time in the application, this causes the context to be held by it and GC will not be able to clean.
Example 2:
1 2 3 4 5 6 7 8 9 10 11 |
public class MainActivity extends Activity { private static ImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... mImageView = (ImageView)findViewById(R.id.imageId); } |
Because ImageView is static and the current context is Activity. This is referenced by imageview, so the entire Activity is leaked.
Some tips to use context:
Here are some tips for using contexts, Since the application exists until the end, so we can save some of the following:
- When the application context can be processed, use the application context as the first priority.
- Do not use / reference of Activity which has a longer lifecycle than Activity.
- Do not use non static inner class inside activity since inner class because inner class has implicit reference to outer class. If using static inner classes , use the weak reference of objects from the outer class.
REFERENCES: