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