Activity
在平时的应用开发中,接触最多的就是activity的生命周期。在生命周期回调方法中,您可以声明当用户离开并重新进入活动时,执行相应的代码行为。每一个回调工作,都应该执行特定动作,在正确的时间进行正确的工作并正确处理转换,才能够使应用程序更加健壮,更有效率。
如果没有处理好activity的生命周期,则有可能导致各种异常:
- 应用程序运行时被电话或者其他程序中断,导致崩溃;
 - 没有正确释放资源时,消耗宝贵的系统资源,甚至OOM。
 - 如果用户离开您的应用程序并在以后返回,则丢失用户的进度。
 - 屏幕在横向和纵向方向之间旋转时,可能会崩溃或丢失用户的进度。
 
所以有必要深入一些,了解和掌握Activity的生命,下面先放一张activity的生命周期图:
                1.1 Activity状态
根据具体的应用的复杂性,可能不需要实现所有的生命周期方法。
- 创建 onCreate():
- 必须实现此回调,当系统首次创建活动时触发。
 - 在该方法中,执行基本的应用程序启动逻辑,该逻辑在整个活动的整个生命周期中应该只发生一次。
 - 例如,将数据绑定到列表,初始化后台线程,并实例化一些类范围变量。
 - 此方法接收参数savedInstanceState,该参数是包含Bundle 活动之前保存的状态的对象。如果活动从未存在,则该Bundle对象的值为null。
 
 开始 onStart():
- 当活动进入“开始”状态时,系统将调用此回调。
 - 该方法是应用程序初始化维护UI的代码的位置。
 - 它也可以注册一个BroadcastReceiver 监视UI中响应的更改。
 - 该状态只是过渡状态,非常快速完成,与“创建”状态一样,活动不会保持在“已启动”状态。一旦这个回调结束,活动进入 Resumed状态,系统调用该 onResume()方法。
 
恢复 onResume():
- 这是应用程序与用户进行交互的状态。该应用程序停留在此状态,直到发生某些事情,将焦点从应用程序中移开。
 - 当发生中断事件时,活动进入暂停 状态,系统调用 onPause()回调。
 - onResume状态说明activity在最上方,用户可以与它进行交互。所以那些仅在用户关注时才使用的组件应该在这个回调中初始化。
 
- 暂停 onPause():
- 当前activity仍然是可见的。但被另一个activity处在最上方,最上方的activity是半透明的,或者是部分覆盖整个屏幕。被暂停的activity不会再接受用户的输入。
 - 动画和音乐播放Activity在暂停状态下不应该继续。
 - 进入暂停的时机有以下几种:
- 电话或者短信等系统中断;
 - 在多窗口模式中,切换到其他窗口;
 - 打开一个新的半透明活动(如对话框);
 
 - 当处于极度低内存的状态时,系统会杀掉该activity,释放相应资源。
 - onPause()执行非常简短,并不一定有足够的时间执行保存操作。保存应用程序或用户数据不应该在这步骤实现;
 
 停止 onStop():
- 当前activity完全被隐藏,不被用户可见。可以认为是处于在后台。
 - 由于对用户不再可见,只要有内存的需要,系统就会杀掉该activity来释放资源。
 - 该状态由
onStop()进入,或onRestart()或者onCreate()重新唤醒软件,或者被onDestroy()彻底死亡.. 
销毁 onDestroy():
- 在活动被销毁之前调用。这是活动收到的最后一个回调。
 - 在该回调中,释放上述所有回调中未被销毁的资源;
 
当acitivty处于暂停或者停止状态,系统可以通过finish()或 android.os.Process.killProcess(android.os.Process.myPid())来杀死其进程。当该activity再次被打开时(结束或杀死后),需要重新创建,走一遍完整的流程。
1.2 Activities调用流程
当Activity A 启动 Activity B时,两个activity都有自个的生命周期。Activity A暂停或者停止,Activity B被创建。记住,在Activity B创建之前,Activity A并不会完全停止,流程如下:
- Activity A 进入onPause();
 - Activity B 依次 onCreate(), onStart(), onResume()。(此时Activity B得到了用户焦点)
 - 如果Activity A不再可见,则进入onStop().
 
1.3 代码实践
利用下面的DemoActivity代码,可亲自感受每一个阶段的状态。比如点返回键,home键,menu键等操作,可以借助通过logcat查看该activity到底处于哪种状态,这里就不说结果了,自己动手,丰衣足食。
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class DemoActivity extends Activity {
    private static final String TAG = "demo";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG,"onCreate::The activity is being created.");
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart::The activity is about to become visible.");
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume::The activity has become visible.");
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause:: Another activity is taking focus.");
    }
    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop::The activity is no longer visible");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy::The activity is about to be destroyed");
    }
}
Service
理解activity的生命周期后,Service的生命周期也是大同小异,先看下Service的生命周期图:
                2.1 启动方式:
service有两种启动方式:
- startService() 启动本地服务Local Service
 - bindService() 启动远程服务Remote Service
 
2.2 生命周期
两种不同的启动方式决定了Service具有两种生命周期的可能(并非互斥的两种)。
- start方式:onCreate(),onStartCommand()。onDestroy释放资源。
 - bind方式: onCreate(),onBind()方法。需要所有client全部调用unbindService()才能将Service释放资源,等待系统回收。
 
2.3 代码实践
利用下面的DemoService代码,通过logcat自行感受每一个阶段的状态与场景的关系。
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class DemoService extends Service {
    private static final String TAG = "demo";
    int mStartMode;       // service被杀掉的方式
    IBinder mBinder;      // clients绑定接口
    boolean mAllowRebind; // 是否允许onRebind
    @Override
    public void onCreate() {
        Log.i(TAG,"onCreate::The service is being created");
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG,"onStartCommand::The service is starting");
        return mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG,"onBind::A client is binding to the service");
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG,"onUnbind::All clients have unbound");
        return mAllowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        Log.i(TAG,"onRebind::A client rebind to the service " +
                "after onUnbind() has already been called");
    }
    @Override
    public void onDestroy() {
        Log.i(TAG,"onDestroy::The service is no longer used");
    }
}