深入理解Android的startservice和bindservice

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

-----------------------------

bindService介绍

一、bindService简介

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

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()方法实际上不会停止 服务,直到最后一次绑定关闭。

如果没有程序停止它或者它自己停止,service将一直运行。在这种模式 下,service开始于调用Context.startService() ,停止于Context.stopService(). service可以通过调用Android Service 生命周期() 或 Service.stopSelfResult()停止自己。不管调用多少次startService() ,只需要调用一次 stopService() 就可以停止service。

可以通过接口被外部程序调用。外部程序建立到service的连接,通过 连接来操作service。建立连接调开始于Context.bindService(), 结束于Context.unbindService(). 多个客户端可以绑定到同一个service,如果service没有启动, bindService() 可以选择启动它。

这2种模式不是完全分离的。你可以可以绑定到一个通过startService()启动的服务。如 一个intent想要播放音乐,通过startService() 方法启动后台播放音乐的service。然后,也许用户想要操作播放器或者获取当前正在播放的乐曲的信息,一个activity就会通过 bindService()建立一个到此service的连接. 这种情况下 stopService() 在全部的连接关闭后才会真正停止service。

二、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在一个生命周期中只能被调用一次。

三、bindService生命周期

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

  void onCreate()

  void onStart(Intent intent)

  void onDestroy()

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

1、整个生命周期

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

2、活动的生命周期

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

任何服务无论它怎样建立,默认客户端都可以连接,所以任何service都能够接收onBind()和onUnbind()方法

四、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 stubSystem.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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401634.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PWA(Progressive Web App)入门系列:Notification

前言 在很多场景下&#xff0c;需要一种通知的交互方式来提醒用户&#xff0c;传统方式下可以在页面实现一个 Dialog&#xff0c;或通过修改网页的 title 来实现消息的通知。然而传统的实现存在着一定的不足&#xff0c;在网页最小化的情况下&#xff0c;无法查看任何通知&…

PWA(Progressive Web App)入门系列:Push

前言 很多时候&#xff0c;原生应用会通过一些消息推送来唤起用户的关注&#xff0c;增加驻留率。网页该怎么做呢&#xff1f;有没有类似原生应用的推送机制&#xff1f;推送功能又能玩出什么花样呢&#xff1f; Push API Push API 给与了 Web 应用程序接收从服务器发出的推送…

Dom学习笔记

DOM document object model 文档 对象 模型 文档&#xff1a;html页面 文档对象&#xff1a;页面中的元素 文档对象模型: 文档对象模型是w3c 为了能够让js去操作页面中的元素&#xff0c;定义的一套标准 DOM会把当前文档看作一棵树 树种的每一个元素就是文档树 的一个节点 同…

PWA(Progressive Web App)入门系列:消息通讯

前言 serviceWorker 的能力决定它要处理的事情&#xff0c;网站页面的部分逻辑处理会转移到 serviceWorker 层进行处理&#xff0c;这里就要页面层和 serviceWorker 层进行交互来实现消息通讯。 下面就说一下两个环境下的消息通讯。 窗口向 serviceWorker 通讯 这里列举出窗…

查看Linux上程序或进程用到的库

为什么80%的码农都做不了架构师&#xff1f;>>> ldd /path/to/program 要找出某个特定可执行依赖的库&#xff0c;可以使用ldd命令。这个命令调用动态链接器去找到程序的库文件依赖关系。 objdump -p /path/to/program | grep NEEDED 注意&#xff01;并不推荐为任…

超方便的 IndexDB 库

前言 做为 Web 浏览器层的本地存储&#xff0c;IndexDB 做为一个很好的选择&#xff0c;几乎可以存储任意类型的数据&#xff0c;且是异步的。但是正常使用方式下需要在监听各种事件来处理结果&#xff0c;不是很方便&#xff0c;下面就对这一层进行了包装&#xff0c;使用方便…

BP网络识别26个英文字母matlab

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;字母识别 获取完整源码源工程文件 一、 设计思想 字符识别在现代日常生活的应用越来越广泛&#xff0c;比如车辆牌照自动识别系统&#xff0c;手写识别系统&#xff0c;办公自动化等等。本文采用BP网络对26个英文字母进行…

PWA(Progressive Web App)入门系列:Sync 后台同步

前言 当我们在一些地下停车场&#xff0c;或者在火车上、电梯等无法避免的信号不稳定的场所&#xff0c;使用网站应用处理一些表单操作或者上传数据的操作时&#xff0c;面临的将是网络连接错误的响应&#xff0c;使用户的操作白费。 而此刻 PWA 的 Sync API 就很好的解决了这…

PWA(Progressive Web App)入门系列:安装 Web 应用

前言 在传统的 Web 应用中&#xff0c;通常只能通过在浏览器的地址栏里输入相应的网址才能进行访问&#xff0c;或者把网页地址创建到桌面上通过点击&#xff0c;然后在浏览器里打开。 传统模式下&#xff0c;图标、启动画面、主题色、视图模式、屏幕方向等等都无法去自定义和…

「工具」IndexDB 版备忘录

前言 工作日常需要做一些备忘录&#xff0c;记录一些要做的事。在 Mac 上有使用系统的备忘录&#xff0c;但功能偏弱且文本格式调整不方便。再就是使用浏览器找专门的备忘录网站&#xff0c;功能是满足了&#xff0c;但是链路长&#xff0c;没有桌面软件直接。 所以最后干脆自…

「工具」PWA Manifest图标及 favicon.ico 生成工具

PWA 其中有一个能力就是把网站安装到系统桌面&#xff0c;以原生应用的体验来运行网站&#xff0c;使用户无需再找开浏览器输入网址进入网站&#xff0c;而是可以直接点击安装好的应用直接运行&#xff0c;给使网站访问缩短路径及增加网站的曝光度。 其中有一个问题就是需要生…

各种浏览器缓存浅析

前言 目前浏览器的缓存类型众多&#xff0c;HTTP Cache、Disk Cache、Memory Cache、ServiceWorker Cache、Push Cache 等等&#xff0c;这些缓存是如何产生的&#xff1f;命中优先级是怎么样&#xff1f;又该如何去使用它们&#xff1f; Disk Cache、Memory Cache Disk Cac…

[工具]TS 视频合并工具

简介 当下载 m3u8 资源时&#xff0c;通常产生的是多个 ts 视频文件&#xff0c;所以需要借助某些工具来将这些 ts 视频片段整合为一个视频文件。 本软件主要解决的就是这个问题&#xff0c;底层基于ffmpeg&#xff0c;可正常运行在 Windows 和 Mac 平台。不仅可以合并 ts 为单…

[会议分享]2020全球软件大会分享-PWA在项目中的最佳实践

大会地址&#xff1a;https://www.bagevent.com/event/1233659# PPT下载&#xff1a;https://download.csdn.net/download/lecepin/12871373

「浏览器插件」非常好用的JSON-View

Chrome 商店&#xff1a;地址 下载地址&#xff1a;地址 Github&#xff1a;https://github.com/lecepin/lp-json-view 查看/格式化 二合一。 功能 自动识别 JSON 内容&#xff0c;并在页面右下角创建切换按钮。支持展开/折叠节点。支持全部展开、全部折叠、展开一二三层节点…

Github Action 快速构建 Electron 应用

前言 在开发 Electron 应用时&#xff0c;比较耗时的部分应该是构建打包的过程&#xff0c;像用 electron-builder 这种打包工具来说&#xff0c;它会根据你要打包的系统来下载应用的系统镜像打包工具&#xff0c;由于这些镜像的源文件托管在 Github 上&#xff0c;且 nodejs …

「浏览器插件」网址小尾巴终结者

前言 在我们日常的开发调试中&#xff0c;会在 URL 上添加一些特殊的小尾巴 用来显示调试界面或者开启一些特殊功能&#xff0c;当你接触了越来越多的系统后&#xff0c;你需要使用的小尾巴就变得越来越多&#xff0c;记忆和使用成本非常大&#xff0c;以及含有小尾巴的网址 在…

什么是低代码?

低代码 是一种软件开发方法&#xff0c;可以减少手工编码的过程&#xff0c;尽可能快的交付应用程序。 低代码平台 是工具的合集&#xff0c;这些工具可以通过建模和图形界面来进行应用程序的可视化开发。低代码使开发人员可以跳过手工编码&#xff0c;从而加快了应用程序的开…

什么是 LOW-CODE ?

低代码平台的特征 可视化建模工具 使用可视化方法和模型创建应用程序比使用代码进行开发要快。具有可视化建模功能的低代码平台&#xff0c;使用内置的组件&#xff0c;以任何人都可读的形式表示任何信息&#xff0c;从没有技术技能的常规企业用户到专业开发人员。 开箱即用…

简简单单 上传下载

背景 我们经常会有手机向电脑传文件 或者 电脑像手机传文件的需求。 而通常的解决方案是&#xff1a;手机上安装一个聊天软件&#xff08;如微信&#xff09;&#xff0c;电脑上安装一个聊天软件&#xff0c;然后自己给自己传输&#xff0c;然后进行下载。 这种方式是很麻烦的…