Activity mActivity =new Activity()

As an Android developer, have you ever thought about this question: Can activities be new? Android application development using the JAVA language, Activity is essentially an object, so what is the problem with the way it is written? I guess a lot of people don’t know. Android programs are not like Java programs, just create a class and write a main() method to run. Android application model is based on the application design mode of components. Components should be run in a complete Android engineering environment. System components such as activities and services can work properly, and these components cannot be created in the normal Java object creation way. Instead, they must have their own Context, that is, the Context we discuss here. Context is a core function class that keeps the components of an Android application working properly, so to speak.

What exactly is Context

Context; Context; Background; Context is often referred to as “context” in development, so what does this “context” mean? In language, we can understand it as context; in program, we can understand it as an environment where the current object is in the program, a process of interaction with the system. For example, in wechat chat, the “environment” refers to the chat interface and related data requests and transmission. Context is involved in loading resources, starting activities, obtaining system services, creating views and other operations.

So what is Context? An Activity is a Context, and a Service is a Context. Android programmers abstract the “scene” into a Context class, thinking that every interaction between a user and the operating system is a scene, such as a phone call or a text message, which is a scene with an interface, and some scenes without an interface, such as a Service running in the background. An application can be thought of as a work environment that users in this environment will switch to a different scene, it’s like a secretary at the front desk, she may need to receive guests, may have to print documents, may also to answering customer calls, the call it different scenarios, the front desk secretary could be called an application.

How do you visualize the Context

The above concept uses the common way of thinking of Context as “Context” or “scene”, if you still feel abstract and difficult to understand. Here I give you a metaphor that may not be very appropriate, and I hope it will help you understand: An Android application can be understood as a movie or a TV series. The four components of Activity, Service, Broadcast Receiver and Content Provider are just like the four protagonists in this play: Hu Ge, Huo Jianhua, Shishi and Baby. They are set by the crew (system) from the beginning, the whole play is led by these four leading actors, so these four leading actors are not randomly pulled on the street (a new object) can play. With actors, of course, there must also be a camera. They must pass the play to the audience through the lens, which means that the four components (the four main characters) must work in the Context (camera lens). Button, TextView, LinearLayout controls, just like the supporting actors or extras in the play, they obviously do not use so much, any passer-by a passer-by b can play (can be a new object), but they also have to face the camera (work in the Context), So Button mButton=new Button (Context) is ok. Although not very appropriate, but still very easy to understand, hopefully helpful.

Context in source code

/** * Interface to global information about an application environment. This is * an abstract class whose implementation  is provided by * the Android system. It * allows access to application-specific resources and classes, as well as * up-calls for application-level operations such as launching activities, * broadcasting and receiving intents, etc. */ public abstract class Context { /** * File creation mode: the default mode, where the created file can only * be accessed by the calling application (or all applications sharing the * same user ID). * @see #MODE_WORLD_READABLE * @see #MODE_WORLD_WRITEABLE */ public static final int MODE_PRIVATE = 0x0000; public static final int MODE_WORLD_WRITEABLE = 0x0002; public static final int MODE_APPEND = 0x8000; public static final int MODE_MULTI_PROCESS = 0x0004; ...}Copy the code

Context provides an interface to global information about the application environment. It is an abstract class whose execution is provided by the Android system. It allows access to application-specific resources and types, and is a context governing some resources (application environment variables, etc.). That is, it describes information about an application environment (that is, context); Is an abstract class. Android provides a concrete implementation of this abstract class. It allows you to retrieve application resources and classes (including application-level actions such as starting an Activity, broadcasting, accepting an Intent, and so on). Context is an abstract class, so there must be an implementation of it. We can see its subclasses in the IDE source code, and we can get the following diagram:

The Context class itself is a pure Abstract class with two concrete implementation subclasses: ContextImpl and ContextWrapper. The ContextWrapper class, as its name suggests, is just a wrapper, and the ContextWrapper constructor must contain a reference to the actual Context, AttachBaseContext () is provided in ContextWrapper to specify the actual Context in the ContextWrapper object. Any method that calls the ContextWrapper object is redirected to the actual Context it contains. The ContextThemeWrapper class, as its name suggests, contains an interface associated with the Theme, as in androidManifest.xml via Android: Theme Specifies the theme for the Application element or Activity element. Of course, only an Activity needs a theme. A Service does not need a theme because it is a background scene with no interface, so the Service directly inherits from ContextWrapper, as does the Application. The ContextImpl class actually implements all the functions in the Context, all the methods in the Context class that are called in the application, all of which are implemented from that class. ContextImpl is the implementation class of the Context, and ContextWrapper is the wrapper class of the Context. Activity, Application, and Service inherit from ContextWrapper, ContextThemeWrapper, ContextWrapper. However, they both create a ContextImpl object during initialization, which implements the methods in the Context.

An application has several contexts

In fact, the question itself is not meaningful, the key is to understand the Context, from the diagram above we can already get the answer, in the Application Context implementation subclasses are: Activity, Service, Application. So number of contexts = number of activities + number of services +1. Of course, if you are careful enough, you may have a question: we often say that the four components, how can we only have the Context of the Activity, Service, Broadcast Receiver, Content Provider? Broadcast Receiver, Content Provider is not a subclass of Context. The Context they hold is transmitted from other places, so it does not count in the total number of contexts. The diagram above also tells us from another side of the entire Android system Context class status is how noble, because obviously Activity, Service, Application are subclasses, its status and role is self-evident.

What Context can do

What exactly can Context do? You need Context to pop up a Toast, start an Activity, start a Service, send a broadcast, operate a database, and so on.

TextView tv = new TextView(getContext()); ListAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), ...) ; AudioManager am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); getApplicationContext().getSharedPreferences(name, mode); getApplicationContext().getContentResolver().query(uri, ...) ; getContext().getResources().getDisplayMetrics().widthPixels * 5 / 8; getContext().startActivity(intent); getContext().startService(intent); getContext().sendBroadcast(intent);Copy the code

The Context scope

Context is powerful, but you can’t just grab a Context instance and do anything you want. There are rules that limit its use. Since the Context instance is implemented by the ContextImpl class, the Activity, Service, and Application Context types are common in most scenarios. However, there are a few special scenarios, such as starting an Activity and popping up a Dialog. For security reasons, Android does not allow an Activity or Dialog to appear out of thin air, and one Activity must be launched on top of another, creating a return stack. A Dialog must pop up on top of an Activity (unless it’s a System Alert Dialog), so in this scenario we can only use an Activity-type Context, otherwise we’ll get an error.

From the figure above we can see that the Context held by the Activity has the widest scope and can do anything. Since the Activity inherits from ContextThemeWrapper, and the Application and Service inherit from ContextWrapper, ContextThemeWrapper obviously does something on top of ContextWrapper to make the Activity more powerful, so I’m not going to post the source code here. Without further explanation of YES and NO in the figure above, I would like to mention two situations in which Application and Service are not recommended.

1: if we use the ApplicationContext to launch a LaunchMode for standard Activity complains when android. Util. AndroidRuntimeException: Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? This is because a non-activity Context does not have a task stack, so the Activity to be launched cannot find the stack. The solution to this problem is to specify the FLAG_ACTIVITY_NEW_TASK bit for the Activity to be started, so that a new stack of tasks is created for it when the Activity is started in singleTask mode. This method of starting an Activity with Application is not recommended. Service is the same as Application.

Layout constructs are also legal in applications and services, but they use the default theme style, which may not be used if you customize them. Therefore, this method is not recommended. To sum up: All uI-related activities should be handled using the Activity Context. Some other operation, Service, Activity, Application instance can, of course, pay attention to the Context reference to hold, to prevent a memory leak.

How to get Context

In general, there are four ways to get a Context object

1: view.getContext, which returns the Context object of the current View object, usually the Activity object currently being displayed. 2: the Activity getApplicationContext, gets the current Activity in the process of (application) of the Context object, usually we use the Context object, to give priority to the process of the global Context. 3: ContextWrapper getBaseContext () : used to obtain a ContextWrapper for decoration before the Context, you can use this method, the method used in the actual development is not much, also is not recommended. 4: Activity.this returns the current Activity instance if it is a UI control that needs to use the Activity as the Context object, but the default Toast actually uses ApplicationContext as well.

GetApplication () and getApplicationContext ()

GetApplicationContext getApplication() : getApplicationContext getApplication() : getApplicationContext getApplication() : getApplicationContext I believe this question will be stumped by many developers.

The program is not deceptive, we can print out from the above code that the memory address of both is the same, it seems that they are the same object. This is easy to understand because Application is itself a Context, so the result of getting getApplicationContext() is an instance of Application itself. The question is, why does Android provide two methods that duplicate functions when both methods give the same results? There is actually a big difference in scope between the two methods. The getApplication() method is semantic enough to get an Application instance, but it can only be called in activities and services. If you want to get an instance of an Application in a BroadcastReceiver, you might want to use it in an Activity or a Service for the most part. You can use the getApplicationContext() method.

publicclassMyReceiverextendsBroadcastReceiver{ @Override publicvoidonReceive(Contextcontext,Intentintent){ ApplicationmyApp=(Application)context.getApplicationContext(); }}Copy the code

Memory leaks caused by Context

Context should not be used arbitrarily, and may cause memory leaks. Here are two examples of incorrect references.

Wrong singleton pattern

public class Singleton { private static Singleton instance; private Context mContext; private Singleton(Context context) { this.mContext = context; } public static Singleton getInstance(Context context) { if (instance == null) { instance = new Singleton(context); } return instance; }}Copy the code

This is A non-thread-safe singleton pattern. Instance, as A static object, has A longer lifetime than A normal object, which also contains an Activity, so if an Activity A goes to getInstance and gets the instance object, pass this, The in-memory Singleton holds the Activity A object you pass in and holds it even if the Activity is destroyed, but because its reference is still in A Singleton, it cannot be GC removed, resulting in A memory leak.

The View holds the Activity reference

public class MainActivity extends Activity { private static Drawable mDrawable; @Override protected void onCreate(Bundle saveInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.activity_main); ImageView iv = new ImageView(this); mDrawable = getResources().getDrawable(R.drawable.ic_launcher); iv.setImageDrawable(mDrawable); }}Copy the code

There’s a static Drawable object and when the ImageView sets the Drawable, the ImageView saves a reference to the mDrawable, and the this that the ImageView passes in is the mContext of the MainActivity, Because static mDrawable is resident in memory and MainActivity is an indirect reference to it, MainActivity cannot be GC removed when it is destroyed, causing a memory leak.

Use Context correctly

The memory leak caused by the Context is almost always when the Context is destroyed, but the destruction fails because it is referenced. The Application Context object can be understood as existing with the process. Therefore, we have concluded the correct position of using the Context: 1: The Application Context is used preferentially when the Application Context can be handled and the object has a long lifetime. 2: Do not allow objects with a lifetime longer than the Activity to hold references to the Activity. 3: Try not to use a non-static inner class in an Activity, because a non-static inner class implicitly holds a reference to an external class instance. If you use a static inner class, the external instance reference is held as a weak reference.

conclusion

【Android detailed Knowledge points mind map (skill tree) 】

In fact, there are so many knowledge points about Android development, and the interview questions are still a little bit of stuff. So there are no other tips for interviews, just how prepared you are for them. So, when you go out for the interview, find out where you are in your revision.

While Android isn’t as hot as it was a few years ago, the days when you could get a high-paying job with just four components are over. This only shows that the positions below the intermediate level of Android are saturated, and there is still a shortage of senior engineers. Many senior positions offer really high salaries (more money may not be able to find suitable ones), so it is most important to strive to become a senior engineer.