01.1android Service的概念及作用

来源:互联网 发布:软件生命周期管理 编辑:程序博客网 时间:2024/05/02 00:57
1、概念及作用

由于ANR对Activity和BroadcastReceiver响应时间的限制(Activity对事件响应不超过5秒,BroadcastReceiver执行不超过10秒),使得在其中都不适合执行较耗时操作,这样像网络、数据库、复杂计算这类耗时操作的执行就需要一个组件来承担。Service作为Android四大组件之一,其功能之一就是耗时操作的执行,主要功能如下:

a. 执行需要长时间运行的操作,这个操作不与用户进行交互,如网络下载、大文件I/O、复杂计算。
b. 应用内或应用间数据通信,Android每个应用程序都在自己的dalvik虚拟机中运行,一个应用是不允许访问其他应用的内存信息的,为此Android引入了Content Provider在不同应用间共享数据,BroadcastReceiver广播信息给不同应用程序,但Content Provider更多用于数据的共享,BroadcastReceiver广播的信息会被所有应用接收较耗费系统资源,对于两个应用间动态的进行交互还需要通过Service来完成。

 startService启动不可进行交互的Service

 bindService启动的Service应用内交互



2、使用
(1) startService启动不可进行交互的Service

a. 示例代码及介绍

Service示例

public class MyService extends Service {

    @Override

    public void onCreate() {

        super.onCreate();

        Toast.makeText(this, "Service Create", Toast.LENGTH_SHORT).show();

    }

    @Override

    public void onDestroy() {

        Toast.makeText(this, "Service Destroty", Toast.LENGTH_SHORT).show();

        super.onDestroy();

    }

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) {

        Toast.makeText(this, "Service Start", Toast.LENGTH_SHORT).show();

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

    }

    @Override

    public IBinder onBind(Intent intent) {

        return null;

    }

}

务都必须在AndroidManifest.xml文件中注册<service android:name=".MyService"/>,在Activity中定义对象private Intent myServiceIntent = new Intent(this, MyService.class);在onCreate函数中startService(myServiceIntent)启动服务; onDestroy函数中stopService(myServiceIntent)关闭服务;


b. 生命周期

通过startService启动服务,若服务未启动,会先执行onCreate函数(若服务已启动则不执行此函数),再执行onStartCommand函数。由此可知多次调用startService传入相同参数不会启动多个服务(onStartCommand函数会执行多次),所以最终只需要调用一次stopService或stopSelf函数停止服务;我们可以将service的处理逻辑放入onStartCommand函数中。服务一直运行,在程序退出后服务也不会停止,直到stopService或stopSelf函数被调用,当然可能被系统回收。

对于onStartCommand的返回值,若返回START_STICKY表示服务通过显式调用启动或停止,若返回START_NOT_STICKY orSTART_REDELIVER_INTENT表示服务仅在有请求发送过来处理时才处于运行状态


c. 使用场景

因为这种方式Service无法与外部进行方便的动态交互,所以适合做后台服务,如网络下载(用户通过Intent传入Url到Service)




(2) bindService启动的Service应用内交互

a. 示例代码及介绍

在上面的方式中Context可以通过Intent向Service传入简单的信息,但是如果希望调用Service的接口进行操作或是获取Service的属性则无法实现,这里我们可以通过bindService实现,如下先定义自己的服务


自定义Service

public class MyService extends Service {

    private int      count;
    private MyBinder myBinder = new MyBinder();

    @Override
    public void onCreate() {
        Toast.makeText(this, "Service onCreate", Toast.LENGTH_SHORT).show();
        count = 0;
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service onDestroy", Toast.LENGTH_SHORT).show();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 服务被绑定时调用
     * 返回值用于让调用者和服务通信,传入ServiceConnection的public void onServiceConnected(ComponentName name, IBinder service)函数第二个参数
     */
    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

    public int getCount() {
        return count;
    }

    public int increaseCount() {
        return ++count;
    }

    public int decreaseCount() {
        return --count;
    }

    public class MyBinder extends Binder {

        MyService getService() {
            return MyService.this;
        }
    }
}

从上可以看出我们重写onBind函数并返回自己的Binder用于调用者和服务之间通信。下面我们在调用者中进行调用


定义自己的Service、Intent、ServiceConnection对象

private MyService         myService;

private Intent            myServiceIntent;

private ServiceConnection con = new ServiceConnection() {

                                  /**

                                   * 服务所在进程被kill或是crash时系统调用,而不是unbindService时调用

                                   */

                                  @Override

                                  public void onServiceDisconnected(ComponentName name) {

                                      Toast.makeText(getApplicationContext(), "Service disconnect",

                                                     Toast.LENGTH_SHORT).show();

                                  }

                                  /**

                                   * 服务连接时调用,若已经连接不进行调用

                                   */

                                  @Override

                                  public void onServiceConnected(ComponentName name, IBinder service) {

                                      myService = ((MyBinder)service).getService();

                                      Toast.makeText(getApplicationContext(), "Service Connect", Toast.LENGTH_SHORT).show();

                                  }

                              };



接着调用bindService(myServiceIntent, con, Context.BIND_AUTO_CREATE);

绑定服务,绑定成功返回true。

这时会执行ServiceConnection对象的onServiceConnected函数为myService变量赋值。接着我们就可以通过myService.increaseCount();操作Service的属性,myService.getCount()获得Service的属性,这样我们就成功和Service进行了通信。在不需要通信时通过unbindService(con);解除服务绑定。




b. 生命周期
通过bindService绑定服务,若服务未启动,会先执行Service的onCreate函数,再执行onBind函数,最后执行ServiceConnection对象的onServiceConnected函数。若服务已启动但尚未绑定,先执行onBind函数,再执行ServiceConnection对象的onServiceConnected函数。若服务已绑定成功,则直接返回。这里不会自动调用onStartCommand函数。
通过unbindService解除绑定服务,若已绑定成功,会先执行Service的onUnbind函数,再执行onDestroy函数,注意这里不会执行ServiceConnection对象的onServiceDisconnected函数,因为该函数是在服务所在进程被kill或是crash时被调用。若服务尚未绑定系统会报服务尚未注册异常,我们可以通过如下代码解决

if (myService != null) {
    unbindService(con);
  myService = null;
}



(2) bindService启动的Service应用内交互

a. 示例代码及介绍

在上面的方式中Context可以通过Intent向Service传入简单的信息,但是如果希望调用Service的接口进行操作或是获取Service的属性则无法实现,这里我们可以通过bindService实现,如下先定义自己的服务


自定义Service

public class MyService extends Service {

    private int      count;
    private MyBinder myBinder = new MyBinder();

    @Override
    public void onCreate() {
        Toast.makeText(this, "Service onCreate", Toast.LENGTH_SHORT).show();
        count = 0;
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service onDestroy", Toast.LENGTH_SHORT).show();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 服务被绑定时调用
     * 返回值用于让调用者和服务通信,传入ServiceConnection的public void onServiceConnected(ComponentName name, IBinder service)函数第二个参数
     */
    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

    public int getCount() {
        return count;
    }

    public int increaseCount() {
        return ++count;
    }

    public int decreaseCount() {
        return --count;
    }

    public class MyBinder extends Binder {

        MyService getService() {
            return MyService.this;
        }
    }
}

从上可以看出我们重写onBind函数并返回自己的Binder用于调用者和服务之间通信。下面我们在调用者中进行调用


定义自己的Service、Intent、ServiceConnection对象

private MyService         myService;

private Intent            myServiceIntent;

private ServiceConnection con = new ServiceConnection() {

                                  /**

                                   * 服务所在进程被kill或是crash时系统调用,而不是unbindService时调用

                                   */

                                  @Override

                                  public void onServiceDisconnected(ComponentName name) {

                                      Toast.makeText(getApplicationContext(), "Service disconnect",

                                                     Toast.LENGTH_SHORT).show();

                                  }

                                  /**

                                   * 服务连接时调用,若已经连接不进行调用

                                   */

                                  @Override

                                  public void onServiceConnected(ComponentName name, IBinder service) {

                                      myService = ((MyBinder)service).getService();

                                      Toast.makeText(getApplicationContext(), "Service Connect", Toast.LENGTH_SHORT).show();

                                  }

                              };



接着调用bindService(myServiceIntent, con, Context.BIND_AUTO_CREATE);

绑定服务,绑定成功返回true。

这时会执行ServiceConnection对象的onServiceConnected函数为myService变量赋值。接着我们就可以通过myService.increaseCount();操作Service的属性,myService.getCount()获得Service的属性,这样我们就成功和Service进行了通信。在不需要通信时通过unbindService(con);解除服务绑定。




b. 生命周期
通过bindService绑定服务,若服务未启动,会先执行Service的onCreate函数,再执行onBind函数,最后执行ServiceConnection对象的onServiceConnected函数。若服务已启动但尚未绑定,先执行onBind函数,再执行ServiceConnection对象的onServiceConnected函数。若服务已绑定成功,则直接返回。这里不会自动调用onStartCommand函数。
通过unbindService解除绑定服务,若已绑定成功,会先执行Service的onUnbind函数,再执行onDestroy函数,注意这里不会执行ServiceConnection对象的onServiceDisconnected函数,因为该函数是在服务所在进程被kill或是crash时被调用。若服务尚未绑定系统会报服务尚未注册异常,我们可以通过如下代码解决

if (myService != null) {
    unbindService(con);
  myService = null;
}

0 0