全屏浏览
缩小浏览
回到页首

android基础---->service的生命周期

   服务是一个应用程序组件代表应用程序执行一个长时间操作的行为,虽然不与用户交互或供应功能供其它应用程序使用。它和其他的应用对象一样,在他的宿主进程的主线程中运行。今天我们开始android中普通service服务的学习。本地服务与前台服务,请参见我的另外一篇博客:   android基础---->IntentService的使用

 

目录导航

  1.   service服务的简单说明
  2.   service服务测试的准备代码
  3.   service服务start的测试
  4.   service服务bind的测试
  5.   service的生命周期的总结        
  6.   友情链接

 

service的简单说明

一、 service类型划分:

  • 运行地点划分:
类别 区别  优点 缺点   应用
本地服务(Local) 该服务依附在主进程上,  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多。  主进程被Kill后,服务便会终止。  非常常见的应用如:HTC的音乐播放服务,天天动听音乐播放服务。
远程服务(Remote) 该服务是独立的进程,  服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。  该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。  一些提供系统服务的Service,这种Service是常驻的。
  •  按运行类型分类:
类别 区别 应用
前台服务 会在通知一栏显示 ONGOING 的 Notification, 当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务。
后台服务 默认的服务即为后台服务,即不会在通知一栏显示 ONGOING 的 Notification。 当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新,日期同步,邮件同步等。
  • 按使用方式分类:
类别 区别
startService 启动的服务 主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService
bindService 启动的服务 该方法启动的服务要进行通信。停止服务使用unbindService
startService 同时也 bindService 启动的服务 停止服务应同时使用stepService与unbindService

 

二、 两种服务的启动流程:

  • context.startService() 启动流程(后台处理工作):

  context.startService()  -> onCreate()  -> onStartCommand()  -> Service running  -> context.stopService()  -> onDestroy()  -> Service stop 所以调用startService的生命周期大致为:onCreate(只在创建的时候调用一次直到被摧毁) --> onStartCommand (服务开启后,可多次调用) --> onDestroy

  • context.bindService()启动流程(在本地同一进程内与Activity交互):

  context.bindService()  -> onCreate()  -> onBind()  -> Service running  -> onUnbind()  -> onDestroy()  -> Service stopbindService的生命周期简化为为:onCreate --> onBind --> onUnbind --> onDestory

 

三、 service的使用细节:

  • 在注册服务的时候,为了将service纳入编译系统,必须在AndroidMainfest.xml中对Service进行显式声明。
  • 计算量较大的又不是UI层的工作的话,可以选择放置在Service中进行工作。
  • 通过开发文档你会发现,Android中的Service与宿主(调用者)在同一线程,而不是专门起一条线程,这意味着,如果你的服务要CPU密集型操作(如:MP3播放)或则阻塞操作(如网络)时,必须产生它自己的线程来完成这个工作,否则会造成线程阻塞。在Service的子类里面,
  • 如果在使用Service的时候又使用了广播接收器配合工作,广播如果是动态注册的话,在服务停止的时候记得调用unregisterReceiver(receiver);这个方法来注销掉接收器

 

四、 android中服务的启动与停止:

  • 服务的启动:
Intent intent = new Intent();
intent.setClass(MainActivity.this , NormalServices.class);
startService(intent);
  • 服务的停止:
Intent intent = new Intent();
intent.setClass(MainActivity.this , NormalServices.class);
stopService(intent);

 

service服务测试的准备代码

  我们通过一个具体的案例来说明start与bind方式的service服务的生命周期的介绍。项目结果如下:

 

一、 在MainActivity.java中做一些初始化工作,如下代码:

private final static String TAG = "NormalServices";
private NormalServices.MyBinder binder;

private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = (NormalServices.MyBinder) service;
        binder.sayHello(name.getClassName());
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.i(TAG, "service disconnect: " + name.getClassName());
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.i(TAG, "main on create.");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

 

二、 创建一个简单的服务类:NormalServices

package com.example.linux.serviceslifetest;

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

public class NormalServices extends Service {
    private final static String TAG = "NormalServices";
    private MyBinder myBinder = new MyBinder();

    class MyBinder extends Binder {
        public void sayHello(String name) {
            Log.i(TAG, "say hello method: " + name);
        }
        public void sayWorld(String name) {
            Log.i(TAG, "say world method: " + name);
        }
    }

    public NormalServices() {
        Log.i(TAG, "NormalServices constructor.");
    }

    @Override
    public IBinder onBind(Intent intent) {
        String username = intent.getStringExtra("username");
        Log.i(TAG, "on bind" + ": username: " + username);
        return myBinder;
    }

    @Override
    public void onCreate() {
        Log.i(TAG, "on create.");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "on start command.");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "on destory.");
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        //默认返回false
        String username = intent.getStringExtra("username");
        Log.i(TAG, "on unbind: " + super.onUnbind(intent) + ", username: " + username);
        return true;
    }

    @Override
    public void onRebind(Intent intent) {
        Log.i(TAG, "on rebind");
        super.onRebind(intent);
    }
}

 

 三、 创建另外一个活动,用于测试活动切换时,service的生命周期的变化:OtherActivity

package com.example.linux.serviceslifetest;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class OtherActivity extends AppCompatActivity {
    private final static String TAG = "NormalServices";
    private NormalServices.MyBinder binder;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binder = (NormalServices.MyBinder) service;
            binder.sayHello(name.getClassName());
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "OtherActivity service disconnect: " + name.getClassName());
        }
    };

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

    public void startService(View view) {
        Intent intent = new Intent();
        intent.setClass(OtherActivity.this, NormalServices.class);
        startService(intent);
    }

    public void stopService(View view) {
        Intent intent = new Intent();
        intent.setClass(OtherActivity.this, NormalServices.class);
        stopService(intent);
    }

    // 绑定服务
    public void bindService(View view) {
        Intent intent = new Intent();
        intent.setClass(OtherActivity.this, NormalServices.class);
        boolean isBind = bindService(intent, connection, Context.BIND_AUTO_CREATE);
        Log.i(TAG, "bind service: " + isBind);
    }

    // 解绑服务
    public void unbindService(View view) {
        Intent intent = new Intent();
        intent.setClass(OtherActivity.this, NormalServices.class);
        unbindService(connection);
    }
}

 

四、 在AndroidManifest.xml中注册服务与活动:

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<service
    android:name=".NormalServices"
    android:enabled="true"
    android:exported="true" />

<activity android:name=".OtherActivity"/

 

五、 在MainActivity中加入方法,启动另外一个活动:

//启动另外一个Activity
public void otherActivity(View view) {
    Intent intent = new Intent();
    intent.setClass(MainActivity.this, OtherActivity.class);
    startActivity(intent);
}

 

service服务start的测试

一、 在MainActivity中创建方法startService,启动服务:

public void startService(View view) {
    Intent intent = new Intent();
    intent.setClass(MainActivity.this, NormalServices.class);
    startService(intent);
}

 

二、 在MainActivity中创建方法stopService,停止服务:

public void stopService(View view) {
    Intent intent = new Intent();
    intent.setClass(MainActivity.this, NormalServices.class);
    stopService(intent);
}

 

三、 运行的结果如下:

  • 点击start:
03-24 19:28:40.130 9986-9986/com.example.linux.serviceslifetest I/NormalServices: NormalServices constructor.
03-24 19:28:40.130 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on create.
03-24 19:28:40.130 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on start command.
  • 点击stop:
03-24 19:31:18.730 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on destory.
  • 点击start:
03-24 19:32:23.660 9986-9986/com.example.linux.serviceslifetest I/NormalServices: NormalServices constructor.
03-24 19:32:23.660 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on create.
03-24 19:32:23.660 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on start command.
  • 点击start:
03-24 19:33:06.350 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on start command.
  • 点击stop:
03-24 19:33:30.240 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on destory.

 

四、 对于上述结果的分析:

  • 当service第一次创建启动(start方法触发):

  service的构造方法:

  oncreate方法

  onStartCommand方法

  • stop方法触发时,关闭服务:

  on destory

  • 如果service没有被destory,那么随后点击start,只会执行onStartCommand方法

                 

 

service服务bind的测试

一、 在MainActivity中创建方法bindService,绑定服务:

// 绑定服务
public void bindService(View view) {
    Intent intent = new Intent();
    intent.setClass(MainActivity.this, NormalServices.class);
    intent.putExtra("username", "linux");
    boolean isBind = bindService(intent, connection, Context.BIND_AUTO_CREATE);
    Log.i(TAG, "bind service: " + isBind);
}

 

二、  在MainActivity中创建方法unbindService,解绑服务:

// 解绑服务
public void unbindService(View view) {
    Intent intent = new Intent();
    intent.setClass(MainActivity.this, NormalServices.class);
    unbindService(connection);
}

 

三、 运行结果如下:

  • 点击bind服务:
03-24 19:37:26.340 18803-18803/com.example.linux.serviceslifetest I/NormalServices: bind service: true
03-24 19:37:26.350 18803-18803/com.example.linux.serviceslifetest I/NormalServices: NormalServices constructor.
03-24 19:37:26.350 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on create.
03-24 19:37:26.350 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on bind: username: linux
03-24 19:37:26.370 18803-18803/com.example.linux.serviceslifetest I/NormalServices: say hello method: com.example.linux.serviceslifetest.NormalServices
  • 点击start开启服务:
03-24 19:38:12.020 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on start command.
  • 点击stop:无输出
  • 点击unbind解绑服务:
03-24 19:39:05.200 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on unbind: false, username: linux
03-24 19:39:05.200 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on destory.

 

四、 对于上述结果的分析:

服务的绑定:
  • 在绑定服务之前,首先要有服务存在才行。如果指定了BIND_AUTO_CREATE,而且此时没有服务。则会创建服务,但onStartCommand方法此时没有执行。
  • 执行onbind方法,返回Ibind是onServiceConnected方法中的service参数,这样就可以执行Ibinder的方法了
  • 一个Activity同时绑定同一服务再次,那么服务的onbind方法就不会得到执行
服务的解绑:
  • onbind方法,如果没有之前的startService,那么onDestory方法也会得到执行
其它说明:
  • 类ServiceConnection中的onServiceDisconnected()方法在正常情况下是不被调用的,它的调用时机是当Service服务被异外销毁时,例如内存的资源不足时.
  • This typically happens when the process hosting the service has crashed or been killed.
活动与服务:
  • 在bind服务时,不需要服务启动。启动服务也不需要有Activity绑定服务
  • Activity销毁之后,对应的服务也被销毁。

 

service的生命周期的总结

   前面我们使用到的onCreate()、onStartCommand()、onBind()和onDestroy()等方法都是在服务的生命周期内可能回调的方法。

一、 启动与停下服务:

  一旦在项目的任何位置调用了Context 的startService()方法,相应的服务就会启动起来,并回调onStartCommand()方法。如果这个服务之前还没有创建过,onCreate()方法会先于onStartCommand()方法执行。服务启动了之后会一直保持运行状态,直到stopService()或stopSelf()方法被调用。注意虽然每调用一次startService()方法,onStartCommand()就会执行一次,但实际上每个服务都只会存在一个实例。所以不管你调用了多少次startService()方法,只需调用一次stopService()或stopSelf()方法,服务就会停止下来了。

 

二、 绑定与解绑服务:

  另外,还可以调用Context 的bindService()来获取一个服务的持久连接,这时就会回调服务中的onBind()方法。类似地,如果这个服务之前还没有创建过,onCreate()方法会先于onBind()方法执行。之后,调用方可以获取到onBind()方法里返回的IBinder 对象的实例,这样就能自由地和服务进行通信了。只要调用方和服务之间的连接没有断开,服务就会一直保持运行状态。

 

三、 启动与绑定服务:

  当调用了startService()方法后,又去调用stopService()方法,这时服务中的onDestroy()方法就会执行,表示服务已经销毁了。类似地,当调用了bindService()方法后,又去调用unbindService()方法,onDestroy()方法也会执行,这两种情况都很好理解。但是需要注意,我们是完全有可能对一个服务既调用了startService()方法,又调用了bindService()方法的,这种情况下该如何才能让服务销毁掉呢?根据Android 系统的机制,一个服务只要被启动或者被绑定了之后,就会一直处于运行状态,必须要让以上两种条件同时不满足,服务才能被销毁。所以,这种情况下要同时调用stopService()和unbindService()方法,onDestroy()方法才会执行。

 

友情链接

 

posted @ 2016-03-24 20:17  huhx  阅读(1540)  评论(0编辑  收藏  举报