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);        }
0 0