Android学习八 Service服务

来源:互联网 发布:矩阵乘以矩阵的转置 编辑:程序博客网 时间:2024/05/11 10:41

         Service是Android四大组件之一,它不能自己运行只能在后台运行,并且可以和其他组件进行交互。它主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。

一、开启服务

1、startService方式开启服务

1.1创建一个类继承自Service,

1.2在MainActivity中开启服务

Intent intent = new Intent(this, FirstService.class);// 开启服务startService(intent);

1.3在清单文件中对服务进行配置

<service android:name="..."> </service>

start方式开启服务的特点:

 (1)服务通过startservice方式开启 第一次点击按钮开启服务 会执行服务的onCreate 和 onStart方法
  (2)如果第二次开始在点击按钮开启服务 服务之后执行onStrat方法
  (3)服务被开启后 会在设置页面里面的 running里面找得到这个服务
  (4)startservice 方式开启服务 服务就会在后台长期运行 直到用户手工停止 或者调用StopService方法 服务才会被销毁(重要)

2、bindService方式开启服务

2.1创建一个类继承自Service

2.2开启服务

///开启服务 Intent intent = new Intent(this,TestService.class);//连接服务 TestServiceMyConn conn = new  MyConn();//绑定服务 bindService(intent, conn, BIND_AUTO_CREATE);
//监视服务的状态private class MyConn implements ServiceConnection{//当连接服务成功后@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {//[4]获取我们定义的中间人对象 myBinder = (MyBinder) service;}//失去连接@Overridepublic void onServiceDisconnected(ComponentName name) {}}

2.3对服务进行声明(同上)

使用bindService开启服务的特点:

  (1)当点击按钮第一次开启服务 会执行服务的onCreate方法 和 onBind()方法
   (2) 当我第二次点击按钮在调用bindservice  服务没有响应
   (3) 当activity销毁的时候服务也销毁  (重要)
  (4)通过bind方式开启服务  服务不能再设置页面里面找到  相当于是一个隐形的服务
  (5)bindservice不能多次解绑 多次解绑会报错

需要注意的是,使用bindService开启服务时,一定要记得在destory()中调用unbindService(conn);对服务进行解绑,否则可能会报Activity has leaked的错误。

二、服务的声明周期

左图为start方式开启,有图bind方式开启。

startService方式开启服务的大体流程为:onCreate(只在创建的时候调用一次直到被摧毁) --> onStartCommand (服务开启后,可多次调用) --> onDestroy。

bindService方式开启服务的生命周期为:onCreate --> onBind --> onUnbind --> onDestory。

三、Activity和服务的交互

          有时我们需要在Activity中调用服务中的方法,但是又不能直接new一个服务出来(会有问题)。这时就要使用bindService解决了。看下面的代码:

private MyBinder myBinder; //@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);////开启服务 Intent intent = new Intent(this,TestService.class);//连接服务 TestServiceMyConn conn = new  MyConn();//绑定服务 bindService(intent, conn, BIND_AUTO_CREATE);}//点击按钮 调用TestService 服务里面的办证方法 public void click(View v) {//通过我们定义的binder对象 间接调用服务里面的方法myBinder.callBanZheng(102);}//监视服务的状态private class MyConn implements ServiceConnection{//当连接服务成功后@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {//[4]获取在service中定义的binder对象 myBinder = (MyBinder) service;}//失去连接@Overridepublic void onServiceDisconnected(ComponentName name) {}}
public class TestService extends Service {//当bindservice @Overridepublic IBinder onBind(Intent intent) {//[3]把我们定义的binder对象返回return new MyBinder();}@Overridepublic void onCreate() {super.onCreate();}//要调用的方法public void banZheng(int money){if (money > 1000) {Toast.makeText(getApplicationContext(), "我是领导 把证给你办了", 1).show();}else{Toast.makeText(getApplicationContext(), "这点钱 还想办事", 1).show();} }//[1定义一个Binder对象 ]public  class MyBinder extends Binder{//[2]定义一个方法 调用办证的方法 public void callBanZheng(int money){banZheng(money);}}}
在Service中定义一个类继承自Binder,将要调用的方法封装进这个类中,然后在onBind方法中返回这个类的一个实例。然后在Activity自己定义的监听服务连接状态的类(即实现了ServiceConnection的类)中就可以获得这个binder实例(当连接成功时),然后通过这个binder实例去调用service中的方法。还可以通过接口的方式对自己定义的Binder类进行封装来隐藏代码内部的细节,暴露那些想暴露的方法,隐藏其他方法。下面是增加了接口后的代码,其他代码同上:

private  class MyBinder extends Binder implements Iservice{public void callBanZheng(int money){banZheng(money);}}
public interface Iservice {//把想暴露的方法 都定义在接口里面 public void callBanZheng(int money);}
四、bindService和startService混合使用

     使用bindService开启服务可以调用服务里的方法,但是当Activity销毁时它也会被销毁。那么如果即想让服务长期在后台执行,又想调用服务里的方法时,就需要这两者混合使用了。先调用startService开启服务,再调用bindService开启服务,代码如下:

//[0]先调用startservice 方法开启服务 保证服务在后台长期运行Intent intent = new Intent(this, MusicService.class);startService(intent);// [1]调用bindservice 目的是为了获取我们定义的binder对象conn = new MyConn();bindService(intent, conn, BIND_AUTO_CREATE);
这样就可以实现即是服务长期在后台执行,又可以调用服务中的方法了。

原创粉丝点击