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();
}