Android复习之四大组件

一.Background

初出茅庐,今个儿业务不急,就把我知道的复习一遍,首先复习android的四大组件的Activity开始。

It's my first time to write technical blog in English.大笑
As we all known,four components of android perform have Activity,Service,BroadcastReceiver,ContentProvider.


二.Activity

2.1 Lifecycle

These is a diagram from Google Developers shows us some of the most important status of activity.


From the figure above, it can be seen that there is what looks like status(methods) in the activity.
1.When the activity is starting, onCreate(Bundle) will be called.
2.Then it will call onStart(). If the activity had been stopped, onStart() will be called after onRestart().
3.Then it will call onResume() and the activity will be running.


4.If another activity comes into the foreground, original activity will call onPause().
5.When the activity is no longer visible,it will call onStop().
6.Then the activity is finishing or being destroyed by the system,onDestroy() will be called. 


There are other regularities and rules.
1.The status is sounds interesting to us, which is starting to feel like the funny opposite-field mystery.For instance,onCreate() and onDestory(),onStart() and onStop(),onResume() and onPause().
2....


Now let's analyse the android source code.

<span style="font-weight: normal;">    /**
     * Called when the activity is starting.  This is where most initialization
     * should go: calling {@link #setContentView(int)} to inflate the
     * activity's UI, using {@link #findViewById} to programmatically interact
     * with widgets in the UI, calling
     * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve
     * cursors for data being displayed, etc.
     *
     * <p>You can call {@link #finish} from within this function, in
     * which case onDestroy() will be immediately called without any of the rest
     * of the activity lifecycle ({@link #onStart}, {@link #onResume},
     * {@link #onPause}, etc) executing.
     *
     * <p><em>Derived classes must call through to the super class's
     * implementation of this method.  If they do not, an exception will be
     * thrown.</em></p>
     *
     * @param savedInstanceState If the activity is being re-initialized after
     *     previously being shut down then this Bundle contains the data it most
     *     recently supplied in {@link #onSaveInstanceState}.  <b><i>Note: Otherwise it is null.</i></b>
     *
     * @see #onStart
     * @see #onSaveInstanceState
     * @see #onRestoreInstanceState
     * @see #onPostCreate
     */
    @MainThread
    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
        if (mLastNonConfigurationInstances != null) {
            mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
        }
        if (mActivityInfo.parentActivityName != null) {
            if (mActionBar == null) {
                mEnableDefaultActionBarUp = true;
            } else {
                mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
            }
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                    ? mLastNonConfigurationInstances.fragments : null);
        }
        mFragments.dispatchCreate();
        getApplication().dispatchActivityCreated(this, savedInstanceState);
        if (mVoiceInteractor != null) {
            mVoiceInteractor.attachActivity(this);
        }
        mCalled = true;
    }</span>

The official explanation for the states of activity's lifecycle look like this:

The entire lifetime

The visible lifetime

The foreground lifetime

|__onCreate()     //Called when the activity is first created.

          |____onRestart()     //Called after your activity has been stopped, prior to it being started again.

         |____onStart()         //Called when the activity is becoming visible to the user.

                   |____onResume()     //Called when the activity will start interacting with the user. 

                   |____onPause()         //Called when the system is about to start resuming a previous activity.

         |____onStop()          //Called when the activity is no longer visible to the user, because another activity has                                                  been resumed and is covering this one.

|__onDestroy()//the activity is finishing (someone called finish() on it, or the system is temporarily destroying this instance of the activity to save space. 


(不写英文了,这自带的编辑器让人捉急(#▼皿▼))



三、Service

      3.1 Service

      Service继承ContextWrapper类,并实现ComponentCallback2接口。


      常见的Service比如后台监控、后台下载、音乐播放等,是长生命周期、无用户界面的。


      主要有2种状态:started和bound状态。

      started状态,组件调用startService()启动服务,stopService()停止服务;

      bound状态,组件调用bindService()绑定到服务,unbindService()解除绑定服务。


      官方对Service的解释:

  • A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
  • A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).


      3.2 Service Lifecycle


      若调用者与service无关,

      onCreate() --> onStart()  -------------------->  onDestroy()//此时,即使调用者退出了,service仍可运行。

      onStart()被onStartCommand(Intent, int, int)替代


      若调用者绑定了service,

      onCreate() --> onBind() --> onUnbind() --> onDestroy()//此时,一旦调用者退出了,service也停下了。

      重新绑定service,onUnbind() --> onRebind() --> onUnbind() --> onDestroy()


      另外,调用者可以同时start和bind。


      如果已经调用了Context.startService(),那么系统会去retrieve(检索)这个service(如果这service没有启动,会先调用onCreate()创建一个),然后调用onStartCommand(Intent, int, int)方法处理客户端提供的参数(启动时传过来的Intent和其他参数)。这个service会一直运行,直到Context.stopService()或stopSelf()被调用。

      注意:无论service被重复启动多少次,只要调用Context.stopService()或stopSelf()就会被终止。然而,service可以使用stopSelf(int)方法来确保该servie直到Intent被处理好后才被终止。


      对于运行中的service,决定service运行依赖于从onStartCommond()返回的参数,主要有2个:

START_STICKY,用于明确需要开始或终止的service

START_NOT_STICKY 或 START_REDELIVER_INTENT,仅仅用于service仍处运行中并且在处理任何发送给它们的命令的service


      官方对这三个参数的解释:

int START_STICKY

Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent.

int START_NOT_STICKY

Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), and there are no new start intents to deliver to it, then take the service out of the started state and don't recreate until a future explicit call toContext.startService(Intent).

int START_REDELIVER_INTENT

Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then it will be scheduled for a restart and the last delivered Intent re-delivered to it again via onStartCommand(Intent, int, int).


      3.3 Process Lifecycle(只是Service Process Lifecycle)


      此处直接翻译官方文档,并加上一点自己的理解:

      如果service正处于运行中或已被调用者绑定,android系统会一直保持着这个寄存服务的进程。当内存不足而不得不要杀这个运行中的进程的时候,该寄存服务的进程的优先级在如下情况下会变高:


      1.如果当前service正在执行的代码在onCreate(),onStartCommand(),或onDestroy()方法内,那么寄存该service的进程就会变成那种可以确保这些代码不被杀掉的前台进程。


      2.如果该service已启动,那么寄存它的宿主进程会变成那种相对于那些当前已经在屏幕展示给用户的任何一个进程(应该是可见进程Visible Process)就显得不那么重要了,但仍比任何一个不可见进程(应该是后台进程Background Process)重要的多。因为一般情况下仅有少数进程是用户一直可见的,这意味着那些期望占用较少内存的service不会被杀。不过,因为用户不能直接意识到后台进程,所以这种状态下的进程会被考虑成一个将被杀掉的有效候选者,你必须为这种情况的发生做好准备。尤其是那种运行了较长时间的services会有更大可能被杀掉(或在合适的情况下被重启),如果他们保留了足够长时间的话。


      3.如果已有客户端(调用者)绑定这些service的话,那么这些service的宿主进程会比那些最重要的调用者更重要(此处官方文档用be never less important than..来形容宿主进程的重要性,可见文档的作者不仅技术牛逼,还有可能是个作家^_^)。如果某一个调用者对用户可见,那么对应的service也会被考虑成对用户可见的。调用者的重要性影响着service重要性的这种方式可以通过BIND_ABOVE_CLIENT,BIND_ALLOW_OOM_MANAGEMENT,BIND_WAIVE_PRIORTANT和BIND_ADJUST_ACTIVITY来调整。


      4.一个运行中的service可使用startForeground(int, Notification) API 来将该service置于前台的状态,这样系统就会认为它是用户可以积极意识到的,所以当内存低时候也不会成为被杀掉的候选者。(对于service,从理论上说它仍然可能在极度需要内存的压力下从当前的前台应用中被杀掉,但这情况在实践中并不用关心。)


      注意,这意味着大多数时候,你的service都是处在运行中的,如果此时系统正处在急需内存的高压下(就是低内存的情况下),那么它可能被系统杀掉。如果这事发生了,那么系统会稍后尝试去重启该service。这种情况下的一个重要结果是如果你通过执行onStartCommand()来计划去异步完成work(就是重启该service)或放另一个线程完成work的话,那么你可能会使用START_FLAG_REDELIVERY来拥有系统重传者去为你传递一个Intent,所以即使你的service被杀掉,它也不会丢失并再次启动它。(完整的翻译要理解起来实在不容易)


      原官方对此的解释:


The Android system will attempt to keep the process hosting a service around as long as the service has been started or has clients bound to it. When running low on memory and needing to kill existing processes, the priority of a process hosting the service will be the higher of the following possibilities:

  • If the service is currently executing code in its onCreate()onStartCommand(), or onDestroy() methods, then the hosting process will be a foreground process to ensure this code can execute without being killed.

  • If the service has been started, then its hosting process is considered to be less important than any processes that are currently visible to the user on-screen, but more important than any process not visible. Because only a few processes are generally visible to the user, this means that the service should not be killed except in low memory conditions. However, since the user is not directly aware of a background service, in that state it is considered a valid candidate to kill, and you should be prepared for this to happen. In particular, long-running services will be increasingly likely to kill and are guaranteed to be killed (and restarted if appropriate) if they remain started long enough.

  • If there are clients bound to the service, then the service's hosting process is never less important than the most important client. That is, if one of its clients is visible to the user, then the service itself is considered to be visible. The way a client's importance impacts the service's importance can be adjusted through BIND_ABOVE_CLIENT,BIND_ALLOW_OOM_MANAGEMENTBIND_WAIVE_PRIORITYBIND_IMPORTANT, and BIND_ADJUST_WITH_ACTIVITY.

  • A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)

Note this means that most of the time your service is running, it may be killed by the system if it is under heavy memory pressure. If this happens, the system will later try to restart the service. An important consequence of this is that if you implement onStartCommand() to schedule work to be done asynchronously or in another thread, then you may want to use START_FLAG_REDELIVERY to have the system re-deliver an Intent for you so that it does not get lost if your service is killed while processing it.

Other application components running in the same process as the service (such as an Activity) can, of course, increase the importance of the overall process beyond just the importance of the service itself.


      3.4 Service实现方式

      源码过多,此处借用amurocrash同学的UML图:

start:


bind:

四、BroadcastReceiver广播接收器

      4.1 BroadcastReceiver

      BroadcastReceiver直接继承Object

      是极短生命周期(10s左右)、无用户界面的。

      App可用broadcast receiver对外部事件进行过滤,对感兴趣的外部事件(eg. 当有电话呼入时,当有网络连接时)进行接受并做出响应(eg. 启动activity或service,用NotificationManager通知用户等)。


      4.2 广播类型(3个)

      普通广播Context.sendBroascast(Intent)发送


      有序广播 Context.sendOrderedBroascast(Intent, receiverPermission)发送


      异步广播Context.sendStickyBroascast(Intent)

Context.sendStickyOrderedBroascast(Intent, resultReceiver, scheduler, initialCode, initialData, initialExtras)发送


       官方对此的解释说明:

There are two major classes of broadcasts that can be received:

  • Normal broadcasts (sent with Context.sendBroadcast) are completely asynchronous. All receivers of the broadcast are run in an undefined order, often at the same time. This is more efficient, but means that receivers cannot use the result or abort APIs included here.
  • Ordered broadcasts (sent with Context.sendOrderedBroadcast) are delivered to one receiver at a time. As each receiver executes in turn, it can propagate a result to the next receiver, or it can completely abort the broadcast so that it won't be passed to other receivers. The order receivers run in can be controlled with the android:priorityattribute of the matching intent-filter; receivers with the same priority will be run in an arbitrary order.


      4.3 Lifecycle

      一个BroascastReceiver对象的有效持续时间只有调用onReceive(Context, Intent)的时间,一旦从onReceive(Context, Intent)返回参数,系统就会认为该对象可以终止并不再活动了。


      4.4 工作过程

      源码过多,此处仍借用amurocrash同学的UML图

      注册(动态):



      发送和接收:


五、Content Provider内容提供者

      官方的说明是:

Content providers manage access to a structured set of data.They encapsulate the data, and provide mechanisms for defining data security. Content providers are the standard interface that connects data in one process with code running in another process. 


      其实就是在多个进程间做数据共享,Android的IPC机制的实现方式之一。后期一定会总结Binder、Socket、AIDL、Message等其它可以handle inter-process communication and secure data access的文章出来详细解释,不过那是后话。


      Content Provider可将某一app的制定数据集提供给其它app,其它app通过ContentResolver类从该Content Provider中获取或存入数据。


      常见的数据有通讯录数据


     ContentResolver类提供了持久化存储的CRUD方法


六、四大组件的配置文件

      6.1 AndroidManifest.xml

Android的配置清单文件,具体功能如下:

1.说明了应用的package;

2.描述了应用的组成部分,eg.四大组件

3.查明了哪些进程

4.确定了哪些权限是应用为了访问受保护的api和与其它应用的交互需要的

5.表明了哪些权限是其它应用为了与本应用交互需要的

6.列出当应用运行时候Instrumentation类提供的分析及其它数据,只在开发和测试时候用,应用上线前会移除掉

7.确定了应用要求的Android最小API等级

8.列出了应用必须被链接的类库


eg. 四大组件的注册

<activity></activity>

<service></service>

<receiver></receiver>

<provider></provider>


      6.2 结构

<?xml version="1.0" encoding="utf-8"?>

<manifest package="">

    <uses-permission />
    <permission />
    <permission-tree />
    <permission-group />
    <instrumentation />
    <uses-sdk />
    <uses-configuration />  
    <uses-feature />  
    <supports-screens />  
    <compatible-screens />  
    <supports-gl-texture />  

    <application>

        <activity>
            <intent-filter>
                <action />
                <category />
                <data />
            </intent-filter>
            <meta-data />
        </activity>

        <activity-alias>
            <intent-filter> . . . </intent-filter>
            <meta-data />
        </activity-alias>

        <service>
            <intent-filter> . . . </intent-filter>
            <meta-data/>
        </service>

        <receiver>
            <intent-filter> . . . </intent-filter>
            <meta-data />
        </receiver>

        <provider>
            <grant-uri-permission />
            <meta-data />
            <path-permission />
        </provider>

        <uses-library />

    </application>

</manifest>

      6.3 后续

      看到androidMinifest.xml的activity和intent,不免想到activity的launch modes和intent, intent-filter,改日继续。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值