2019独角兽企业重金招聘Python工程师标准>>>

1.使用Intent进行异步通讯

在Service任务一旦完成后,就发送广播。开发者只需要实现一个BroadcastReceiver来监听响应既可。

Activity.startService启动intentService,intentService完成任务后sendBroadcast()发送广播,BroadcastReceiver.startActivity()通知Activity操作结果。

在任务结束后调用sendBroadcast(new Intent(Action));

然后在广播中通知Activity执行的结果。这种方法的优点是,Android提供了现成的机制,而不需要开发者自己构建复杂的组件间消息处理系统。

缺点是通知的结果受限于Intent,该方法也不适合在IntentService和Activity之间进行大规模快速更新操作,比如进度条,因为这会阻塞系统。

具体的代码就不多讲,和基本的Service一样使用,只是多实现了个广播.

2.本地绑定Service

本地绑定Service可以在Service中给Activity提供更复杂的回调,因为那些耗时的操作必须放到Service的后台线程中,所以Service大部分回调应该是异步的。实际的调用触发后台操作立即返回,一旦操作完成,Service使用回调接口来通知Activity相应的执行结果.

下面的例子添加了一个回调接口和一个实现AsyncTask的类,该类用来模拟后台操作。Service的onBind()方法返回一个localBinder对象,通过该对象客户端可以获取Service引用,并能执行doLongRunningOperation()方法。此方法创建了一个新的AsyncTask,并用客户端传递进来的参数执行execute()函数,在执行的过程中,回调函数会通知客户端新进度,当执行完毕会回调执行结果.

这个例子以下载图片讲解其详细的实现步骤

public class MyLocalService extends Service {
private static final int NOTIFICATION_ID = 1001;//通知的ID
private LocalBinder mLocalBinder = new LocalBinder();//用于返回的localBinder对象
private Callback mCallback;

@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return this.mLocalBinder;
}

public class LocalBinder extends Binder {
public MyLocalService getService() {
return MyLocalService.this;
}
}

public void setCallback(Callback callback) {
this.mCallback = callback;
}

//回调接口,便于Activity与Service进行通信
public interface Callback {
void onOperationProgress(int progress);

void onOperationCompleted(String result);
}

public void doLongRunningOperation(String urlString) {
new MyAsyncTask().execute(urlString);
}

private class MyAsyncTask extends AsyncTask<String, Integer, String> {

//处理任务之中
@Override
protected String doInBackground(String... params) {
publishProgress(0);//更新进度条
String result = downloadPhoto(params[0]);
publishProgress(10);
return result;
}

//执行任务之前
@Override
protected void onPreExecute() {
super.onPreExecute();
startForeground(NOTIFICATION_ID, buildNotification());//保持服务一直处于活跃状态。并创建通知
}

//返回任务执行结果
@Override
protected void onPostExecute(String result) {
if (mCallback != null) {
mCallback.onOperationCompleted(result);
}
mCallback.onOperationProgress(10);
stopForeground(true);
}

//进度条更新
@Override
protected void onProgressUpdate(Integer... values) {
if (mCallback != null && values.length > 0) {
for (Integer value : values) {
mCallback.onOperationProgress(value);
}
}
}

//任务(结束)调用取消后
@Override
protected void onCancelled(String result) {
// TODO Auto-generated method stub
super.onCancelled(result);
stopForeground(true);
}

}

//创建通知
private Notification buildNotification() {
Builder builder = new Builder(this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("正在下载");
builder.setContentText("图片还在下载中");
Notification notification = builder.getNotification();
return notification;
}

//下载图片
private String downloadPhoto(String uriString) {
HttpURLConnection conn = null;
try {
Thread.sleep(8000);
URL url = new URL(uriString);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(8000);
conn.setConnectTimeout(8000);
InputStream is = conn.getInputStream();
File file = new File(Environment.getExternalStorageDirectory()
.toString() + "/" + "book.jpg");

FileOutputStream fos = new FileOutputStream(file);
byte[] buf = new byte[8196];
int line = 0;
while ((line = is.read(buf)) != -1) {
fos.write(buf, 0, line);
}
fos.close();
return "下载完成";
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect();
}
}
return "下载失败";
}
}

下面的代码显示了更新后的Activity,值得注意的变化是Activity实现了MyLocalService.Callback接口,当在onServiceConnected()方法中获取到对Service的引用后,调用setCallback(this)方法,以便于Activity能在操作执行期间收到回调通知。还有一点非常重要,当用户离开Activity或者调用onPause()时,不要忘记移除回调监听,否则可能导致内存泄漏。

public class MainActivity extends Activity implements ServiceConnection,
MyLocalService.Callback {
private Button start;
private TextView content;
private MyLocalService mService;
private ProgressDialog dialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.start = (Button) findViewById(R.id.start);
this.content = (TextView) findViewById(R.id.content);

}

//启动Service里的AsyncTask线程

public void onTriggerLongRunningOperation(View view) {
if (this.mService != null) {
this.mService
.doLongRunningOperation("http://image.baidu.com/i?tn=download&word=download&ie=utf8&fr=detail&url=http%3A%2F%2Fwenwen.soso.com%2Fp%2F20090901%2F20090901120123-329341688.jpg&thumburl=http%3A%2F%2Fimg5.imgtn.bdimg.com%2Fit%2Fu%3D390263343%2C2695552076%26fm%3D21%26gp%3D0.jpg");
}
}

//进度条更新操作
@Override
public void onOperationProgress(int progress) {
if (dialog == null) {
dialog = new ProgressDialog(this);
dialog.setMessage("正在下载");
dialog.setMax(10);
dialog.setCanceledOnTouchOutside(false);
dialog.show();
} else {
dialog.setProgress(progress);
}
if (progress == 10 && dialog != null) {
dialog.dismiss();
}
}

@Override
public void onOperationCompleted(String result) {
this.content.setText(result);//设置下载图片的返回结果
}

//绑定服务后的初始化操作都写在该方法内
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
this.mService = ((MyLocalService.LocalBinder) service).getService();
this.mService.setCallback(this);
this.start.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
onTriggerLongRunningOperation(v);//执行Service下载线程
start.setEnabled(false);//设置启动按钮为不可用
}
});
}

//注销之前结束后的收尾操作
@Override
public void onServiceDisconnected(ComponentName name) {
this.mService = null;
}

@Override
protected void onResume() {
super.onResume();
Intent bindIntent = new Intent(this, MyLocalService.class);
bindService(bindIntent, this, BIND_AUTO_CREATE);//绑定Service
}

@Override
protected void onPause() {
super.onPause();
if (this.mService != null) {
this.mService.setCallback(null);
unbindService(this);//解绑Service
}
}
}

如果用户在操作执行完前离开了Activity,Service还会继续执行,因为显式调用了StartForeground()方法。如果Activity在操作结束前又重新恢复,它会在成功绑定到Service后继续调用继续接受回调。这种行为很容易把耗时的操作和用户界面分开。并且允许Activity恢复后还能继续获取运行的状态。

如果Service内部维护了一些状态,允许客户端获取这些状态以及订阅这些状态的变化是个很好的做法。因为当Activity重新恢复并绑定到Service后,这些状态可能已经发生了变化.

转载于:https://my.oschina.net/liyuanjinglyj/blog/414513

Service通信详解相关推荐

  1. OS--进程间通信详解(二)

    OS–进程间通信详解(二) 文章目录 OS--进程间通信详解(二) 一.进程间通信 1.互斥量 Futexes Pthreads中的互斥量 2.管程 3.消息传递 消息传递系统的设计要点 用消息传递解 ...

  2. OS--进程间通信详解(一)

    OS–进程间通信详解(一) 文章目录 OS--进程间通信详解(一) 一.进程间通信 1.竞态条件 2.临界区 3.忙等互斥 屏蔽中断 锁变量 严格轮询法 Peterson 解法 TSL指令 4.睡眠与 ...

  3. 容器编排技术 -- Kubernetes kubectl create service 命令详解

    容器编排技术 -- Kubernetes kubectl create service 命令详解 1 kubectl create service 2 语法 3 参考 kubectl create s ...

  4. Java串口通信详解(转)

    Java串口通信详解(转) 作者:denimcc 日期:2007-05-11 序言     说到开源,恐怕很少有人不挑大指称赞.学生通过开源代码学到了知识,程序员通过开源类库获得了别人的成功经验及能够 ...

  5. 【流媒体服务器Mediasoup】 NodeJs与C++信令通信详解及Linux下管道通信的详解(五)

    目录 前言 匿名管道进程间通信 进程间管道 的创建与图解 MediaSoup中的管道创建 MediaSoup Channel的创建 NodeJs和 C++ 管道通信的过程 MediaSoup 消息确认 ...

  6. 【STM32】标准库与HAL库对照学习教程八--串口通信详解

    [STM32]标准库与HAL库对照学习教程八--串口通信详解 一.前言 二.准备工作 三.通信的基本概念 1.通信方式 2.串行通信与并行通信 (1)串行通信 (2)并行通信 3.异步通信与同步通信 ...

  7. IIC通信协议(硬件实现IIC通信详解I)

    IIC通信协议 什么是IIC协议 协议层 起始信号和停止信号 数据的有效性 什么是IIC协议 I2C(Inter-Integrated Circuit)通讯协议是由 Phiilps 公司开发的两线式串 ...

  8. MATLAB与51单片机进行串口通信详解

    目录 一.51单片机与电脑进行串口通信 二.MATLAB串口通信函数 三.串口属性 四.示例Demo 4.1 MATLAB接收单片机发来的数据 4.2 MATLAB向单片机发送数据控制LED 五.总结 ...

  9. S5PV210串口通信详解

    S5PV210串口通信详解 S5PV210概述: S5PV210有4路独立,异步,串行的输入输出IO口,UART支持的通信速率达到3Mbps. 一个周期数据的组成:1位起始位,8位有效数据位,1位奇偶 ...

最新文章

  1. AC日记——小书童——刷题大军 洛谷 P1926
  2. 敏捷过程、极限编程和SCRUM的关系
  3. windows 下frp服务启动_内网穿透frp linux服务端搭建和windows客户端使用
  4. ElasticSearch 面试 4 连炮,你顶得住么?
  5. lookup无序查找_学习LOOKUP 函数实现无序查询
  6. python导入模块--案例
  7. 设计模式 命令模式 实例_根据您的命令-命令设计模式
  8. 【转】magento性能优化的教程(非常详细)
  9. 程序员面试金典 - 面试题 02.01. 移除重复节点(哈希set)
  10. 苹果11是高通基带吗_最强对抗!小米11对抗三星、苹果华为等最高旗舰|喜欢小米吗?...
  11. 彻底卸载oracle
  12. 根据当前登录域账号 获取AD用户姓名和所在OU目录
  13. linux 大文本文件,Linux文本文件处理(1)
  14. try except 异常捕获的方法、断言的使用
  15. SVN 冲突文件快速解决方法
  16. 界面控件Telerik UI for WinForm初级教程 - 系统要求 安装步骤
  17. 程序员英语5:number和digit都是数字,有什么区别?
  18. VMware安装win10镜像
  19. MyBatis学习总结-06:动态SQL
  20. 大数据处理基本思想——分治法

热门文章

  1. 生成xml报文方法并输出
  2. java ArrayList集合
  3. 设置TOMCAT TITLE 、 内存大小 、jdk路径
  4. ajax请求数据之后在已经有的数据前面打对勾的方法
  5. oracle数据库建表、修改字段名称类型、增加字段、ID自动增长写法
  6. vue各路径,组件都没问题,但页面空白
  7. NLP自然语言处理-Pytorch情感分析简介
  8. Spark常见优化原则
  9. 大数据可视化平台有什么特点
  10. Appium 屏幕页面滑动(swipe函数实现)