Context在Android应用开发中占据了绝对重要的地位,不管是Framework提供给我们的四大组件还是应用级别的Application,还是负责View展现层的View相关类,甚至连我们很多时候创建的实体类都会需要一个Context的引用,在Android Framework中,Context贯穿了整个Android MVC框架,它的应用很普遍。尽管如此,Context本质上还是一个普通的抽象类,我们在上面的装饰模式中提到Context类中的startActivity方法,实质上除了startActivity方法,Context还定义了大量相当牛的方法,这些方法不但与我们上面提到的四大组件密切相关,还与资源文件、文件管理、包管理、类加载、权限管理、系统服务获取等各式各样的功能相切合。

/*** 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 {/*** Same as {@link #startActivity(Intent, Bundle)} with no options* specified.** @param intent The description of the activity to start.** @throws ActivityNotFoundException &nbsp;*`* @see #startActivity(Intent, Bundle)* @see PackageManager#resolveActivity*///启动一个Activitypublic abstract void startActivity(@RequiresPermission Intent intent);/*** Same as {@link #startActivity(Intent, Bundle)} with no options* specified.** @param intent The description of the activity to start.** @throws ActivityNotFoundException &nbsp;*`* @see #startActivity(Intent, Bundle)* @see PackageManager#resolveActivity*///启动一个Activitypublic abstract void startActivity(@RequiresPermission Intent intent);/*** Same as {@link #startActivities(Intent[], Bundle)} with no options* specified.** @param intents An array of Intents to be started.** @throws ActivityNotFoundException &nbsp;** @see #startActivities(Intent[], Bundle)* @see PackageManager#resolveActivity*///启动多个Activitypublic abstract void startActivities(@RequiresPermission Intent[] intents);/*** Launch multiple new activities.  This is generally the same as calling* {@link #startActivity(Intent)} for the first Intent in the array,* that activity during its creation calling {@link #startActivity(Intent)}* for the second entry, etc.  Note that unlike that approach, generally* none of the activities except the last in the array will be created* at this point, but rather will be created when the user first visits* them (due to pressing back from the activity on top).** <p>This method throws {@link ActivityNotFoundException}* if there was no Activity found for <em>any</em> given Intent.  In this* case the state of the activity stack is undefined (some Intents in the* list may be on it, some not), so you probably want to avoid such situations.** @param intents An array of Intents to be started.* @param options Additional options for how the Activity should be started.* See {@link android.content.Context#startActivity(Intent, Bundle)}* Context.startActivity(Intent, Bundle)} for more details.** @throws ActivityNotFoundException &nbsp;** @see #startActivities(Intent[])* @see PackageManager#resolveActivity*///启动多个Activitypublic abstract void startActivities(@RequiresPermission Intent[] intents, Bundle options);/** Return the full application info for this context's package. *///获取应用程序信息public abstract ApplicationInfo getApplicationInfo();/*** Request that a given application service be started.  The Intent* should either contain the complete class name of a specific service* implementation to start, or a specific package name to target.  If the* Intent is less specified, it logs a warning about this.  In this case any of the* multiple matching services may be used.  If this service* is not already running, it will be instantiated and started (creating a* process for it if needed); if it is running then it remains running.** <p>Every call to this method will result in a corresponding call to* the target service's {@link android.app.Service#onStartCommand} method,* with the <var>intent</var> given here.  This provides a convenient way* to submit jobs to a service without having to bind and call on to its* interface.** <p>Using startService() overrides the default service lifetime that is* managed by {@link #bindService}: it requires the service to remain* running until {@link #stopService} is called, regardless of whether* any clients are connected to it.  Note that calls to startService()* do not nest: no matter how many times you call startService(),* a single call to {@link #stopService} will stop it.** <p>The system attempts to keep running services around as much as* possible.  The only time they should be stopped is if the current* foreground application is using so many resources that the service needs* to be killed.  If any errors happen in the service's process, it will* automatically be restarted.** <p>This function will throw {@link SecurityException} if you do not* have permission to start the given service.** <p class="note"><strong>Note:</strong> Each call to startService()* results in significant work done by the system to manage service* lifecycle surrounding the processing of the intent, which can take* multiple milliseconds of CPU time. Due to this cost, startService()* should not be used for frequent intent delivery to a service, and only* for scheduling significant work. Use {@link #bindService bound services}* for high frequency calls.* </p>** @param service Identifies the service to be started.  The Intent must be*      fully explicit (supplying a component name).  Additional values*      may be included in the Intent extras to supply arguments along with*      this specific start call.** @return If the service is being started or is already running, the* {@link ComponentName} of the actual service that was started is* returned; else if the service does not exist null is returned.** @throws SecurityException If the caller does not have permission to access the service* or the service can not be found.* @throws IllegalStateException If the application is in a state where the service* can not be started (such as not in the foreground in a state when services are allowed).** @see #stopService* @see #bindService*///启动一个Service@Nullablepublic abstract ComponentName startService(Intent service);/*** Request that a given application service be stopped.  If the service is* not running, nothing happens.  Otherwise it is stopped.  Note that calls* to startService() are not counted -- this stops the service no matter* how many times it was started.** <p>Note that if a stopped service still has {@link ServiceConnection}* objects bound to it with the {@link #BIND_AUTO_CREATE} set, it will* not be destroyed until all of these bindings are removed.  See* the {@link android.app.Service} documentation for more details on a* service's lifecycle.** <p>This function will throw {@link SecurityException} if you do not* have permission to stop the given service.** @param service Description of the service to be stopped.  The Intent must be either*      fully explicit (supplying a component name) or specify a specific package*      name it is targetted to.** @return If there is a service matching the given Intent that is already* running, then it is stopped and {@code true} is returned; else {@code false} is returned.** @throws SecurityException If the caller does not have permission to access the service* or the service can not be found.* @throws IllegalStateException If the application is in a state where the service* can not be started (such as not in the foreground in a state when services are allowed).** @see #startService*///停止一个Servicepublic abstract boolean stopService(Intent service);/*** Connect to an application service, creating it if needed.  This defines* a dependency between your application and the service.  The given* <var>conn</var> will receive the service object when it is created and be* told if it dies and restarts.  The service will be considered required* by the system only for as long as the calling context exists.  For* example, if this Context is an Activity that is stopped, the service will* not be required to continue running until the Activity is resumed.** <p>This function will throw {@link SecurityException} if you do not* have permission to bind to the given service.** <p class="note">Note: this method <em>can not be called from a* {@link BroadcastReceiver} component</em>.  A pattern you can use to* communicate from a BroadcastReceiver to a Service is to call* {@link #startService} with the arguments containing the command to be* sent, with the service calling its* {@link android.app.Service#stopSelf(int)} method when done executing* that command.  See the API demo App/Service/Service Start Arguments* Controller for an illustration of this.  It is okay, however, to use* this method from a BroadcastReceiver that has been registered with* {@link #registerReceiver}, since the lifetime of this BroadcastReceiver* is tied to another object (the one that registered it).</p>** @param service Identifies the service to connect to.  The Intent must*      specify an explicit component name.* @param conn Receives information as the service is started and stopped.*      This must be a valid ServiceConnection object; it must not be null.* @param flags Operation options for the binding.  May be 0,*          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},*          {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},*          {@link #BIND_ALLOW_OOM_MANAGEMENT}, or*          {@link #BIND_WAIVE_PRIORITY}.* @return If you have successfully bound to the service, {@code true} is returned;*         {@code false} is returned if the connection is not made so you will not*         receive the service object. However, you should still call*         {@link #unbindService} to release the connection.** @throws SecurityException If the caller does not have permission to access the service* or the service can not be found.** @see #unbindService* @see #startService* @see #BIND_AUTO_CREATE* @see #BIND_DEBUG_UNBIND* @see #BIND_NOT_FOREGROUND*///绑定一个Service到Activitypublic abstract boolean bindService(@RequiresPermission Intent service,@NonNull ServiceConnection conn, @BindServiceFlags int flags);/*** Disconnect from an application service.  You will no longer receive* calls as the service is restarted, and the service is now allowed to* stop at any time.** @param conn The connection interface previously supplied to*             bindService().  This parameter must not be null.** @see #bindService*/
//解绑一个Service到Activitypublic abstract void unbindService(@NonNull ServiceConnection conn);/*** Broadcast the given intent to all interested BroadcastReceivers.  This* call is asynchronous; it returns immediately, and you will continue* executing while the receivers are run.  No results are propagated from* receivers and receivers can not abort the broadcast. If you want* to allow receivers to propagate results or abort the broadcast, you must* send an ordered broadcast using* {@link #sendOrderedBroadcast(Intent, String)}.** <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.** @param intent The Intent to broadcast; all receivers matching this*               Intent will receive the broadcast.** @see android.content.BroadcastReceiver* @see #registerReceiver* @see #sendBroadcast(Intent, String)* @see #sendOrderedBroadcast(Intent, String)* @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)*///发送一个广播public abstract void sendBroadcast(@RequiresPermission Intent intent);/*** Broadcast the given intent to all interested BroadcastReceivers, allowing* an optional required permission to be enforced.  This* call is asynchronous; it returns immediately, and you will continue* executing while the receivers are run.  No results are propagated from* receivers and receivers can not abort the broadcast. If you want* to allow receivers to propagate results or abort the broadcast, you must* send an ordered broadcast using* {@link #sendOrderedBroadcast(Intent, String)}.** <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.** @param intent The Intent to broadcast; all receivers matching this*               Intent will receive the broadcast.* @param receiverPermission (optional) String naming a permission that*               a receiver must hold in order to receive your broadcast.*               If null, no permission is required.** @see android.content.BroadcastReceiver* @see #registerReceiver* @see #sendBroadcast(Intent)* @see #sendOrderedBroadcast(Intent, String)* @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)*///发送一个广播public abstract void sendBroadcast(@RequiresPermission Intent intent,@Nullable String receiverPermission);/*** Like {@link #sendBroadcast(Intent, String)}, but also allows specification* of an associated app op as per {@link android.app.AppOpsManager}.* @hide*/public abstract void sendBroadcast(Intent intent,String receiverPermission, int appOp);/*** Broadcast the given intent to all interested BroadcastReceivers, delivering* them one at a time to allow more preferred receivers to consume the* broadcast before it is delivered to less preferred receivers.  This* call is asynchronous; it returns immediately, and you will continue* executing while the receivers are run.** <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.** @param intent The Intent to broadcast; all receivers matching this*               Intent will receive the broadcast.* @param receiverPermission (optional) String naming a permissions that*               a receiver must hold in order to receive your broadcast.*               If null, no permission is required.** @see android.content.BroadcastReceiver* @see #registerReceiver* @see #sendBroadcast(Intent)* @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)*///发送一个有序广播public abstract void sendOrderedBroadcast(@RequiresPermission Intent intent,@Nullable String receiverPermission);/*** Version of {@link #sendBroadcast(Intent)} that allows you to* receive data back from the broadcast.  This is accomplished by* supplying your own BroadcastReceiver when calling, which will be* treated as a final receiver at the end of the broadcast -- its* {@link BroadcastReceiver#onReceive} method will be called with* the result values collected from the other receivers.  The broadcast will* be serialized in the same way as calling* {@link #sendOrderedBroadcast(Intent, String)}.** <p>Like {@link #sendBroadcast(Intent)}, this method is* asynchronous; it will return before* resultReceiver.onReceive() is called.** <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.** @param intent The Intent to broadcast; all receivers matching this*               Intent will receive the broadcast.* @param receiverPermission String naming a permissions that*               a receiver must hold in order to receive your broadcast.*               If null, no permission is required.* @param resultReceiver Your own BroadcastReceiver to treat as the final*                       receiver of the broadcast.* @param scheduler A custom Handler with which to schedule the*                  resultReceiver callback; if null it will be*                  scheduled in the Context's main thread.* @param initialCode An initial value for the result code.  Often*                    Activity.RESULT_OK.* @param initialData An initial value for the result data.  Often*                    null.* @param initialExtras An initial value for the result extras.  Often*                      null.** @see #sendBroadcast(Intent)* @see #sendBroadcast(Intent, String)* @see #sendOrderedBroadcast(Intent, String)* @see android.content.BroadcastReceiver* @see #registerReceiver* @see android.app.Activity#RESULT_OK*///发送一个有序广播public abstract void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent,@Nullable String receiverPermission, @Nullable BroadcastReceiver resultReceiver,@Nullable Handler scheduler, int initialCode, @Nullable String initialData,@Nullable Bundle initialExtras);/*** <p>Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the* Intent you are sending stays around after the broadcast is complete,* so that others can quickly retrieve that data through the return* value of {@link #registerReceiver(BroadcastReceiver, IntentFilter)}.  In* all other ways, this behaves the same as* {@link #sendBroadcast(Intent)}.** @deprecated Sticky broadcasts should not be used.  They provide no security (anyone* can access them), no protection (anyone can modify them), and many other problems.* The recommended pattern is to use a non-sticky broadcast to report that <em>something</em>* has changed, with another mechanism for apps to retrieve the current value whenever* desired.** @param intent The Intent to broadcast; all receivers matching this* Intent will receive the broadcast, and the Intent will be held to* be re-broadcast to future receivers.** @see #sendBroadcast(Intent)* @see #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)*///发送一个会滞留的广播@Deprecated@RequiresPermission(android.Manifest.permission.BROADCAST_STICKY)public abstract void sendStickyBroadcast(@RequiresPermission Intent intent);/*** <p>Version of {@link #sendStickyBroadcast} that allows you to* receive data back from the broadcast.  This is accomplished by* supplying your own BroadcastReceiver when calling, which will be* treated as a final receiver at the end of the broadcast -- its* {@link BroadcastReceiver#onReceive} method will be called with* the result values collected from the other receivers.  The broadcast will* be serialized in the same way as calling* {@link #sendOrderedBroadcast(Intent, String)}.** <p>Like {@link #sendBroadcast(Intent)}, this method is* asynchronous; it will return before* resultReceiver.onReceive() is called.  Note that the sticky data* stored is only the data you initially supply to the broadcast, not* the result of any changes made by the receivers.** <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.** @deprecated Sticky broadcasts should not be used.  They provide no security (anyone* can access them), no protection (anyone can modify them), and many other problems.* The recommended pattern is to use a non-sticky broadcast to report that <em>something</em>* has changed, with another mechanism for apps to retrieve the current value whenever* desired.** @param intent The Intent to broadcast; all receivers matching this*               Intent will receive the broadcast.* @param resultReceiver Your own BroadcastReceiver to treat as the final*                       receiver of the broadcast.* @param scheduler A custom Handler with which to schedule the*                  resultReceiver callback; if null it will be*                  scheduled in the Context's main thread.* @param initialCode An initial value for the result code.  Often*                    Activity.RESULT_OK.* @param initialData An initial value for the result data.  Often*                    null.* @param initialExtras An initial value for the result extras.  Often*                      null.** @see #sendBroadcast(Intent)* @see #sendBroadcast(Intent, String)* @see #sendOrderedBroadcast(Intent, String)* @see #sendStickyBroadcast(Intent)* @see android.content.BroadcastReceiver* @see #registerReceiver* @see android.app.Activity#RESULT_OK*///发送一个会滞留的广播@Deprecated@RequiresPermission(android.Manifest.permission.BROADCAST_STICKY)public abstract void sendStickyOrderedBroadcast(@RequiresPermission Intent intent,BroadcastReceiver resultReceiver,@Nullable Handler scheduler, int initialCode, @Nullable String initialData,@Nullable Bundle initialExtras);/*** Register a BroadcastReceiver to be run in the main activity thread.  The* <var>receiver</var> will be called with any broadcast Intent that* matches <var>filter</var>, in the main application thread.** <p>The system may broadcast Intents that are "sticky" -- these stay* around after the broadcast has finished, to be sent to any later* registrations. If your IntentFilter matches one of these sticky* Intents, that Intent will be returned by this function* <strong>and</strong> sent to your <var>receiver</var> as if it had just* been broadcast.** <p>There may be multiple sticky Intents that match <var>filter</var>,* in which case each of these will be sent to <var>receiver</var>.  In* this case, only one of these can be returned directly by the function;* which of these that is returned is arbitrarily decided by the system.** <p>If you know the Intent your are registering for is sticky, you can* supply null for your <var>receiver</var>.  In this case, no receiver is* registered -- the function simply returns the sticky Intent that* matches <var>filter</var>.  In the case of multiple matches, the same* rules as described above apply.** <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.** <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers* registered with this method will correctly respect the* {@link Intent#setPackage(String)} specified for an Intent being broadcast.* Prior to that, it would be ignored and delivered to all matching registered* receivers.  Be careful if using this for security.</p>** <p class="note">Note: this method <em>cannot be called from a* {@link BroadcastReceiver} component;</em> that is, from a BroadcastReceiver* that is declared in an application's manifest.  It is okay, however, to call* this method from another BroadcastReceiver that has itself been registered* at run time with {@link #registerReceiver}, since the lifetime of such a* registered BroadcastReceiver is tied to the object that registered it.</p>** @param receiver The BroadcastReceiver to handle the broadcast.* @param filter Selects the Intent broadcasts to be received.** @return The first sticky intent found that matches <var>filter</var>,*         or null if there are none.** @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)* @see #sendBroadcast* @see #unregisterReceiver*///注册一个广播接收者@Nullablepublic abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,IntentFilter filter);/*** Register to receive intent broadcasts, to run in the context of* <var>scheduler</var>.  See* {@link #registerReceiver(BroadcastReceiver, IntentFilter)} for more* information.  This allows you to enforce permissions on who can* broadcast intents to your receiver, or have the receiver run in* a different thread than the main application thread.** <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.** <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers* registered with this method will correctly respect the* {@link Intent#setPackage(String)} specified for an Intent being broadcast.* Prior to that, it would be ignored and delivered to all matching registered* receivers.  Be careful if using this for security.</p>** @param receiver The BroadcastReceiver to handle the broadcast.* @param filter Selects the Intent broadcasts to be received.* @param broadcastPermission String naming a permissions that a*      broadcaster must hold in order to send an Intent to you.  If null,*      no permission is required.* @param scheduler Handler identifying the thread that will receive*      the Intent.  If null, the main thread of the process will be used.** @return The first sticky intent found that matches <var>filter</var>,*         or null if there are none.** @see #registerReceiver(BroadcastReceiver, IntentFilter)* @see #sendBroadcast* @see #unregisterReceiver*/
//注册一个广播接收者@Nullablepublic abstract Intent registerReceiver(BroadcastReceiver receiver,IntentFilter filter, @Nullable String broadcastPermission,@Nullable Handler scheduler);/*** Unregister a previously registered BroadcastReceiver.  <em>All</em>* filters that have been registered for this BroadcastReceiver will be* removed.** @param receiver The BroadcastReceiver to unregister.** @see #registerReceiver*///取消注册一个广播接收者public abstract void unregisterReceiver(BroadcastReceiver receiver);/** Return a ContentResolver instance for your application's package. *///获取一个ContentResolver对象public abstract ContentResolver getContentResolver();/*** Return the Looper for the main thread of the current process.  This is* the thread used to dispatch calls to application components (activities,* services, etc).* <p>* By definition, this method returns the same result as would be obtained* by calling {@link Looper#getMainLooper() Looper.getMainLooper()}.* </p>** @return The main looper.*/// 获取主线程中的looperpublic abstract Looper getMainLooper();/*** Return the context of the single, global Application object of the* current process.  This generally should only be used if you need a* Context whose lifecycle is separate from the current context, that is* tied to the lifetime of the process rather than the current component.** <p>Consider for example how this interacts with* {@link #registerReceiver(BroadcastReceiver, IntentFilter)}:* <ul>* <li> <p>If used from an Activity context, the receiver is being registered* within that activity.  This means that you are expected to unregister* before the activity is done being destroyed; in fact if you do not do* so, the framework will clean up your leaked registration as it removes* the activity and log an error.  Thus, if you use the Activity context* to register a receiver that is static (global to the process, not* associated with an Activity instance) then that registration will be* removed on you at whatever point the activity you used is destroyed.* <li> <p>If used from the Context returned here, the receiver is being* registered with the global state associated with your application.  Thus* it will never be unregistered for you.  This is necessary if the receiver* is associated with static data, not a particular component.  However* using the ApplicationContext elsewhere can easily lead to serious leaks* if you forget to unregister, unbind, etc.* </ul>*/// 获取应用级别的Context对象public abstract Context getApplicationContext();/*** Return the handle to a system-level service by name. The class of the* returned object varies by the requested name. Currently available names* are:** <dl>*  <dt> {@link #WINDOW_SERVICE} ("window")*  <dd> The top-level window manager in which you can place custom*  windows.  The returned object is a {@link android.view.WindowManager}.*  <dt> {@link #LAYOUT_INFLATER_SERVICE} ("layout_inflater")*  <dd> A {@link android.view.LayoutInflater} for inflating layout resources*  in this context.*  <dt> {@link #ACTIVITY_SERVICE} ("activity")*  <dd> A {@link android.app.ActivityManager} for interacting with the*  global activity state of the system.*  <dt> {@link #POWER_SERVICE} ("power")*  <dd> A {@link android.os.PowerManager} for controlling power*  management.*  <dt> {@link #ALARM_SERVICE} ("alarm")*  <dd> A {@link android.app.AlarmManager} for receiving intents at the*  time of your choosing.*  <dt> {@link #NOTIFICATION_SERVICE} ("notification")*  <dd> A {@link android.app.NotificationManager} for informing the user*   of background events.*  <dt> {@link #KEYGUARD_SERVICE} ("keyguard")*  <dd> A {@link android.app.KeyguardManager} for controlling keyguard.*  <dt> {@link #LOCATION_SERVICE} ("location")*  <dd> A {@link android.location.LocationManager} for controlling location*   (e.g., GPS) updates.*  <dt> {@link #SEARCH_SERVICE} ("search")*  <dd> A {@link android.app.SearchManager} for handling search.*  <dt> {@link #VIBRATOR_SERVICE} ("vibrator")*  <dd> A {@link android.os.Vibrator} for interacting with the vibrator*  hardware.*  <dt> {@link #CONNECTIVITY_SERVICE} ("connection")*  <dd> A {@link android.net.ConnectivityManager ConnectivityManager} for*  handling management of network connections.*  <dt> {@link #WIFI_SERVICE} ("wifi")*  <dd> A {@link android.net.wifi.WifiManager WifiManager} for management of Wi-Fi*  connectivity.  On releases before NYC, it should only be obtained from an application*  context, and not from any other derived context to avoid memory leaks within the calling*  process.*  <dt> {@link #WIFI_AWARE_SERVICE} ("wifiaware")*  <dd> A {@link android.net.wifi.aware.WifiAwareManager WifiAwareManager} for management of* Wi-Fi Aware discovery and connectivity.*  <dt> {@link #WIFI_P2P_SERVICE} ("wifip2p")*  <dd> A {@link android.net.wifi.p2p.WifiP2pManager WifiP2pManager} for management of* Wi-Fi Direct connectivity.* <dt> {@link #INPUT_METHOD_SERVICE} ("input_method")* <dd> An {@link android.view.inputmethod.InputMethodManager InputMethodManager}* for management of input methods.* <dt> {@link #UI_MODE_SERVICE} ("uimode")* <dd> An {@link android.app.UiModeManager} for controlling UI modes.* <dt> {@link #DOWNLOAD_SERVICE} ("download")* <dd> A {@link android.app.DownloadManager} for requesting HTTP downloads* <dt> {@link #BATTERY_SERVICE} ("batterymanager")* <dd> A {@link android.os.BatteryManager} for managing battery state* <dt> {@link #JOB_SCHEDULER_SERVICE} ("taskmanager")* <dd>  A {@link android.app.job.JobScheduler} for managing scheduled tasks* <dt> {@link #NETWORK_STATS_SERVICE} ("netstats")* <dd> A {@link android.app.usage.NetworkStatsManager NetworkStatsManager} for querying network* usage statistics.* <dt> {@link #HARDWARE_PROPERTIES_SERVICE} ("hardware_properties")* <dd> A {@link android.os.HardwarePropertiesManager} for accessing hardware properties.* </dl>** <p>Note:  System services obtained via this API may be closely associated with* the Context in which they are obtained from.  In general, do not share the* service objects between various different contexts (Activities, Applications,* Services, Providers, etc.)** @param name The name of the desired service.** @return The service or null if the name does not exist.** @see #WINDOW_SERVICE* @see android.view.WindowManager* @see #LAYOUT_INFLATER_SERVICE* @see android.view.LayoutInflater* @see #ACTIVITY_SERVICE* @see android.app.ActivityManager* @see #POWER_SERVICE* @see android.os.PowerManager* @see #ALARM_SERVICE* @see android.app.AlarmManager* @see #NOTIFICATION_SERVICE* @see android.app.NotificationManager* @see #KEYGUARD_SERVICE* @see android.app.KeyguardManager* @see #LOCATION_SERVICE* @see android.location.LocationManager* @see #SEARCH_SERVICE* @see android.app.SearchManager* @see #SENSOR_SERVICE* @see android.hardware.SensorManager* @see #STORAGE_SERVICE* @see android.os.storage.StorageManager* @see #VIBRATOR_SERVICE* @see android.os.Vibrator* @see #CONNECTIVITY_SERVICE* @see android.net.ConnectivityManager* @see #WIFI_SERVICE* @see android.net.wifi.WifiManager* @see #AUDIO_SERVICE* @see android.media.AudioManager* @see #MEDIA_ROUTER_SERVICE* @see android.media.MediaRouter* @see #TELEPHONY_SERVICE* @see android.telephony.TelephonyManager* @see #TELEPHONY_SUBSCRIPTION_SERVICE* @see android.telephony.SubscriptionManager* @see #CARRIER_CONFIG_SERVICE* @see android.telephony.CarrierConfigManager* @see #INPUT_METHOD_SERVICE* @see android.view.inputmethod.InputMethodManager* @see #UI_MODE_SERVICE* @see android.app.UiModeManager* @see #DOWNLOAD_SERVICE* @see android.app.DownloadManager* @see #BATTERY_SERVICE* @see android.os.BatteryManager* @see #JOB_SCHEDULER_SERVICE* @see android.app.job.JobScheduler* @see #NETWORK_STATS_SERVICE* @see android.app.usage.NetworkStatsManager* @see android.os.HardwarePropertiesManager* @see #HARDWARE_PROPERTIES_SERVICE*///获取应用的系统服务
public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);/*** Returns a Resources instance for the application's package.* <p>* <strong>Note:</strong> Implementations of this method should return* a Resources instance that is consistent with the AssetManager instance* returned by {@link #getAssets()}. For example, they should share the* same {@link Configuration} object.** @return a Resources instance for the application's package* @see #getAssets()*///获取Resource对象处理资源文件public abstract Resources getResources();/*** Retrieve and hold the contents of the preferences file 'name', returning* a SharedPreferences through which you can retrieve and modify its* values.  Only one instance of the SharedPreferences object is returned* to any callers for the same name, meaning they will see each other's* edits as soon as they are made.** @param name Desired preferences file. If a preferences file by this name* does not exist, it will be created when you retrieve an* editor (SharedPreferences.edit()) and then commit changes (Editor.commit()).* @param mode Operating mode.** @return The single {@link SharedPreferences} instance that can be used*         to retrieve and modify the preference values.** @see #MODE_PRIVATE*///获取SharedPreferences对象public abstract SharedPreferences getSharedPreferences(String name, @PreferencesMode int mode);/*** Returns the absolute path to the directory on the primary shared/external* storage device where the application can place persistent files it owns.* These files are internal to the applications, and not typically visible* to the user as media.* <p>* This is like {@link #getFilesDir()} in that these files will be deleted* when the application is uninstalled, however there are some important* differences:* <ul>* <li>Shared storage may not always be available, since removable media can* be ejected by the user. Media state can be checked using* {@link Environment#getExternalStorageState(File)}.* <li>There is no security enforced with these files. For example, any* application holding* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to* these files.* </ul>* <p>* If a shared storage device is emulated (as determined by* {@link Environment#isExternalStorageEmulated(File)}), it's contents are* backed by a private user data partition, which means there is little* benefit to storing data here instead of the private directories returned* by {@link #getFilesDir()}, etc.* <p>* Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions* are required to read or write to the returned path; it's always* accessible to the calling app. This only applies to paths generated for* package name of the calling application. To access paths belonging to* other packages,* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or* {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.* <p>* On devices with multiple users (as described by {@link UserManager}),* each user has their own isolated shared storage. Applications only have* access to the shared storage for the user they're running as.* <p>* The returned path may change over time if different shared storage media* is inserted, so only relative paths should be persisted.* <p>* Here is an example of typical code to manipulate a file in an* application's shared storage:* </p>* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java* private_file}* <p>* If you supply a non-null <var>type</var> to this function, the returned* file will be a path to a sub-directory of the given type. Though these* files are not automatically scanned by the media scanner, you can* explicitly add them to the media database with* {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[], android.media.MediaScannerConnection.OnScanCompletedListener)* MediaScannerConnection.scanFile}. Note that this is not the same as* {@link android.os.Environment#getExternalStoragePublicDirectory* Environment.getExternalStoragePublicDirectory()}, which provides* directories of media shared by all applications. The directories returned* here are owned by the application, and their contents will be removed* when the application is uninstalled. Unlike* {@link android.os.Environment#getExternalStoragePublicDirectory* Environment.getExternalStoragePublicDirectory()}, the directory returned* here will be automatically created for you.* <p>* Here is an example of typical code to manipulate a picture in an* application's shared storage and add it to the media database:* </p>* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java* private_picture}** @param type The type of files directory to return. May be {@code null}*            for the root of the files directory or one of the following*            constants for a subdirectory:*            {@link android.os.Environment#DIRECTORY_MUSIC},*            {@link android.os.Environment#DIRECTORY_PODCASTS},*            {@link android.os.Environment#DIRECTORY_RINGTONES},*            {@link android.os.Environment#DIRECTORY_ALARMS},*            {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},*            {@link android.os.Environment#DIRECTORY_PICTURES}, or*            {@link android.os.Environment#DIRECTORY_MOVIES}.* @return the absolute path to application-specific directory. May return*         {@code null} if shared storage is not currently available.* @see #getFilesDir* @see #getExternalFilesDirs(String)* @see Environment#getExternalStorageState(File)* @see Environment#isExternalStorageEmulated(File)* @see Environment#isExternalStorageRemovable(File)*/
//获取外部文件存储目录@Nullablepublic abstract File getExternalFilesDir(@Nullable String type);/*** Returns absolute paths to application-specific directories on all* shared/external storage devices where the application can place* persistent files it owns. These files are internal to the application,* and not typically visible to the user as media.* <p>* This is like {@link #getFilesDir()} in that these files will be deleted* when the application is uninstalled, however there are some important* differences:* <ul>* <li>Shared storage may not always be available, since removable media can* be ejected by the user. Media state can be checked using* {@link Environment#getExternalStorageState(File)}.* <li>There is no security enforced with these files. For example, any* application holding* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to* these files.* </ul>* <p>* If a shared storage device is emulated (as determined by* {@link Environment#isExternalStorageEmulated(File)}), it's contents are* backed by a private user data partition, which means there is little* benefit to storing data here instead of the private directories returned* by {@link #getFilesDir()}, etc.* <p>* Shared storage devices returned here are considered a stable part of the* device, including physical media slots under a protective cover. The* returned paths do not include transient devices, such as USB flash drives* connected to handheld devices.* <p>* An application may store data on any or all of the returned devices. For* example, an app may choose to store large files on the device with the* most available space, as measured by {@link StatFs}.* <p>* No additional permissions are required for the calling app to read or* write files under the returned path. Write access outside of these paths* on secondary external storage devices is not available.* <p>* The returned path may change over time if different shared storage media* is inserted, so only relative paths should be persisted.** @param type The type of files directory to return. May be {@code null}*            for the root of the files directory or one of the following*            constants for a subdirectory:*            {@link android.os.Environment#DIRECTORY_MUSIC},*            {@link android.os.Environment#DIRECTORY_PODCASTS},*            {@link android.os.Environment#DIRECTORY_RINGTONES},*            {@link android.os.Environment#DIRECTORY_ALARMS},*            {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},*            {@link android.os.Environment#DIRECTORY_PICTURES}, or*            {@link android.os.Environment#DIRECTORY_MOVIES}.* @return the absolute paths to application-specific directories. Some*         individual paths may be {@code null} if that shared storage is*         not currently available. The first path returned is the same as*         {@link #getExternalFilesDir(String)}.* @see #getExternalFilesDir(String)* @see Environment#getExternalStorageState(File)* @see Environment#isExternalStorageEmulated(File)* @see Environment#isExternalStorageRemovable(File)*///获取多个(如果有的话)外部文件存储目录public abstract File[] getExternalFilesDirs(String type);}

以上这些方法我们在开发中经常用到,当然这里仅仅是定义一个声明,如上面装饰模式源码分析所说,Context中方法的所有实现均由ContextImpl类承担,具体相关方法的实现这里就不再多说了。

Android应用开发中我们从来都是从一个Activity的onCreate方法开始的,从未接触过类似main一样的程序入口方法,但是main方法确实存在,在ActivityThread类中。

/*** This manages the execution of the main thread in an* application process, scheduling and executing activities,* broadcasts, and other operations on it as the activity* manager requests.** {@hide}*/
public final class ActivityThread {}public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// CloseGuard defaults to true and can be quite spammy.  We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.//暂时关闭CloseGuard检测,稍后会打开CloseGuard.setEnabled(false);//当前用户初始化环境参数Environment.initForCurrentUser();// Set the reporter for event logging in libcore//配置EventLoggerEventLogger.setReporter(new EventLoggingReporter());// Make sure TrustedCertificateStore looks in the right place for CA certificates//获取并确保信用凭证在目录中final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);
//设置启动标识值,标识主循环准备初始化Process.setArgV0("<pre-initialized>");//准备循环主线程(也就是当前线程)中的LooperLooper.prepareMainLooper();//构造ActivityThread对象并attachActivityThread thread = new ActivityThread();thread.attach(false);//获取主线程handlerif (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}//该代码用于调试if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);/// M: ANR Debug MechanismmAnrAppManager.setMessageLogger(Looper.myLooper());//调用Looper的loop方法使主线程中消息循环Looper.loop();//如果代码执行到这里说明主线程消息循环出现异常,这时则抛出异常终止系统运行throw new RuntimeException("Main thread loop unexpectedly exited");}

ActivityThread中的main方法逻辑并不多,大多复杂的逻辑被封装到了ActivityThread类中,而这里我们也主要只关注ActivityThread类,在上面的main方法中构造了一个ActivityThread对象,随后又为sMainThreadHandler这个handler引用赋值,sMainThreadHandler为ActivityThread的类变量,这里sMainThreadHandler指向的对象是由ActivityThread的getHandler方法获取,该方法只是单纯返回一个H类型的对象。

#ActivityThreadfinal H mH = new H();final Handler getHandler() {return mH;}

H是ActivityThread的一个私有内部类,继承于Handler,其作用很简单,处理消息以及将消息压入队列,,在H的handleMessage方法中可以得到一段处理Activity启动的逻辑。

#ActivityThreadprivate class H extends Handler {public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");//获取记录Activity状态等相关信息的ActivityClientRecord对象final ActivityClientRecord r = (ActivityClientRecord) msg.obj;//获取PackageInfor.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);//启动ActivityhandleLaunchActivity(r, null, "LAUNCH_ACTIVITY");Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;... ...
}
}

在处理启动Activity的这段分支代码中,主要是调用了handleLaunchActivity方法来处理启动的具体逻辑,在handleLaunchActivity方法中又会调用performLaunchActivity方法来获取一个Activity实例。

#ActivityThreadprivate void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {... ...Activity a = performLaunchActivity(r, customIntent);... ...
}

而这个performLanchActivity方法才是正真处理Activity启动的关键所在,其中对大量Activity相关参数进行初始化。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");//获取ActivityInfo信息ActivityInfo aInfo = r.activityInfo;if (r.packageInfo == null) {r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);}//获取要启动的Activity的组件信息ComponentName component = r.intent.getComponent();if (component == null) {component = r.intent.resolveActivity(mInitialApplication.getPackageManager());r.intent.setComponent(component);}//根据相关信息构建组件对象if (r.activityInfo.targetActivity != null) {component = new ComponentName(r.activityInfo.packageName,r.activityInfo.targetActivity);}//获取Context对象ContextImpl appContext = createBaseContextForActivity(r);//这里开始构造具体的Activity对象Activity activity = null;try {//获取PackageInfo所描述的类加载器java.lang.ClassLoader cl = appContext.getClassLoader();//通过Instrumentation对象获取一个Activity对象activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());//设置相关参数准备初始化Activityr.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess();if (r.state != null) {r.state.setClassLoader(cl);}} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to instantiate activity " + component+ ": " + e.toString(), e);}}try {//获取Application对象Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (localLOGV) Slog.v(TAG, "Performing launch of " + r);if (localLOGV) Slog.v(TAG, r + ": app=" + app+ ", appName=" + app.getPackageName()+ ", pkg=" + r.packageInfo.getPackageName()+ ", comp=" + r.intent.getComponent().toShortString()+ ", dir=" + r.packageInfo.getAppDir());if (activity != null) {CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());//构造Configuration 对象Configuration config = new Configuration(mCompatConfiguration);if (r.overrideConfig != null) {config.updateFrom(r.overrideConfig);}if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "+ r.activityInfo.name + " with config " + config);Window window = null;if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null;}appContext.setOuterContext(activity);//通过attach方法将上述信息保存到activity内部activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback);if (customIntent != null) {activity.mIntent = customIntent;}r.lastNonConfigurationInstances = null;checkAndBlockForNetworkAccess();activity.mStartedActivity = false;//设置主题int theme = r.activityInfo.getThemeResource();if (theme != 0) {activity.setTheme(theme);}activity.mCalled = false;//根据是否需要持久化调用callActivityOnCreate方法通知Activity已被创建和启动if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onCreate()");}r.activity = activity;r.stopped = true;if (!r.activity.mFinished) {activity.performStart();r.stopped = false;}if (!r.activity.mFinished) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}if (!r.activity.mFinished) {activity.mCalled = false;if (r.isPersistable()) {mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnPostCreate(activity, r.state);}if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onPostCreate()");}}}r.paused = true;mActivities.put(r.token, r);} catch (SuperNotCalledException e) {throw e;} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to start activity " + component+ ": " + e.toString(), e);}}return activity;}

Activity所需要的Context对象构造过程:

#ActivityThreadprivate ContextImpl createBaseContextForActivity(ActivityClientRecord r) {final int displayId;try {displayId = ActivityManager.getService().getActivityDisplayId(r.token);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();// For debugging purposes, if the activity's package name contains the value of// the "debug.use-second-display" system property as a substring, then show// its content on a secondary display if there is one.String pkgName = SystemProperties.get("debug.second-display.pkg");if (pkgName != null && !pkgName.isEmpty()&& r.packageInfo.mPackageName.contains(pkgName)) {for (int id : dm.getDisplayIds()) {if (id != Display.DEFAULT_DISPLAY) {Display display =dm.getCompatibleDisplay(id, appContext.getResources());appContext = (ContextImpl) appContext.createDisplayContext(display);break;}}}return appContext;}

在createBaseContextForActivity中 , 通过ContextImpl的静态方法createActivityContext获得一个ContextImpl的实例对象。并通过 appContext.setOuterContext(activity);方法将两者进行关联。

Applicaition创建过程:

#ActivityThread.H.handleMesage方法
case BIND_APPLICATION:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;
#ActivityThreadprivate void handleBindApplication(AppBindData data) {
.......Application app;final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();try {// If the app is being launched for full backup or restore, bring it up in// a restricted environment with the base application class.app = data.info.makeApplication(data.restrictedBackupMode, null);mInitialApplication = app;
......}

handleBindApplication中调用makeApplication方法生成一个Application对象。

#LoadedApk
public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {//相对成员变量mApplication做非空判断避免重复构造if (mApplication != null) {return mApplication;}Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");Application app = null;String appClass = mApplicationInfo.className;if (forceDefaultAppClass || (appClass == null)) {appClass = "android.app.Application";}try {java.lang.ClassLoader cl = getClassLoader();if (!mPackageName.equals("android")) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"initializeJavaContextClassLoader");initializeJavaContextClassLoader();Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}//获取一个ContextImpl对象ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);//获取一个Application对象app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);//将Application与得到的ContextImpl进行关联appContext.setOuterContext(app);} catch (Exception e) {if (!mActivityThread.mInstrumentation.onException(app, e)) {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);throw new RuntimeException("Unable to instantiate application " + appClass+ ": " + e.toString(), e);}}mActivityThread.mAllApplications.add(app);mApplication = app;if (instrumentation != null) {try {instrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!instrumentation.onException(app, e)) {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);throw new RuntimeException("Unable to create application " + app.getClass().getName()+ ": " + e.toString(), e);}}}// Rewrite the R 'constants' for all library apks.SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();final int N = packageIdentifiers.size();for (int i = 0; i < N; i++) {final int id = packageIdentifiers.keyAt(i);if (id == 0x01 || id == 0x7f) {continue;}rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);return app;}

这里可以看到,虽然具体代码不尽相同,但是创建Applcation和Context以及将两者关联的套路基本是与Activity一致,当然还有Service,具体不说了。

参考《Android源码设计模式》

Context与ContextImpl相关推荐

  1. 【Android 安全】DEX 加密 ( Application 替换 | 获取 ContextImpl、ActivityThread、LoadedApk 类型对象 | 源码分析 )

    文章目录 一.获取对象类型分析 二.获取 ContextImpl 类型对象 三.获取 ActivityThread.LoadedApk 类型对象 dex 解密时 , 需要将 代理 Applicatio ...

  2. 一种 Android 应用内全局获取 Context 实例的装置

    哥白尼 · 罗斯福 · 马丁路德 · 李开复 · 嫁衣曾经说过 Where there is an Android App, there is an Application context. 没毛病, ...

  3. android context继承关系,android中Context深入详解

    以下分别通过Context认知角度,继承关系,对象创建等方面android中Context做了深入的解释,一起学习下. 1.Context认知. Context译为场景,一个应用程序可以认为是一个工作 ...

  4. Android中Context详解

    给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中时刻的在与它打交道,例如:Service.BroadcastReceiver.Activity等 ...

  5. Android Context应用上下文详解

    Context类 ,说它熟悉,是应为我们在开发中时刻的在与它打交道,例如:Service.BroadcastReceiver.Activity等都会利用到Context的相关方法 : 说它陌生,完全是 ...

  6. Android在Context详细解释 ---- 你不知道Context

                                                                                                         ...

  7. 与context的关系_Android-Context

    一.简介 Context 翻译为上下文环境,是一个应用程序环境信息的接口. 如果以 Android 系统角度来看可以理解为某一与操作系统的交互的具体场景,比如 Activity 的具体功能,Servi ...

  8. 与context的关系_Android 一个进程有多少个 Context 对象(答对的不多)

    本文作者 作者:彭旭锐 链接: https://www.jianshu.com/p/51d63a1ffb95 本文由作者授权发布. 0前言 "一个进程有多少 Context 对象?" ...

  9. Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析

    出自:http://blog.csdn.net/luoshengyang/article/details/8201936 在前文中,我们简要介绍了Android应用程序窗口的框架.Android应用程 ...

最新文章

  1. JavaScript强化教程——AJAX
  2. myeclipse2019左侧工程目录字体的大小调整
  3. 百度SEO站群最新易支付源码完整版 已pj全解密
  4. 解决JupyterLab/JupyterNotebook安装pycherts后依旧报错报错 ModuleNotFoundError: No module named ‘pyecharts‘
  5. 耐克为何不接受加密货币付款?
  6. css中float left与float right的使用说明
  7. 虚函数和虚析构函数的实现原理--虚函数表
  8. dell服务器错误代码
  9. 【蓝桥杯真题】2021年蓝桥杯省赛B组题目解析+代码(C/C++)
  10. 设计圈都这么卷的吗!看霜降海报哪家强
  11. 通过Matplotlib画sin(x)
  12. cpu.h-栈的宏定义-满减栈
  13. yum源解释(接地气)
  14. AI面临产业大考:落地虽难,但产业化路径已日渐清晰
  15. jquery实现歌词滚动
  16. PM2.5传感器通过树莓派推送到ThingsPanel
  17. PTA乙级题解(110题全)
  18. 好书推荐--Linux之父Linus的自传《Just for Fun》
  19. cml sml区别_资本资产定价模型中cml与sml有什么区别?
  20. 西航计算机学院学生会,“智”行千里,逐梦远航丨西航职院人工智能学院召开2020年度总结表彰暨新年联欢会...

热门文章

  1. 【接口文档】微信支付现金红包未开通,公众号发红包用第三方红包代发接口
  2. 求最大公约数,最小公倍数
  3. 小技巧,怎么查看数据库热度排名
  4. Uncle Sam 山姆大叔
  5. TypeError: __init__() takes 1 positional argument but 2 were given
  6. 计算机824难不难,南京理工大学
  7. 微信分享本地视频到朋友圈,收藏或者对话
  8. 阿里云设置登录掩码错误无法登录
  9. 【模电】0014 运放自激振荡和消除(补偿)
  10. 用wait¬ify实现多线程才是正确打开方式