深刻理解Android的startservice和bindservice

1、首先,让咱们确认下什么是service?
        service就是android系统中的服务,它有这么几个特色:它没法与用户直接进行交互、它必须由用户或者其余程序显式的启动、它的优先级比较高, 它比处于前台的应用优先级低,可是比后台的其余应用优先级高,这就决定了当系统由于缺乏内存而销毁某些没被利用的资源时,它被销毁的几率很小哦。
2、那么,何时,咱们须要使用service呢?
        咱们知道,service是运行在后台的应用,对于用户来讲失去了被关注的焦点。这就跟咱们打开了音乐播放以后,便想去看看图片,这时候咱们还不想音乐停 止,这里就会用到service;又例如,咱们打开了一个下载连接以后,咱们确定不想瞪着眼睛等他下载完再去作别的事情,对吧?这时候若是咱们想手机一边 在后台下载,一边可让我去看看新闻啥的,就要用到service。
3、service分类:
       通常咱们认为service分为两类,        <!-- service配置结束-->
第三步:在activity中进行启动、绑定、解绑或者中止service。
        (不少书上说,service与用户是不能交互的,其实这话很不正确,咱们彻底能够经过activity与service进行交互!我认为,确切的说法应该是service与用户不能进行直接的交互)。
android

-----------------------------安全

bindService介绍

1、bindService简介app

bindService是绑定Service服务,执行service服务中的逻辑流程。ide

service经过Context.startService()方法开始,经过Context.stopService()方法中止;也能够经过Service.stopSelf()方法或者Service.stopSelfResult()方法来中止本身。只要调用一次stopService()方法即可以中止服务,不管以前它被调用了多少次的启动服务方法。工具

客户端创建一个与Service的链接,并使用此链接与Service进行通话,经过Context.bindService()方法来绑定服务,Context.unbindService()方法来关闭服务。多个客户端能够绑定同一个服务,若是Service还未被启动,bindService()方法能够启动服务。学习

上面startService()和bindService()两种模式是彻底独立的。你能够绑定一个已经经过startService()方法启动的服务。例如:一 个后台播放音乐服务能够经过startService(intend)对象来播放音乐。可能用户在播放过程当中要执行一些操做好比获取歌曲的一些信息,此时 activity能够经过调用bindServices()方法与Service创建链接。这种状况下,stopServices()方法实际上不会中止 服务,直到最后一次绑定关闭。this

若是没有程序中止它或者它本身中止,service将一直运行。在这种模式 下,service开始于调用Context.startService() ,中止于Context.stopService(). service能够经过调用Android Service 生命周期() 或 Service.stopSelfResult()中止本身。无论调用多少次startService() ,只须要调用一次 stopService() 就能够中止service。spa

能够经过接口被外部程序调用。外部程序创建到service的链接,经过 链接来操做service。创建链接调开始于Context.bindService(), 结束于Context.unbindService(). 多个客户端能够绑定到同一个service,若是service没有启动, bindService() 能够选择启动它。线程

这2种模式不是彻底分离的。你能够能够绑定到一个经过startService()启动的服务。如 一个intent想要播放音乐,经过startService() 方法启动后台播放音乐的service。而后,也许用户想要操做播放器或者获取当前正在播放的乐曲的信息,一个activity就会经过 bindService()创建一个到此service的链接. 这种状况下 stopService() 在所有的链接关闭后才会真正中止service。code

2、bindService启动流程

context.bindService()  ——> onCreate()  ——> onBind()  ——> Service running  ——> onUnbind()  ——> onDestroy()  ——> Service stop

onBind()将返回给 客户端一个IBind接口实例,IBind容许客户端回调服务的方法,好比获得Service的实例、运行状态或其余操做。这个时候把调用者 (Context,例如Activity)会和Service绑定在一块儿,Context退出了,Srevice就会调用 onUnbind->onDestroy相应退出。

因此调用bindService的生命周期为:onCreate --> onBind(只一次,不可屡次绑定) --> onUnbind --> onDestory。

在Service每一次的开启关闭过程当中,只有onStart可被屡次调用(经过屡次startService调用),其余onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。

3、bindService生命周期

像一个activity那样,一个service有些能够用来改变状态的生命周期方法,可是比activity的方法少,service生命周期方法只有三个public

  void onCreate()

  void onStart(Intent intent)

  void onDestroy()

经过实现这三个生命周期方法,你能够监听service的两个嵌套循环的生命周期:

一、整个生命周期

service 的整个生命周期是在onCreate()和onDestroy()方法之间。和activity同样,在onCreate()方法里初始化,在 onDestroy()方法里释放资源。例如,一个背景音乐播放服务能够在onCreate()方法里播放,在onDestroy()方法里中止。

二、活动的生命周期

service 的活动生命周期是在onStart()以后,这个方法会处理经过startServices()方法传递来的Intent对象。音乐service能够通 过开打intent对象来找到要播放的音乐,而后开始后台播放。注: service中止时没有相应的回调方法,即没有onStop()方法,只有onDestroy()销毁方法。

任何服务不管它怎样创建,默认客户端均可以链接,因此任何service都可以接收onBind()和onUnbind()方法

onCreate()方法和onDestroy()方法是针对全部的services,不管它们是否启动,经过Context.startService()和Context.bindService()方法均可以访问执行。然而,只有经过startService()方法启动service服务时才会调用onStart()方法
 

若是一个service容许别人绑定,那么须要实现如下额外的方法:

      IBinder onBind(Intent intent)

      boolean onUnbind(Intent intent)

      void onRebind(Intent intent)

onBind()回调方法会继续传递经过bindService()传递来的intent对象

onUnbind()会处理传递给unbindService()的intent对象。若是service容许绑定,onBind()会返回客户端与服务互相联系的通讯句柄(实例)。

若是创建了一个新的客户端与服务的链接,onUnbind()方法能够请求调用onRebind()方法。

4、bindService和startservice示例

(1)mainactivity

public class MainActivity extends Activity {
    Button startServiceButton;// 启动服务按钮
    Button shutDownServiceButton;// 关闭服务按钮
    Button startBindServiceButton;// 启动绑定服务按钮
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        getWidget();
        regiestListener();
    }

    /** 得到组件 */
    public void getWidget() {
        startServiceButton = (Button) findViewById(R.id.startServerButton);
        startBindServiceButton = (Button) findViewById(R.id.startBindServerButton);
        shutDownServiceButton = (Button) findViewById(R.id.sutdownServerButton);
    }

    /** 为按钮添加监听 */
    public void regiestListener() {
        startServiceButton.setOnClickListener(startService);
        shutDownServiceButton.setOnClickListener(shutdownService);
        startBindServiceButton.setOnClickListener(startBinderService);
    }
    
    
    /** 启动服务的事件监听 */
    public Button.OnClickListener startService = new Button.OnClickListener() {
        public void onClick(View view) {
            /** 单击按钮时启动服务 */
            Intent intent = new Intent(MainActivity.this,
                    CountService.class);
            startService(intent);
            
            Log.v("MainStadyServics", "start Service");
        }
    };
    /** 关闭服务 */
    public Button.OnClickListener shutdownService = new Button.OnClickListener() {
        public void onClick(View view) {
            /** 单击按钮时启动服务 */
            Intent intent = new Intent(MainActivity.this,
                    CountService.class);
            /** 退出Activity是,中止服务 */
            stopService(intent);
            Log.v("MainStadyServics", "shutDown serveice");
        }
    };
    /** 打开绑定服务的Activity */
    public Button.OnClickListener startBinderService = new Button.OnClickListener() {
        public void onClick(View view) {
            /** 单击按钮时启动服务 */
            Intent intent = new Intent(MainActivity.this, UseBrider.class);
            startActivity(intent);
            Log.v("MainStadyServics", "start Binder Service");
        }
    };
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

 

(2)service

package com.example.testservice;

/**引入包*/
import android.app.Service;// 服务的类
import android.os.IBinder;
import android.os.Binder;
import android.content.Intent;
import android.util.Log;

/** 计数的服务 */
public class CountService extends Service {
    /** 建立参数 */
    boolean threadDisable;
    int count;

    public IBinder onBind(Intent intent) {
        return null;
    }

    public void onCreate() {
        super.onCreate();
        /** 建立一个线程,每秒计数器加一,并在控制台进行Log输出 */
        new Thread(new Runnable() {
            public void run() {
                while (!threadDisable) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {

                    }
                    count++;
                    Log.v("CountService", "Count is" + count);
                }
            }
        }).start();
    }

    public void onDestroy() {
        super.onDestroy();
        /** 服务中止时,终止计数进程 */
        this.threadDisable = true;
    }

    public int getConunt() {
        return count;
    }

//此方法是为了能够在Acitity中得到服务的实例   

class ServiceBinder extends Binder {
        public CountService getService() {
            return CountService.this;
        }
    }
}

 

(3)bindservice(必定要记着这个是要得到,连接的对象)

package com.example.testservice;

/**引入包*/
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

/** 经过bindService和unBindSerivce的方式启动和结束服务 */
public class UseBrider extends Activity {
    /** 参数设置 */
    CountService countService;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new UseBriderFace(this));
        
        Intent intent = new Intent(UseBrider.this, CountService.class);
        /** 进入Activity开始服务 */
        bindService(intent, conn, Context.BIND_AUTO_CREATE);

    }

    
    private ServiceConnection conn = new ServiceConnection() {
        /** 获取服务对象时的操做 */
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            countService = ((CountService.ServiceBinder) service).getService();

        }

        /** 没法获取到服务对象时的操做 */
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            countService = null;
        }

    };

    protected void onDestroy() {
        super.onDestroy();
        this.unbindService(conn);
        Log.v("MainStadyServics", "out");
    }
}

 

注意:这个地方有朋友可能会出现onServiceConnected不调用的状况。

这个问题当调用bindService方法后就会回调Activity的onServiceConnected,在这个方法中会向Activity中传递一个IBinder的实例,Acitity须要保存这个实例

在Service中须要建立一个实现IBinder的内部类(这个内部类不必定在Service中实现,但必须在Service中建立它)。

在OnBind()方法中需返回一个IBinder实例,否则onServiceConnected方法不会调用。

不过,我在这里传递null也可以调用,你们根据状况进行断定吧,若是是返回一个ibinder实例的话,示例代码以下:

public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        System.out.println("onBind.....");
         IBinder result = null;  
            if ( null == result ) result = new MyBinder() ;
        Toast.makeText(this, "onBind",Toast.LENGTH_LONG);
        return result;
    }

 

至于startservice和bindservice的使用场景,有网友这么说:

1.经过startservice开启的服务.一旦服务开启, 这个服务和开启他的调用者之间就没有任何的关系了.
调用者不能够访问 service里面的方法. 调用者若是被系统回收了或者调用了ondestroy方法, service还会继续存在 
2.经过bindService开启的服务,服务开启以后,调用者和服务之间 还存在着联系 ,
一旦调用者挂掉了.service也会跟着挂掉 .

 

示例下载地址:http://pan.baidu.com/share/link?shareid=1614272126&uk=1428765741

还有一个多样化的demo学习地址:http://pan.baidu.com/share/link?shareid=1616100229&uk=1428765741

 

内容来源于互联网,感谢做者的无私提供

相关文章
相关标签/搜索