Android中Service与多个Activity通信
由于项目需要,我们有时候需要在service中处理耗时操作,然后将结果发送给activity以更新状态。通常情况下,我们只需要在一个service与一个activity之间通信,通常这种情况下,我们使用最多的是通过回调接口。具体做法是在service中定义一个接口,在activity中实现该接口,并通过bindservice来传入。实现方式很简单,在此不再赘述。
当需要将service中的结果一次发送给多个activity时,我们又该如何实现呢?经过多个项目的积累,总结了三种实现的方式。分别是回调接口、广播接收者和观察者模式。
1.回调接口的方式,与单个service与单个activity通信类似,只是将service中的接口变为接口的集合,每个需要通信的activity都实现接口,然后在获取结果后,循环调用集合中的实现类,来与多个activity进行通信,代码如下:
Service类:
package com.example.servicecallback; import java.util.ArrayList;
import java.util.List; import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log; public class ContentService extends Service { //回调接口的集合
private List<Callback> list; @Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return new LocalBinder();
} @Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
list = new ArrayList<Callback>();
} public final class LocalBinder extends Binder {
public ContentService getService() {
return ContentService.this;
}
} /**
* 回调接口
* @author Ivan Xu
*
*/
public interface Callback {
public void getPerson(Person person);
} /**
* 往回调接口集合中添加一个实现类
* @param callback
*/
public void addCallback(Callback callback) {
list.add(callback);
} public void asyncSendPerson(final String name) {
// 休息5秒,模拟异步任务
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.sendMessage(handler.obtainMessage(0, name));
}
}).start();
} private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
String name = (String) msg.obj;
Log.i("ContentService", "---name-->" + name);
Person person = new Person();
person.setName(name);
Log.i("ContentService", "---list.size()-->" + list.size());
Log.i("ContentService", "---person-->" + person.toString());
//遍历集合,通知所有的实现类,即activity
for (int i = 0; i < list.size(); i++) {
list.get(i).getPerson(person);
}
}
};
}
第一个activity:
package com.example.servicecallback; import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import com.example.servicecallback.ContentService.Callback;
import com.example.servicecallback.ContentService.LocalBinder; public class MainActivity extends Activity implements Callback { private MyServiceConn conn;
private ContentService service;
private TextView mContent; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); conn=new MyServiceConn();
bindService(new Intent(this, ContentService.class), conn,
BIND_AUTO_CREATE); mContent = (TextView) findViewById(R.id.content); this.findViewById(R.id.button1).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startActivity(new Intent(MainActivity.this,
OtherActivity.class));
}
});
} @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;
} public class MyServiceConn implements ServiceConnection { @Override
public void onServiceConnected(ComponentName name, IBinder binder) {
service = ((LocalBinder) binder).getService();
//将当前activity添加到接口集合中
service.addCallback(MainActivity.this);
} @Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
service = null;
}
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unbindService(conn);
} /**
* 获取回调的内容,更新UI
*/
@Override
public void getPerson(Person person) {
// TODO Auto-generated method stub
mContent.setText(person.toString());
}
}
第二个activity:
package com.example.servicecallback; import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.example.servicecallback.ContentService.Callback;
import com.example.servicecallback.ContentService.LocalBinder;
import com.example.servicecallback.MainActivity.MyServiceConn; public class OtherActivity extends Activity implements Callback { private ContentService service;
private TextView mContent;
private Button mSubmit;
private EditText mEditText;
private ServiceConnection conn; @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState); setContentView(R.layout.other); mEditText = (EditText) findViewById(R.id.edittext);
mSubmit = (Button) findViewById(R.id.button1);
mContent = (TextView) findViewById(R.id.content); mSubmit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String name = mEditText.getText().toString();
service.asyncSendPerson(name);
}
}); conn=new MyServiceConn();
bindService(new Intent(OtherActivity.this, ContentService.class), conn,
BIND_AUTO_CREATE); } public final class MyServiceConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
// TODO Auto-generated method stub
service = ((LocalBinder) binder).getService();
//将当前activity添加到接口集合中
service.addCallback(OtherActivity.this);
} @Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
service = null;
}
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unbindService(conn);
} /**
* 获取回调的内容,更新UI
*/
@Override
public void getPerson(Person person) {
// TODO Auto-generated method stub
mContent.setText(person.toString());
}
}
2.通过广播接收者,在service中执行完耗时操作后,将结果以广播的形式发送,在所有的activity中注册广播,接收到结果后更新UI,这种方式比较简单,也是笔者比较推荐的方式。因为耗时的操作结果不需要以handler的方式发送到主线程,可以直接在子线程中发送广播,接收者始终运行在主线程中。代码如下:
Service类:
package com.example.servicecallback; import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder; public class ContentService extends Service { @Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return new LocalBinder();
} @Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
} public final class LocalBinder extends Binder {
public ContentService getService() {
return ContentService.this;
}
} public void asyncSendPerson(final String name) {
// 休息5秒,模拟异步任务
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//可以在子线程中直接发送广播
sendContentBroadcast(name);
}
}).start();
} /**
* 发送广播
* @param name
*/
protected void sendContentBroadcast(String name) {
// TODO Auto-generated method stub
Intent intent=new Intent();
intent.setAction("com.example.servicecallback.content");
intent.putExtra("name", name);
sendBroadcast(intent);
}
}
第一个activity:
package com.example.servicecallback; import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView; public class MainActivity extends Activity { private MyServiceConn conn;
private TextView mContent;
private ContentReceiver mReceiver; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); conn = new MyServiceConn();
bindService(new Intent(this, ContentService.class), conn,
BIND_AUTO_CREATE); mContent = (TextView) findViewById(R.id.content); this.findViewById(R.id.button1).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startActivity(new Intent(MainActivity.this,
OtherActivity.class));
}
}); doRegisterReceiver();
} /**
* 注册广播接收者
*/
private void doRegisterReceiver() {
mReceiver=new ContentReceiver();
IntentFilter filter = new IntentFilter(
"com.example.servicecallback.content");
registerReceiver(mReceiver, filter);
} @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;
} public class MyServiceConn implements ServiceConnection { @Override
public void onServiceConnected(ComponentName name, IBinder binder) {
// service = ((LocalBinder) binder).getService();
} @Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
// service = null;
}
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unbindService(conn);
if (mReceiver!=null) {
unregisterReceiver(mReceiver);
}
} public class ContentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getStringExtra("name");
Person person = new Person();
person.setName(name);
mContent.setText(person.toString());
}
}
}
另一个activity:
package com.example.servicecallback; import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView; import com.example.servicecallback.ContentService.LocalBinder; public class OtherActivity extends Activity { private ContentService service;
private TextView mContent;
private Button mSubmit;
private EditText mEditText;
private ServiceConnection conn;
private ContentReceiver mReceiver; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.other); mEditText = (EditText) findViewById(R.id.edittext);
mSubmit = (Button) findViewById(R.id.button1);
mContent = (TextView) findViewById(R.id.content); mSubmit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String name = mEditText.getText().toString();
service.asyncSendPerson(name);
}
}); conn=new MyServiceConn();
bindService(new Intent(OtherActivity.this, ContentService.class), conn,
BIND_AUTO_CREATE); doRegisterReceiver();
} private void doRegisterReceiver() {
mReceiver=new ContentReceiver();
IntentFilter filter = new IntentFilter(
"com.example.servicecallback.content");
registerReceiver(mReceiver, filter);
} public final class MyServiceConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
service = ((LocalBinder) binder).getService();
} @Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}
} @Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
if (mReceiver!=null) {
unregisterReceiver(mReceiver);
}
} public class ContentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getStringExtra("name");
Person person = new Person();
person.setName(name);
mContent.setText(person.toString());
}
}
}
3.使用观察者模式,service为被观察者,所有的activity为观察者,当service中的内容发生改变时,通知所有的activity来更新,代码如下:
Service类:
package com.example.servicecallback; import java.util.Observable;
import java.util.Observer; import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message; public class ContentService extends Service { //被观察者
private MyObservable mObservable; @Override
public IBinder onBind(Intent arg0) {
return new LocalBinder();
} @Override
public void onCreate() {
super.onCreate();
mObservable = new MyObservable();
} public final class LocalBinder extends Binder {
public ContentService getService() {
return ContentService.this;
}
} public void asyncSendPerson(final String name) {
// 休息5秒,模拟异步任务
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendMessage(handler.obtainMessage(0, name));
}
}).start();
} /**
* 添加观察者
* @param observer
*/
public void addObserver(Observer observer) {
mObservable.addObserver(observer);
} private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
String name = (String) msg.obj;
Person person = new Person();
person.setName(name);
//通知更新
mObservable.notifyChanged(person);
}
}; public class MyObservable extends Observable { public void notifyChanged(Object object) {
this.setChanged();
this.notifyObservers(object);
}
}
}
第一个activity:
package com.example.servicecallback; import java.util.Observable;
import java.util.Observer;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView; import com.example.servicecallback.ContentService.LocalBinder; public class MainActivity extends Activity implements Observer { private MyServiceConn conn;
private TextView mContent;
private ContentService mService; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); conn = new MyServiceConn();
bindService(new Intent(this, ContentService.class), conn,
BIND_AUTO_CREATE); mContent = (TextView) findViewById(R.id.content); this.findViewById(R.id.button1).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,
OtherActivity.class));
}
});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
} public class MyServiceConn implements ServiceConnection { @Override
public void onServiceConnected(ComponentName name, IBinder binder) {
mService = ((LocalBinder) binder).getService();
//将当前activity添加为观察者
mService.addObserver(MainActivity.this);
} @Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
} @Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
} //更新UI
@Override
public void update(Observable observable, Object data) {
Person person = (Person) data;
mContent.setText(person.toString());
} }
第二个activity:
package com.example.servicecallback; import java.util.Observable;
import java.util.Observer; import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView; import com.example.servicecallback.ContentService.LocalBinder; public class OtherActivity extends Activity implements Observer { private ContentService service;
private TextView mContent;
private Button mSubmit;
private EditText mEditText;
private ServiceConnection conn; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.other); mEditText = (EditText) findViewById(R.id.edittext);
mSubmit = (Button) findViewById(R.id.button1);
mContent = (TextView) findViewById(R.id.content); mSubmit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String name = mEditText.getText().toString();
service.asyncSendPerson(name);
}
}); conn = new MyServiceConn();
bindService(new Intent(OtherActivity.this, ContentService.class), conn,
BIND_AUTO_CREATE); } public final class MyServiceConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
service = ((LocalBinder) binder).getService();
//将当前activity添加为观察者
service.addObserver(OtherActivity.this);
} @Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}
} @Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
} //更新UI
@Override
public void update(Observable observable, Object data) {
// TODO Auto-generated method stub
Person person=(Person) data; mContent.setText(person.toString());
}
}
附上其他相关代码,三种方式都一样:
Person类:
package com.example.servicecallback; public class Person { private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Person [name=" + name + "]";
} }
MainActiivty的布局文件
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="next" /> <TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello_world" /> </LinearLayout>
OtherActivity的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <EditText
android:id="@+id/edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> <Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="submit" /> <TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="content" /> </LinearLayout>
由于笔者的水平有限,如有错漏,请各位留言指正,感激不尽!
以上虽有借鉴别人的思想,但是源代码均为原创。请尊重笔者的劳动成果。如果转载,请注明出处,谢谢!
全文完
Android中Service与多个Activity通信的更多相关文章
- Android中Service(服务)详解
http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...
- Android中Service的使用详解和注意点(LocalService)
Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...
- Android中Service的一个Demo例子
Android中Service的一个Demo例子 Service组件是Android系统重要的一部分,网上看了代码,很简单,但要想熟练使用还是需要Coding. 本文,主要贴代码,不对Servic ...
- Android中Service和Activity之间的通信
启动Service并传递数据进去: Android中通过Intent来启动服务会传递一个Intent过去. 可以在Intent中通过putExtra()携带数据 Intent startIntent ...
- (六)Android中Service通信
一.启动Service并传递参数 传递参数时只需在startService启动的Intent中传入数据便可,接收参数时可在onStartCommand函数中通过读取第一个参数Intent的内容来实现 ...
- Android中Service 使用详解(LocalService + RemoteService)
Service 简介: Service分为本地服务(LocalService)和远程服务(RemoteService): 1.本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...
- android中service启动后台程序
Service是Android中一个类,它是Android四大组件之一,使用Service可以在后台执行长时间的操作( perform long-running operations in the b ...
- Android中Service深入学习
概述 1.当用户在与当前应用程序不同的应用程序时,Service可以继续在后台运行. 2.Service可以让其他组件绑定,以便和它交互并进行进程间通信. 3.Service默认运行在创建它的应用程序 ...
- Android中Service概述
Service是Android中一种非常重要的组件,一般来说有两种用途:用Service执行长期执行的操作,而且与用户没有UI界面的交互:某个应用程序的Service能够被其它应用程序的组件调用以便提 ...
随机推荐
- URAL 1698. Square Country 5(记忆化搜索)
题目链接 题意 : 自守数的定义:如果某个数的平方的末尾几位数等于这个数,那么就称这个数为自守数.例如5*5=25,则5就是自守数.让你求不超过n位的自守数有多少 思路 : 实际上,自守数还有两个性质 ...
- servlet及xml文件处理流程
启动项目----会找到web.xml文件---跳转到默认jsp----页面重定向----转到xml.文件下 通过<servlet-mapping>映射找到<servlet>标签 ...
- 字节序(Endian),大端(Big-Endian),小端(Little-Endian)
http://www.cppblog.com/tx7do/archive/2009/01/06/71276.html 在各种计算机体系结构中,对于字节.字等的存储机制有所不同,因而引发了计算机通信领域 ...
- Acrobat_8_Pro_SC 激活老是提示你输入的授权码无效
假如安装了Adobe Acrobat Professional 8 的时候无法激活, 或在恢复安装时 Adobe Acrobat Professional 8 需要重新激活, 激活的时候,总是提示你输 ...
- JDK安装目录分析-两个jre和三个lib
安装JDK后,Java目录下有jdk和jre两个目录,但jdk下还有一个jre目录,而且这个jre比前面那个jre在bin目录下少了个server文件夹(Server端的Java虚拟机)!前一个jre ...
- 「HNOI 2015」落忆枫音
题目链接 戳我 \(Description\) 给一张\(n\)割点\(m\)条边的\(DAG\),保证点\(1\)不存在入边,现在需要在\(DAG\)中加入一条不在原图中的边\((x,y)\),求这 ...
- 导出包含图片的excel、word、pdf 笔记
/** * 导出word * @throws Exception */ @Override public byte[] WordExport( List<VbLibGlobalAnalyList ...
- DAY31、socket套接字
一.复习1.网络编程 软件开发架构 b/s架构 c/s架构 本质都是c/s架构2.互联网协议 OSI七层协议 应用层 表示层 会话层 传输层 网络层 数据链路层 物理连接层3. 物理连接层:建立物理连 ...
- [Flex] 组件Tree系列 —— 利用firstVisibleItem属性,设置或取得第一个显示节点
mxml: <?xml version="1.0" encoding="utf-8"?> <!--功能描述: 利用firstVisibleIt ...
- [ActionScript 3.0] 十进制与二进制,十六进制等数据之间的相互转换
将十进制转换为二进制,方法是:将数字除以2,根据余数来从右往左排列二进制的位数,如下以十进制数10为例 10除以2得5,余数为0,故第一个位置为0: 5除以2得2,余数为1,故第二个位置为1: 2除以 ...