Service与Activity通信 回调方式***
要实现service与activity的高强度通信用什么方法?
service与activity之前的通信方式有很多,回调接口方式、观察者模式、广播、还有handler等,方法有很多,但要高强度地通信,个人觉得还是用回调接口的方式比较妥当(虽然本人开始也是用的传入的handler。。。哈哈,用handler的话,如果涉及到service要向多个activity传送数据就变得麻烦了)。所以在这里记录下回调接口的方式进行通信:
1、怎样在启动一个Service时向它传递数据
关键点:Intent传值,onStartCommand()接收。
2、怎样向运行的Service中同步数据
关键点:通过onBind()获取Service实例,然后再调用Binder中的相关方法。
3、怎样侦听Service中数据变化
关键点:通过回调函数达到目的。
一、准备Service
先贴出Service的详细代码,然后再慢慢分析
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Binder;
public class MyService extends Service {
private String data = "默认消息";
private boolean serviceRunning = false;
// 必须实现的方法,用于返回Binder对象
@Override
public IBinder onBind(Intent intent) {
System.out.println("--onBind()--");
return new MyBinder();
}
public class MyBinder extends Binder {
MyService getService() {
return MyService.this;
}
public void setData(String data) {
MyService.this.data = data;
}
}
// 创建Service时调用该方法,只调用一次
@Override
public void onCreate() {
super.onCreate();
System.out.println("--onCreate()--");
serviceRunning = true;
new Thread() {
@Override
public void run() {
int n = 0;
while (serviceRunning) {
n++;
String str = n + data;
System.out.println(str);
if (dataCallback != null) {
dataCallback.dataChanged(str);
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
}
// 每次启动Servcie时都会调用该方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("--onStartCommand()--");
data = intent.getStringExtra("data");
return super.onStartCommand(intent, flags, startId);
}
// 解绑Servcie调用该方法
@Override
public boolean onUnbind(Intent intent) {
System.out.println("--onUnbind()--");
return super.onUnbind(intent);
}
// 退出或者销毁时调用该方法
@Override
public void onDestroy() {
serviceRunning = false;
System.out.println("--onDestroy()--");
super.onDestroy();
}
DataCallback dataCallback = null;
public DataCallback getDataCallback() {
return dataCallback;
}
public void setDataCallback(DataCallback dataCallback) {//注意这里以单个回调为例 如果是向多个activity传送数据 可以定义一个回调集合 在此处进行集合的添加
this.dataCallback = dataCallback;
}
// 通过回调机制,将Service内部的变化传递到外部
public interface DataCallback {
void dataChanged(String str);
}
}
代码分析:我们都知道,通过startService启动一个Service时,Service会调用生命周期函数onStartCommand(),在代码中创建一个Service,在onStartCommand()方法中获取从Activity传递过来的数据,并在Service的onCreate()方法中开启一个新的线程,使其循环调用回调函数,以达到通知外界信息改变的目的。并在Service中通过Binder类,将Service与Activity链接起来,以实现信息同步。
二、准备布局文件
布局文件比较简单,直接贴出,就不分析了,activity_main.xml如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <TextView
android:id="@+id/tv_out"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="显示区域" /> <EditText
android:id="@+id/et_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" > <requestFocus />
</EditText> <Button
android:id="@+id/btn_start_service"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="startService" /> <Button
android:id="@+id/btn_stop_service"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="stopService" /> <Button
android:id="@+id/btn_bind_service"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="bindService" /> <Button
android:id="@+id/btn_unbind_service"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="unbindService" /> <Button
android:id="@+id/btn_sync_data"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="同步数据" /> </LinearLayout>
三、准备Activity
MainActivity代码如下:
public class MainActivity extends Activity implements OnClickListener {
private Intent intent = null;
private Button btn_start_service;
private Button btn_stop_service;
private Button btn_bind_service;
private Button btn_unbind_service;
private Button btn_sync_data;
private EditText et_data;
private TextView tv_out;
MyServiceConn myServiceConn;
MyService.MyBinder binder = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, MyService.class);
myServiceConn = new MyServiceConn();
setOnClick();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start_service:
//用intent启动Service并传值
intent.putExtra("data", et_data.getText().toString());
startService(intent);
break;
case R.id.btn_stop_service:
//停止Service
stopService(intent);
break;
case R.id.btn_bind_service:
//绑定Service
bindService(intent, myServiceConn, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_unbind_service:
//解绑Service
if (binder != null) {
unbindService(myServiceConn);
}
break;
case R.id.btn_sync_data:
//注意:需要先绑定,才能同步数据
if (binder != null) {
binder.setData(et_data.getText().toString());
}
break;
default:
break;
}
}
class MyServiceConn implements ServiceConnection {
// 服务被绑定成功之后执行
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// IBinder service为onBind方法返回的Service实例
binder = (MyService.MyBinder) service;
binder.getService().setDataCallback(new MyService.DataCallback() {
//执行回调函数
@Override
public void dataChanged(String str) {
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("str", str);
msg.setData(bundle);
//发送通知
handler.sendMessage(msg);
}
});
}
@SuppressLint("HandlerLeak")
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
//在handler中更新UI
tv_out.setText(msg.getData().getString("str"));
};
};
// 服务奔溃或者被杀掉执行
@Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
}
}
private void loadUI() {
btn_start_service = (Button) findViewById(R.id.btn_start_service);
btn_stop_service = (Button) findViewById(R.id.btn_stop_service);
btn_bind_service = (Button) findViewById(R.id.btn_bind_service);
btn_unbind_service = (Button) findViewById(R.id.btn_unbind_service);
btn_sync_data = (Button) findViewById(R.id.btn_sync_data);
et_data = (EditText) findViewById(R.id.et_data);
tv_out = (TextView) findViewById(R.id.tv_out);
}
private void setOnClick() {
loadUI();
btn_start_service.setOnClickListener(this);
btn_stop_service.setOnClickListener(this);
btn_bind_service.setOnClickListener(this);
btn_unbind_service.setOnClickListener(this);
btn_sync_data.setOnClickListener(this);
}
}
代码分析:
1、加载UI,初始化变量啥的跳过了,主要说一下关键代码,在第28代码中,与启动一个Activity类似,通过Intent想要启动的Service传递参数。
2、在37行通过bindService绑定Service,然后在ServiceConnection中获取Service类中onBind方法返回的实例,获取实例Service实例后,我们就可以通过调用Service中MyBinder的setData()方法对Service进行同步数据,如48行所示。
3、整个过程,在Service的onCreate方法中都会循环调用回调函数,同时我们在MainActivity中重写回调方法以实现更新UI。
四、测试
1、启动示例后,在输入框输入你好,然后点击startService,界面和对应的日志如下:

看了下面的代码后就会知道,此时因为没有绑定service,所以办法执行回调函数更新UI,所以显示区域没有更新。
2、点击bindService后,界面如下:

当执行bindService后,在ServiceConnection方法中就会执行执行回调函数更新UI,此时显示区域开始更新。
3、改变输入框内容,点击同步数据,界面和对应的日志如下:

Service与Activity通信 回调方式***的更多相关文章
- Android学习笔记(九)一个例子弄清Service与Activity通信
上一篇博文主要整理了Service的创建.绑定过程,本篇主要整理一下Service与Activity的通信方式.包括在启动一个Service时向它传递数据.怎样改变运行中的Service中得数据和侦听 ...
- 本地/远程Service 和Activity 的交方式(转)
android SDK提供了Service,用于类似*nix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Remo ...
- Android开发学习之路-该怎么学Android(Service和Activity通信为例)
在大部分地方,比如书本或者学校和培训机构,教学Android的方式都基本类似,就是告诉先上原理方法,然后对着代码讲一下. 但是,这往往不是一个很好的方法,为什么? ① 学生要掌握这个方法的用途,只能通 ...
- activity 与 service 之间的通信
activity和service通信:通过binder 举个我实际项目中的例子:在service中下载更新应用 首先是下载更新apk的service: public class UpdateVersi ...
- android开发之使用Messenger实现service与activity交互
service与activity交互的方式有多种,这里说说使用Messenger来实现两者之间的交互. Service程序 public class MessengerService extends ...
- Android Service与Activity之间通信的几种方式
在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activ ...
- Activity与Service通信的方式有三种:
在博客园看到的,看着挺不错的,借来分享下 继承Binder类 这个方式仅仅有当你的Acitivity和Service处于同一个Application和进程时,才干够用,比方你后台有一个播放背景音乐的S ...
- Android中Service与多个Activity通信
由于项目需要,我们有时候需要在service中处理耗时操作,然后将结果发送给activity以更新状态.通常情况下,我们只需要在一个service与一个activity之间通信,通常这种情况下,我们使 ...
- Android Service与Activity之间通信
主要分为: 通过Binder对象 通过broadcast(广播)的形式 Activity调用bindService (Intent service, ServiceConnection conn, i ...
随机推荐
- WinRAR捆绑木马
准备好木马文件 server.exe 准备一个小游戏 趣味数学计算 压缩 创建自解压格式压缩文件 自解压选项设置 解压路径设置 设置程序 模式设置 压缩完成 使用 开始玩游戏
- css 和常用快捷键
一.css概述: 1.规则:CSS 规则由选择器,以及一条或多条声明两个部分构成. 2.选择器:选择器通常是您需要改变样式的 HTML 元素. 3.声明:声明是您要设置的样式(每条声明由一个属性和一个 ...
- 【函数】wm_concat包的订制
[函数]wm_concat包的订制 1 BLOG文档结构图 2 前言部分 2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道 ...
- es截取指定的字段返回
SearchResponse response = client.prepareSearch(index_name).setTypes("lw_devices") .setFrom ...
- MySQL高可用架构应该考虑什么? 你认为应该如何设计?
一.MySQL高可用架构应该考虑什么? 对业务的了解,需要考虑业务对数据库一致性要求的敏感程度,切换过程中是否有事务会丢失 对于基础设施的了解,需要了解基础设施的高可用的架构.例如 单网线,单电源等情 ...
- 关于git报 warning: LF will be replaced by CRLF in README.md.的警告的解决办法
在使用git把代码上传至仓库时,会有下面这种警告: 虽然说是警告,但是看着真的很碍眼啊,特别是有强迫症的人就更难受了. 输入这一行命令就可以完美解决了 git config core.autocrlf ...
- 线性回归-API
线性回归的定义 利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式 线性回归的分类 线性关系 非线性关系 损失函数 最小二乘法 线性回归优化方法 正规方程 ...
- 实验3 SQL注入原理-万能密码注入
实验目的 (1)理解[万能密码]的原理 (2)学习[万能密码]的使用 实验原理 一.访问目标网站 1.选择一个存在漏洞的论坛 http://192.168.1.3:8009 进入 2.输入用户名[ad ...
- HTML&CSS基础-文档声明
HTML&CSS基础-文档声明 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HTML的发展 1993年6月: HTML第一个版本 1995年11月: HTML2.0 ...
- uiautomator2+python自动化测试1-环境准备
前言 uiautomator是Google提供的用来做安卓自动化测试的一个Java库.功能很强,可以对第三方App进行测试,获取屏幕上任意一个APP的任意一个控件属性,并对其进行任意操作,但有两个缺点 ...