Android组件之间的通信方式
来源:互联网 发布:jquery 转js 编辑:程序博客网 时间:2024/06/01 18:00
Android组件之间的通信方式
**学习Android也有一段时间了,有很多总结,一直没整理。想起来的时候懒得整理,想整理的时候又懒得去想。今天总结下四大组件之间的通信方式。如若有不足和错误,欢迎指正补充^_^。
对于Android的组件Activity, Service, ContentProvider和Service,Setter和Getter在这里是没有用的。开发者只能实现其规定的回调接口,组件的创建与销毁都是由系统框架控制的,开发者不能强行干预,更没有办法获取组件的对象。这也决定了,组件之间通信只能用系统支持的Intent。而Intent只能传递基本数据类型和Uri等一些常见的数据类型。Intent只支持传递内置类型和一些限制类型,这就导致了组件之间的数据传递必须都是基本类型,所以枚举类型无法使用。
- Activity之间的回调
这种startActivity或者startActivityForResult通信方式,局限性很大,。
现有两个Activity :A和B,顺序是A->B.传递数据的通信方式就是Intent,没什么好说的,要想从B向A传递数据。需要回调,就是常用的startActivityForResult / onActivityResult / setResult 组合。
提到这类函数组合,相信只要有过一段时间Android开发的来说都很熟悉了,此函数组合主要用于如下场景:用户在A Activity上点击某个按钮,跳转到B Activity,然后用户在B Activity上进行一些具体的操作,待操作完成后返回到A Activity,同时常常将B Activity中操作的一些数据返回到A Activity中。
再如上场景中,A -> B 需要通过startActivityForResult()方式打开。具体方式如下:
在A 中:
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(AActivity.this, BActivity.class); startActivityForResult(intent, 1); } });
其中,startActivityForResult第一个参数为Intent,因此,对于需要传递额外参数时,可以通过Intent直接传递。其中Bundle为可选参数。第二个参数为requestCode,即业务请求码。
在B中:
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setResult(RESULT_OK, intent); finish(); } });
在处理完或相应完用户操作后,自身结束前,需要通过setResult将数据回传给A。
接下来A接手B回传的数据。在A中:
@Override protected void onActivityResult(int requestCode, int resultCode,Intent intent) { //获取从B Activity回调的intent数据。 }
- 广播通信方式
广播通信是我们经常用的方式,可以跨应用传递,也是Android里面的标准方法,可以算是观察者模式的一种实现方式。
缺点:无法传递复杂数据,必须通过bundle来传递
主要流程为:
- 1、广播接收者BroadcastReceiver通过Binder机制向AMS(Activity ManagerService)进行注册;
- 2、广播发送者通过binder机制向AMS发送广播;
- 3、AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到
BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中; 4、消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。
使用方式就不罗嗦了
- 基于观察者模式的通信方式
定义对象间的一种一个(Subject)对多(Observer)的依赖关系,当一个对象的状态发送改变时,所以依赖于它的 对象都得到通知并被自动更新
Observer模式要解决的问题为:
建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候, 依赖这个“一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析时候, 我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。 这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。 Observer模式就是解决了这一个问题。
适用性:
1. 当一个抽象模型有两个方面,其中一个方面依赖于另一方面 将这两者封装成独立的对象中以使它们可以各自独立的改变和服用
2. 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变
3. 当一个对象必须通知其它对象,而它又不能假定其它对象是谁
观察者需要四个对象:
1. Subject(目标)
目标知道它的观察者,可以有任意多个观察者观察同一个目标 提供注册和删除观察者对象的接口
2. Observer(观察者)
为那些在目标发生改变时需获得通知的对象定义个更新的接口
3. ConcreteSubject(具体目标)
将有关状态存入各ConcreteObserver对象,当它的状态发送改变时,向它的各个观察者发出通知
4. ConcreteObserver(具体观察者)
维护一个指向ConcreteObserver对象的引用 存储有关状态,这些状态应与目标的状态保持一致 实现Observer的更新接口是自身状态与目标的状态保持一致
简单示例:
1.定义抽象的观察者接口:
public interface ObserverInterface { /** * 根据事件进行数据或者UI的更新 * @param message */ public void dispatchChange(String message);}
2.定义观察者接口实现:
public abstract class Observer implements ObserverInterface{ private Handler mHandler; public Observer(){ mHandler=new Handler(Looper.getMainLooper()); } public abstract void onChange(String message); @Override public void dispatchChange(String message){ mHandler.post(new NotificationRunnable(message)); } private final class NotificationRunnable implements Runnable{ private String message; public NotificationRunnable(String message){ this.message=message; } @Override public void run() { Observer.this.onChange(message); } }}
3.定义抽象的目标角色,即抽象的被观察者,在其中声明方法(添加、移除观察者,通知观察者):
public interface SubjectInteraface { /** * 注册观察者 * @param observer */ public void registerObserver(Observer observer); /** * 反注册观察者 * @param observer */ public void removeObserver(Observer observer); /** * 通知注册的观察者进行数据或者UI的更新 */ public void notifyObserver(String message);}
4.定义抽象目标接口实现:
public class Subject implements SubjectInteraface { private List<Observer> mEventObservers=new ArrayList<Observer>(); private static volatile Subject mEventSubject; private Subject(){ } public synchronized static Subject getInstance(){ if(mEventSubject ==null){ mEventSubject =new Subject(); } return mEventSubject; } @Override public void registerObserver(Observer observer) { synchronized (mEventObservers){ if(observer!=null){ if(mEventObservers.contains(observer)){ return; } mEventObservers.add(observer); } } } @Override public void removeObserver(Observer observer) { synchronized (mEventObservers){ int index = mEventObservers.indexOf(observer); if (index >= 0) { mEventObservers.remove(observer); } } } @Override public void notifyObserver(String message) { if(mEventObservers!=null && mEventObservers.size()>0 && message!=null){ for(Observer observer:mEventObservers){ observer.dispatchChange(message); } } }}
5.定义观察者模式的Activity:
/** * 观察者模式的Activity。 * Created by 2014 on 2015/9/2. */public abstract class BaseActivity extends ActionBarActivity { private ActivityObserver mActivityObserver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mActivityObserver=new ActivityObserver(this); registerObserver(mActivityObserver); } @Override protected void onDestroy() { super.onDestroy(); removeObserver(mActivityObserver); } /** * 注册为观察者 * @param observer */ public void registerObserver(Observer observer) { final Subject eventSubject=Subject.getInstance(); eventSubject.registerObserver(observer); } /** * 反注册观察者 * @param observer */ public void removeObserver(Observer observer) { final Subject eventSubject=Subject.getInstance(); eventSubject.removeObserver(observer); } /** * 该方法会在具体的观察者对象中调用,可以根据事件的类型来更新对应的UI,这个方法在UI线程中被调用, * 所以在该方法中不能进行耗时操作,可以另外开线程 * @param message 事件类型 */ protected abstract void onChange(String message); private static class ActivityObserver extends Observer { //添加弱引用,防止对象不能被回收 private final WeakReference<BaseActivity> mActivity; public ActivityObserver(BaseActivity activity){ super(); mActivity=new WeakReference<BaseActivity>(activity); } @Override public void onChange(String message) { BaseActivity activity=mActivity.get(); if(activity!=null){ activity.onChange(message); } } }}
最后贴一个简单的使用示例:
第一个Activity:(被观察者):
public class FirstActivity extends ActionBarActivity { private Button notifyButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first); notifyButton=(Button) findViewById(R.id.NotifyButton); notifyButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { //通知所有观察者,给所有观察者发出消息 Subject sb=Subject.getInstance(); sb.notifyObserver("Hi,this is a message ! "); } }); }}
第二个Activity:(观察者):
public class SecondActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); } @Override protected void onChange(String message) { System.out.println("SecondActivity Received Message:"+message); }}
- 基于 发布/订阅者 模式的通信方式
发布/订阅简称(Pub/Sub)模式,这种模式是观察者observer的一种变体。发布者主要是负责向外发送消息,S订阅者主要是订阅接收消息。主要用于“只负责传递消息,并不关心其他订阅者已经收到这个消息”.和广播通信非常相似。我们常用的发布订阅模式是EventBus框架.
优点:代码简洁优雅,大大降低了耦合性。简化了应用程序内各组件间、组件与后台线程间的通信。
缺点:无法进程间通信,如果一个应用内有多个进程的话就没办法了,无法跨应用传递事件。在组件之间通信非常频繁复杂繁琐的时候,会需要很多不同通信的消息Event实体 , EventBus的缺点也就暴露出来了,此时代码维护也很变得不容易了,显得混乱。
- 1、初始化时注册EventBus.getDefault().register(this);
- 2、用完之后注销EventBus.getDefault().unregister(this);
- 3、中间过程主要就是消息推送和接收,通过EventBus.getDefault().post(param)推送,通onEventMainThread(param),onEventPostThread(param),onEventBackgroundThread(param),onEventAsync(param)接收并处理。
首先定义消息Event实体
public Class MessageEvent{ private int xxx; private String xxx; //getter和setter方法}
发布者:可以在任意组件中发布消息:EventBus.getDefault().post(new MessageEvent());
接收方:要想接受到消息,必须注册:
@Override public void onCreate(Bundle savedInstanceState) { EventBus.getDefault().register(this); }
接受消息处理,有四种ThreadMod:
- PostThread:事件的处理在和事件的发送在相同的进程,这是默认的模式。当事件处理比较简单,不涉及主线程的UI更新时候,推荐使用。如果事件处理需要很长时间,会阻塞主线程也就是发送线程,对应的函数名是onEventPostThread。
- MainThread: 事件的处理会在UI线程中执行。事件处理时间不能太长,否则会阻塞主线程,对应的函数名是onEventMainThread。
- BackgroundThread:事件的处理会在一个后台线程中执行,事件处理是在后台线程,但事件处理时间还是不应该太长,因为如果发送事件的线程是后台线程,会直接执行事件,如果当前线程是UI线程,事件会被加到一个队列中,由一个线程依次处理这些事件,如果某个事件处理时间太长,会阻塞后面的事件的派发或处理。对应的函数名是onEventBackgroundThread。
- Async:事件处理会在单独的线程中执行,主要用于在后台线程中执行耗时操作,每个事件会开启一个线程(有线程池),但最好限制线程的数目。对应的函数名是onEventAsync。
public void onEventMainThread(MessageEvent mfe) { String newData = mfe.getXXX(); button.setText(newData );}
最后在在Ondestory()中取消订阅
@Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); }
- Android组件之间的通信方式
- Android组件之间的通信
- Android组件之间通信
- 组件之间的通信
- 组件之间的通信
- Android常用的组件间通信方式
- React组件之间的通信
- react组件之间的通信
- react组件之间的通信
- vue组件之间的通信
- React组件之间的通信
- 父子组件之间的通信
- Angular组件之间的通信
- vue组件之间的通信
- VUE组件之间的通信
- vue组件之间的通信
- EvenBus:Android应用组件之间高效通信的开发库
- 使用Broadcast实现android组件之间的通信
- android中判断是否为空遇到的问题
- c++ 中文分词介绍
- webview加载页面,JS方法不能加载的问题解决
- LeetCode题解:Valid Sudoku
- hdu 5299 树上博弈
- Android组件之间的通信方式
- U-boot-2014.04移植到MINI2440(1) 初步探索移植
- iOS 制作圆形头像
- myEclipse搭建SSH(Struts2+Spring3+Hibernate3)框架项目教程
- 二叉查找各类情况总结
- 程序员的生活充满压力,但你不能放弃!
- Foreach用法
- 常见JAVA框架
- Tomcat Server.xml详解