Android 数据绑定,android服务是什么

  Android 数据绑定,android服务是什么

  绑定服务是一种具有接口的服务,用于促进客户端和服务器之间的通信。服务允许组件(如活动)绑定它。组件可以发送请求、接收响应,并在进程间与服务进行通信。绑定服务通常的生命周期存在于它所服务的其他应用程序组件中,它不会总是在后台运行。

  本文告诉您如何创建绑定服务,包括如何绑定服务。

  基础知识

  服务允许其他组件绑定它并与之交互。为了使服务具有绑定功能,有必要实现onBind()方法,该方法返回IBinder对象,该对象定义了客户端如何与服务器通信。

  绑定到已启动的服务

  正如在服务文档中所讨论的,您可以创建一个既已启动又已绑定的服务。也就是说,可以通过调用startService()来启动服务,这允许服务无限期运行,也允许客户端通过调用bindService()来绑定到服务。

  如果您确实允许您的服务被启动和绑定,那么当服务被启动时,当所有客户端解除绑定时,系统不会销毁该服务。相反,您必须通过调用topSelf()或topService()来显式停止该服务。

  尽管您通常应该实现orenbind()或StartCommand(),但有时也有必要两者都实现。例如,音乐播放器可能会发现允许其服务无限期运行并提供绑定很有用。这样,活动可以启动服务来播放一些音乐,即使用户离开应用程序,音乐也会继续播放。然后,当用户返回到应用程序时,活动可以绑定到服务以重新获得对回放的控制。

  在向已启动的服务添加绑定时,请务必阅读关于管理绑定服务的生命周期一节,以获得关于服务生命周期的更多信息。

  客户端可以调用bindService()方法来绑定到服务。当它被绑定后,它必须提供serviceConnection的实现,该实现可以监控与服务的连接。bind()方法会立即返回,没有值。但是,当系统在客户端和服务器之间创建链接时,会调用ServiceConnection上的onServiceConnected(),并获取IBinder对象。

  一个服务可以同时连接到每个客户端。但是,当系统第一次调用onBind()时,只会返回IBinder对象。系统会将这个IBinder对象返回给绑定它的客户端,不会重复调用onBind()。

  没有客户绑定的时候,系统会销毁服务。

  在实现绑定服务时,定义IBinder接口非常重要。有许多方法可以定义这个接口,下面将会讨论。

  创建绑定服务

  要创建绑定服务,必须提供IBinder接口。有三种方法可以定义该接口:

  扩展Binder类如果这个服务只为当前的应用服务,并且运行在同一个进程中,那么创建的接口必须继承Binder类,并在onBind()方法中返回。客户可以通过它获得Binder对象,通过它可以直接访问常用功能。

  当服务只服务于自己的应用程序时,这是首选技术。

  使用Messenger如果需要在不同进程之间使用接口,可以使用Messenger为服务类创建接口。通过这种方式,服务定义了用于处理不同消息对象的处理程序。这个处理程序是Messenger的基础,它可以与客户共享IBinder,并允许客户用消息向服务发送命令。点,客户端可以自定义Messenger,这样服务就可以发回消息。

  这是进程间最简单的通信方式。因为Messenger队列中的所有请求都发生在一个线程上,所以不需要考虑服务的线程安全性。

  使用Aidlaidl (Android接口定义语言)可以将对象分解成系统可以识别的单元,已经达到了进程间通信的能力。在以前的技术中,所使用的信使实际上是基于AIDL的结构。如上所述,Messenger在一个线程中创建了所有客户请求的队列。如果希望服务同时处理多个请求,可以直接使用AIDL。在这种情况下,服务必须能够处理多线程,并且是线程安全的。

  要直接使用aidl,必须创建一个定义程序的接口文件,后缀为。AIDL。Android SDK工具可以通过这个文件生成实现这个接口并处理IPC的抽象类,自定义服务需要继承这个抽象类。

  注意:大多数应用不需要使用AIDL来创建绑定服务,因为它可能需要多线程功能,实现起来更复杂。就AIDL而言,它不适合大多数应用程序,本文将不讨论AIDL的使用。如果你需要直接使用AIDL,你可以查阅AIDL文档。

  扩展Binder类

  如果服务只在这个应用中使用,不需要进程间通信,从而实现客户端可以直接访问的Binder类,可以帮助客户端访问服务中的常用方法。

  注意:这个服务必须在同一个应用程序和进程中才能工作,这种方法也是最常见的。例如,在音乐应用程序中,activity需要与它自己服务绑定,以便在后台播放音乐。

  下面是设置它的方法:

  在服务中,创建一个Binder实例,它必须满足:

  包括客户端可以调用的常用方法。

  返回当前服务实例

  或者,返回另一个类的实例。

  onBind()方法返回一个Binder对象。

  在客户端,从onServiceConnected()获取Binder对象,调用提供的方法操作绑定服务。

  注意:服务和客户端之所以必须在同一个应用程序中,是因为客户端可以将返回的对象强制转换为合理的对象,以及调用它的API。服务和客户端必须在同一个进程中,这不能处理进程之间的信号处理。

  例如,下面是服务,客户端可以通过绑定器调用它的方法:

  publicsclasslocalserviceextendsservice {

  //给客户端的活页夹

  privatefinalIBinder MB inder=new local binder();

  //随机数生成器

  privatefinaldrandom mGenerator=new random();

  /**

  *用于客户端绑定器的类。因为我们知道这项服务总是

  *与客户端运行在相同的进程中,我们不需要处理IPC。

  */

  publicsclasslocalbinderextendsbinder {

  LocalService getService(){

  //返回LocalService的这个实例,以便客户端可以调用公共方法

  returnLocalService.this

  }

  }

  @覆盖

  publicIBinder onBind(意图intent){

  返回mBinder

  }

  /**客户端方法*/

  publicint getRandomNumber(){

  返回m generator . nextint(100);

  }}

  LocalService可以通过clientlocalbinder (getService())的常用方法获得。客户端可以通过这个服务调用它的公共方法。例如,客户端可以调用getRandomNumber()。

  以下活动绑定到LocalService,双击按钮时调用getRandomNumber():

  public class binding activity extends activity {

  LocalService mService

  boolean mBound=false

  @覆盖

  protected void onCreate(Bundle saved instancestate){

  super . oncreate(savedInstanceState);

  setContentView(r . layout . main);

  }

  @覆盖

  protectedvoid onStart(){

  super . onstart();

  //绑定到LocalService

  Intent intent=newIntent(this,local service . class);

  bindService(intent,mConnection,Context。BIND _ AUTO _ CREATE);

  }

  @覆盖

  protectedvoid onStop(){

  super . onstop();

  //解除与服务的绑定

  if(mBound){

  unbindService(MC connection);

  mBound=false

  }

  }

  /**单击按钮时调用(布局文件中的按钮附加到

  *此方法带有android:onClick属性)*/

  publicvoid onButtonClick(视图v){

  if(mBound){

  //从LocalService调用方法。

  //但是,如果这个调用可能会挂起,那么这个请求应该

  //发生在单独的线程中,以避免降低活动性能。

  int num=m服务。getrandomnumber();

  Toast.makeText(this, num: num,Toast .LENGTH_SHORT).show();

  }

  }

  /**定义服务绑定的回调,传递给bindService() */

  privateServiceConnection MC connection=newServiceConnection(){

  @覆盖

  public void onServiceConnected(组件名类名,

  对象服务){

  //我们已经绑定到本地服务,转换对象并获取本地服务实例

  LocalBinder binder=(LocalBinder)服务;

  m服务=装订器。获取服务();

  mBound=true

  }

  @覆盖

  public void onServiceDisconnected(组件名称参数0){

  mBound=false

  }

  };}

  上面的实例展示客户如何实现服务连接和实现服务连接的回调方法onServiceConnected()与服务绑定。

  注意:上面的例子并没有显示的取消和服务的绑定,所有的客户必须在合适的时候解除绑定(活动停止)。

  想了解更加详细的例子代码,可以在分类里面查找LocalService.java和LocalServiceActivities.java。

  使用信使

  与接口描述语言相比

  当您需要执行工业程序控制( industrial process control的缩写)时,为您的接口使用一个信使比用接口描述语言实现它更简单,因为一个信使会对服务的所有调用进行排队,而纯接口描述语言接口会同时向服务发送请求,然后服务必须处理多线程。

  对于大多数应用程序,服务不需要执行多线程,因此使用消息允许服务一次处理一个调用。如果你的服务是多线程的很重要,那么你应该使用aidlt来定义你的接口。

  如果服务需要与远程的进程通讯,可以用送信人;通信员为服务提供一个接口。这种技术可以处理进程间的通讯。

  下面是使用送信人;通信员的简介:

  服务要实现处理者,它可以收到每一个客户调用的回调。

  处理者用于创建送信人;通信员对象(这是对处理者的引用)。

  送信人;通信员创建一个伊宾德,客户调用onBind()时,IBinder要返回给客户的

  客户通过对象实例化信使(引用服务的句柄),信使为了客户发送消息对象到服务。

  服务通过处理者收到每一个消息,在handleMessage()方法明确的处理。

  利用这种方式,服务中没有方法可一个被客户调用客户。通过传递消息(消息)到服务的处理者中。

  下面是一个简单的例子,通过送信人;通信员的方式实现:

  publicsclassmessengerserviceextendsservice {

  /**命令到服务以显示消息*/

  静态final int MSG _ SAY _ HELLO=1;

  /**

  *客户端传入消息的处理程序。

  */

  类别incominghandlerextendshandler {

  @覆盖

  公共void句柄消息(Message msg){

  switch(msg.what){

  案例消息_说_你好:

  吐司。制作文本(getApplicationContext(), hello!,吐司. LENGTH_SHORT)。show();

  打破;

  默认值:

  超级棒。处理消息(msg);

  }

  }

  }

  /**

  *我们为客户端发布的目标,用于向IncomingHandler发送消息。

  */

  final messenger mMessenger=new messenger(newIncomingHandler());

  /**

  *当绑定到服务时,我们向送信人;通信员返回一个接口

  *用于向服务发送消息。

  */

  @覆盖

  publicIBinder onBind(意图意图){

  吐司。制作文本(getApplicationContext(), binding ,Toast).LENGTH_SHORT).show();

  返回马森格先生。get binder();

  }}

  主意:处理程序的handleMessage()方法收到消息,并且根据消息的什么变量确定需要做什么。

  客户的需要实现的是,基于返回的对象创建送信人;通信员对象,并且通过发送()发送消息给服务的处理程序。例如,下面的活动绑定了服务,而且传递MSG _ SAY _消息到服务中处理:

  publiclassactivitymessageextendssactive {

  /**用于与服务通信的信使.*/

  Messenger mService=null

  /**指示我们是否对服务调用了约束的标志。*/

  布尔姆本德

  /**

  *用于与服务的主接口交互的类。

  */

  privateServiceConnection MC connection=newServiceConnection(){

  public void onServiceConnected(组件名类名,IBinder服务){

  //当与服务的连接被

  //已建立,给了我们可以用来

  //与服务交互。我们正在与

  //服务,所以这里我们得到了一个客户端

  //原始对象对象的表示形式。

  mService=newMessenger(服务);

  mBound=true

  }

  public void onServiceDisconnected(组件名类名){

  //当与服务的连接被

  //意外断开连接——即其进程崩溃。

  mService=null

  mBound=false

  }

  };

  publicvoid sayHello(视图五){

  如果(!mBound)返回;

  //使用支持的“什么”值创建消息并将其发送到服务

  Message msg=Message.obtain(null,MessengerService .MSG_SAY_HELLO,0,0);

  尝试{

  mservice。发送(msg);

  }catch(远程异常e){

  e。printstacktrace();

  }

  }

  @覆盖

  受保护的void onCreate(Bundle saved instancestate){

  超级棒。oncreate(savedInstanceState);

  setContentView(r . layout。main);

  }

  @覆盖

  protectedvoid onStart(){

  超级棒。onstart();

  //绑定到服务

  bindService(newIntent(this,MessengerService.class),mConnection,

  语境. BIND _ AUTO _ CREATE);

  }

  @覆盖

  protectedvoid onStop(){

  超级棒。onstop();

  //解除与服务的绑定

  if(mBound){

  unbindService(MC连接);

  mBound=false

  }

  }}

  注意:这个例子没有体现服务是如何响应客户。如果想服务响应客户,需要在客户里面创建一个信使。当客户收到onServiceConnected()回调,就会发送消息到服务,发送()方法的消息变量回复包括客户端的信使。

  可以从MessengerService.java(服务)和messengerserviceactivities。Java(客户端)例子中知道如何提供双向通讯。

  绑定到服务

  应用的组件调用bindService()可以绑定服务。系统会调用服务的onBind()方法,返回一个伊宾德,以便组件能与服务很好的交互。

  绑定过程是异步bindService()能很快的返回,并且不会返回对象到客户端客户。收到对象时,会创建服务连接并且通过它绑定到服务。服务连接包括一个系统调用传递对象的方法。

  注意:仅仅活动、服务、和内容提供商能够与服务绑定-不能把广播收音机与服务绑定。

  因此,为了让客户与服务绑定,必须:

  实现服务连接。

  实现必须重写两个方法:

  onServiceConnected()系统调用这个函数来传递服务的onBind()方法返回的伊宾德.onservicedisconnected()Android系统在服务的连接意外丢失时调用这个函数,例如当服务崩溃或被终止时。当客户端解除绑定时,不会调用此函数。

  调用绑定服务(),传递服务连接的实现。

  当系统调用onServiceConnected()方法,就可以调用服务的方法,能调用的方法必须是定义在接口中的。

  调用取消绑定服务()取消与服务的连接。

  当客户销毁时,就会取消与服务的绑定,但是当做完任务或者活动停止的时候,要取消绑定,以便服务在不需要的时候能够停止

  例如,下面的一段代码通过继承粘合剂类,从而客户和服务可以绑定,因此,需要将返回的对象转换成本地服务,并取得本地服务对象:

  local service mServiceprivateServiceConnection MC connection=newServiceConnection(){

  //建立与服务的连接时调用

  public void onServiceConnected(component name class name,IBinder service){

  //因为我们已经绑定到一个显式的

  //在我们自己的进程中运行的服务,我们可以

  //将其IBinder强制转换为具体的类并直接访问它。

  LocalBinder binder=(LocalBinder)服务;

  m service=binder . get service();

  mBound=true

  }

  //当与服务的连接意外断开时调用

  public void onServiceDisconnected(component name class name){

  Log.e(标签, onServiceDisconnected );

  mBound=false

  }};

  通过这个ServiceConnection,客户端可以通过bindService()绑定服务。例如:

  Intent intent=newIntent(this,local service . class);

  bindService(intent,mConnection,Context。BIND _ AUTO _ CREATE);

  第一个变量是指定要通过意图绑定的服务。

  第二个参数是ServiceConnection对象。

  第三个参数是设置绑定的选项。通常是BIND_AUTO_CREATE,在服务没有运行的时候会自动创建。其他值有BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,或者是0(没有任何意义)。

  补充说明:

  以下是绑定服务时需要注意的事项:

  总是捕捉DeadObjectException异常,并在连接断开时将其抛出。这是远程方法抛出的唯一异常。

  按对象进程的引用计数。

  Bind和unbind与start和close方法成对出现。例如:

  当活动可见时,要与服务交互,需要在onStart()方法中绑定它,并在onStop()方法中解除绑定。

  当活动需要接收回复时,即使它已经在后台停止,它在onCreate()中被绑定,在onDestroy()中被解除绑定。这意味着您的活动需要在整个运行时间内使用该服务(即使它在后台运行)。因此,如果服务在另一个进程中,然后你增加了服务的权重,系统会先杀死它。注意:通常情况下,不能在onResume()和onPause()活动方法中绑定和解除绑定。这个回调函数在每一个生命周期的转变中都会发生,所以应该保证这个转变发生的越少越好。类似地,如果一个应用程序中有多个活动被绑定到同一个服务,并且两个活动中有多余的活动,那么当前一个活动被挂起时,服务将解除绑定,并重新绑定到另一个活动。(活动生命周期的协调在活动文档中)

  更多的例子,你可以在ApiDemos的RemoteService.java中看到如何绑定服务。

  管理绑定服务的生命周期

  当服务没有被任何客户端绑定时,android系统会将其杀死(除非中间有其他组件调用onStartCommand())。根据这个原理,不需要管理绑定服务的生命周期——Android系统会根据绑定原理自动管理服务。

  但是,如果选择onStartCommand()方法,则必须显式停止服务,因为服务的当前状态被视为已启动。在这种情况下,无论是否绑定了任何客户端,服务都会一直运行,直到stopSelf()或其他组件调用stopService()方法。这意味着当一个绑定的服务通过onStartCommand()启动时,需要stopSelf()和stopService()方法来停止它,即使中间绑定了其他客户端。

  补充了,如果服务已经启动并接受了客户端的绑定,那么当系统调用onUnbind()方法时,如果希望客户端下次绑定服务时调用onBind(),可以选择返回true,(而不是再次调用onBind())。onBind()返回void,但是客户端仍然接受onServiceConnected()中的IBinder。下图说明了上述逻辑。

  图一。启动并允许绑定的服务的生命周期。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • windowsandroid手机版下载,windowsandroid安装apk
  • windowsandroid手机版下载,windowsandroid安装apk,WindowsAndroid 安装教程详解
  • android调用webview方法,androidwebview是什么,Android 中 WebView 的基本用法详解
  • android传感器高级编程,Android传感器,Android编程之光线传感器用法详解
  • android.app.Dialog,android自定义dialog对话框,Android开发笔记之-Dialog的使用详解
  • android 图片视频轮播框架,androidlayout轮播图,Android实现炫酷轮播图效果
  • android里的viewpager,安卓自定义view流程,Android自定义引导玩转ViewPager的方法详解
  • android里的viewpager,android viewpager详解
  • android里的viewpager,android viewpager详解,Android自定义超级炫酷的ViewPage指示器
  • android调用webview方法,androidwebview是什么
  • android设置控件宽度,android获取屏幕宽度和高度
  • android设置控件宽度,android获取屏幕宽度和高度,Android中获取控件宽高的4种方法集合
  • android蓝牙开发的基本流程,安卓蓝牙app开发教程
  • android蓝牙开发的基本流程,安卓蓝牙app开发教程,android蓝牙简单开发示例教程
  • android菜单栏,android菜单控件
  • 留言与评论(共有 条评论)
       
    验证码: