Service: 生命周期与 startService

Service 经常被使用,结合开发过程中遇到的问题以及注意事项,总结一下 android service 组件。


Service: 小试 AIDL IPC 牛刀 是我年少轻狂之时写的一篇很糟糕的博文,那个时候学得东西不多,但是激情很高。


本来想删掉它,然后重新写一篇,以免毒害他人。后来,还是舍不得,略做修改,勉强一下吧!


本人觉得,it 就是一份扯淡的事业。只要你在 it 行业,就会永远发现新东西。没有尽头!


学会分享和总结,你会发现世界还是很美好地!


这篇博文,算是很简单的入门,高手或者你已经很清楚 service 生命周期的不妨试读一下,给点建议。


运行界面




点击 Button 会启动一个Service(PlayerService),Activity(PlayerActivity)代码示例如下

package mark.zhang;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;


public class PlayerActivity extends Activity {


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}


public void onService(View view) {
    Intent intent = new Intent(PlayerActivity.this, PlayerService.class);
    startService(intent);
}

}


PlayerService 代码示例如下

说明:onStart 方法已经过时了,所以使用 onStartCommand 方法。


package mark.zhang;


import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;


public class PlayerService extends Service {
private static final String TAG = "PlayerService";


private static final long DELAY = 5000;


private int mServiceStartId = -1;


private Handler sWork = new Handler();


private Runnable task = new Runnable() {


    @Override
    public void run() {
        Log.d(TAG, DELAY / 1000 + "s after-----------");
        stopSelf();
        //stopSelf(mServiceStartId);
    }
};


@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "onBind------");
    return null;
}


@Override
public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate------");
    sWork.postDelayed(task, 5000);
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand------and startId = " + startId);
    mServiceStartId = startId;
    return super.onStartCommand(intent, flags, startId);
}


@Override
public void onDestroy() {
    Log.d(TAG, "onDestroy------");
    super.onDestroy();
}

}


在 PlayerService 里面使用 Handler 在 5s 之后停止 PlayerService。


点击 Button 5 次,打印结果




5s 之后,调用 stopSelf(实际调用的是 stopSelf(-1) 这个方法),停止服务。


当然,你也可以在 PlayerActivity 里面调用 stopService 来停止服务。


从这里,可以看出通过 startService 启动服务,其生命周期是这样的。


                                                         



在 Service 的一个生命周期中,onCreate / onDestroy 方法只调用一次,onStartConmand 方法可以被调用多次。

在 onStartConmand 方法里面,可以看出,每调用一次这个方法,startId 就会加 1.


stopSelf() 与 stopSelf(int startId) 与 stopService 的s功效是一样的。

网上很多人说,stopSelf() 与 stopSelf(int startId) 是不会立即停止服务的,我觉得说法不科学。


调用 stopSelf() 或者 stopSelf(int startId),  这个时候 onDestroy 均会被调用,说明 service 的生命已经 over,哪来的服务没有停止?只能说应用程序没有停止,你写的代码如线程死循环一直在跑,虽然该线程也是在 service 里面启动的,但是记住 Service 是与 Activity 默认在一个进程(一个 application 就是一个进程),那麽应用程序没有挂掉,死循环的线程怎么会停止?!


下面举个例子:


在 PlayerService 的 onStartCommand 方法里面


isRunning 是成员变量,默认值为 false

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand------and startId = " + startId);
    mServiceStartId = startId;

    isRunning = true;

    new Thread(new Runnable() {

        @Override
        public void run() {
            while(isRunning) {
                Log.d(TAG, "running--------------------");
            }
        }
       }).start();

    return super.onStartCommand(intent, flags, startId);
}

       

可见如果 isRunning 不设置为 false 或者该 Application 不停止,这个该死的线程永远也不会停下来。

所以,需要在合适的地方设置 isRunning 


如 onDestroy


@Override
public void onDestroy() {
    Log.d("mark", "onDestroy------");
    isRunning = false;
    super.onDestroy();
}





©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页