Analysis of Android's Context

Welcome to my personal website: https://coderyuan.com

Context is a concept that is used a lot in Android App, and it is often translated into context. This concept is also used in other technologies. If you accidentally click on the source code of Context, then let’s analyze and analyze Context in Android. What is it?

Paste the code first

/**
 * 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 {

It can be seen from the comments that the official Android interpretation of it can be roughly understood as an interface for global information in the application environment . It integrates many system-level services, which can be used to obtain classes and resources in applications, and can be used for applications. Program-level call-up operations, such as starting Activity, Service, etc., and the Context class is abstract and does not contain specific function implementations.

That means that you can do a lot of things, anyway, it's very arrogant. . .

So I searched for the reference of Context, no more.

Context reference

Structural Analysis

The Context class contains two types of content: constants , abstract method definitions

Since Context itself is abstract, it is only responsible for defining the required operations, and it does not care about the specific implementation. Although the ContextWrapper that directly inherits from Context is not modified with abstract, it does not do the actual implementation, but just does a simple The packaging for better presentation to classes such as Application and Service. What we can see is the first layer of Context implementation, which should be ContextImpl located under the android.app package

Context inheritance relationship

So first analyze the member variables in ContextImpl (including static, final, public, private), the following source code is all the member variables of ContextImpl:

    // ContextImpl.java

    /**
     * Map from package name, to preference name, to cached preferences.
     */
    @GuardedBy("ContextImpl.class")
    private static ArrayMap<String, ArrayMap<File, SharedPreferencesImpl>> sSharedPrefsCache;

    /**
     * Map from preference name to generated path.
     */
    @GuardedBy("ContextImpl.class")
    private ArrayMap<String, File> mSharedPrefsPaths;

    final @NonNull ActivityThread mMainThread;
    final @NonNull LoadedApk mPackageInfo;
    private @Nullable ClassLoader mClassLoader;

    private final @Nullable IBinder mActivityToken;

    private final @Nullable UserHandle mUser;

    private final ApplicationContentResolver mContentResolver;

    private final String mBasePackageName;
    private final String mOpPackageName;

    private final @NonNull ResourcesManager mResourcesManager;
    private @NonNull Resources mResources;
    private @Nullable Display mDisplay; // may be null if default display

    private final int mFlags;

    private Context mOuterContext;
    private int mThemeResource = 0;
    private Resources.Theme mTheme = null;
    private PackageManager mPackageManager;
    private Context mReceiverRestrictedContext = null;

    // The name of the split this Context is representing. May be null.
    private @Nullable String mSplitName = null;

    private final Object mSync = new Object();

    @GuardedBy("mSync")
    private File mDatabasesDir;
    @GuardedBy("mSync")
    private File mPreferencesDir;
    @GuardedBy("mSync")
    private File mFilesDir;
    @GuardedBy("mSync")
    private File mNoBackupFilesDir;
    @GuardedBy("mSync")
    private File mCacheDir;
    @GuardedBy("mSync")
    private File mCodeCacheDir;

    // The system service cache for the system services that are cached per-ContextImpl.
    final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();

According to its name and type, the basic role can be analyzed:

sSharedPrefsCache : Cache information for managing SharedPreference

mSharedPrefsPaths : used to save SharedPreference file storage paths

mMainThread : The main thread used to operate components such as Activity

mPackageInfo : PackageInfo of the currently loaded APK, including package name, version number, etc.

mClassLoader : The class loader used to load Dex classes, similar to the ClassLoader in other Java projects, it will be used when doing plug-in in Android

mActivityToken : a Binder that can be used for IPC communication

mUser : used to manage user data, used with ContentResovler

mContentResolver : Application-level ContentResolver for data exchange between different processes

mBasePackageName : base package name

mOpPackageName : It seems to be another package name. . .

mResourcesManager : System resource service, which can be used to obtain resources such as pictures and strings, and is used a lot

mResources : System resources, such as themes, color definitions, etc.

mDisplay : System monitor/screen information, such as getting resolution, PPI

mFlags : Flag bit, used to distinguish the category of Context

mOuterContext : Context used externally

mThemeResource : Theme resource Id

mTheme : The theme used by the APP

mPackageManager : Package manager, which can be used to obtain information about the installed APP

mReceiverRestrictedContext : should be the Context used for BroadcastReceiver

mSplitName : It is speculated that it is also used to distinguish Context

mSync : used to set the synchronization function to ensure the thread safety of file operations

mDatabasesDir : Directory path to store database files

mPreferencesDir : Directory path to store SharedPreference files

mFilesDir : directory path for storing general files

mNoBackupFilesDir : Directory path to store files not used for automatic backups

mCacheDir : Directory path to store cache files

mCodeCacheDir : The directory path to store code cache files (mainly used to load Dex)

Among them, the @GuardedBy annotation is used to deal with multi-threaded protection issues, to indicate which object is protected by a synchronization lock in a multi-threaded environment

After analyzing the use of the above member variables, the basic responsibilities of ContextImpl are also clarified. The remaining member methods and static methods are all operations based on these members, that is, some operations that we are familiar with Context can perform, such as: startActivity, startService, getExternalCacheDir, getDatabasesDir, getMainLooper, getResources, getTheme, checkPermission, etc.

However, in addition to these member methods, there are several static methods that are important:

createSystemContext、createSystemUiContext、createAppContext、createActivityContext

Although I haven't seen any direct references to these methods, take the Activity startup process as an example. ActivityManagerService (AMS) uses the zygote process to start an ActivityThread first. When attaching, it will call the static method of ContextImpl to create all The required Context is also the same for the Context in other components such as Application and Service. Therefore, the various Contexts we use in the App are actually created by ContextImpl in the final analysis, which shows the importance of ContextImpl!

Context memory leak

As we all know, memory leaks in Android are caused by Context in many cases. According to the above analysis of its structure and use, the following reasons can be inferred:

  1. Involving various systems and APP resources, the function is too powerful, resulting in too many places of use, causing confusion in the process and reference relationship, such as: asynchronous network requests, View animations, etc., are not handled properly in the process, resulting in failure to release

  2. Disorganized value transfer makes many objects hold a Context, which opens up too many resources that cannot be recycled

  3. Drawable objects and Bitmap objects are not recycled in a timely manner, and even bound to View

  4. The abuse of singleton causes Context to be referenced for a long time and cannot be released

solution:

  1. When there is no need to pass values, try to use the Context of the Application, so as to ensure that the Context can be used globally without creating multiple copies.

  2. In the case of coupling with components such as Activity, when it is necessary to use the Context of the Activity, consider using weak references to avoid cyclically holding the Context

Summarize

In general, Context in Android is the encapsulation of a series of system service interfaces, including: management of internal resources, packages, class loading, I/O operations, permissions, main threads, IPC, and component startup. Its structure is relatively simple, but there are many methods and operations involved. When using it, special attention should be paid to memory leaks and multi-threading problems to avoid conflicts or serious bugs.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324696076&siteId=291194637