Android中消息传递,看这一篇足够了

   上次写了Android的文件存储,这是和外界的信息交流,今天来写个Android的内部的信息交流,Android的消息传递方式。

    该博客分为以下几个方面:  1、Android 常见的需要传递数据的地方
                                                                                                          Activity与Activity
                                                                                                          Activity 与 Fragment
                                                                                                          Activity 与 Service

                                                2、常见的传递数据的方式
                                                                                          这四种方式适用于所有的传递数据的地方
                                                                                                           EventBus方式传递数据
                                                                                                            BroadCast方式传递数据
                                                                                                            观察者模式传递数据
                                                                                                            接口回调

                                               3、对所有的方式进行代码演示,和比较

                                               4、格外经验  Fragment的生命周期,多个切换的处理方法
 

    首先简单的介绍一下,需要传递消息的地方。Activity 和 Activity 之间的传递数据,初学者都找到 Intent 切了页面也穿了数据(很low),Activity 向 Fragemnt 传递数据(Bundle),Fragment向Activity传递数据(回调接口),这些最Android的入门。

     然后再简单的介绍传递数据的几种方式,代码已经上传到Github上面 地址:https://github.com/KEYD111/AndroidMessageHandler,请大家对照着代码看,注释很详细了。

     2.1  Handler Message  网上说可以可以在Activity和Fragment之间使用,没试过,感觉那样,代码会显得杂乱无章,个人建议在一个类中使用就行了

      2.2 广播的方式,该博客不具体介绍,想知道的看我的另外一篇博客  

                        BroadCast的两种使用方法                   https://mp.csdn.net/postedit/83044862

      2.3 EventBus 的方式   该博客不具体介绍,想知道的看我的另外一篇博客  

                        Android中EventBus(事件总线)传递数据           https://mp.csdn.net/postedit/83044862

             这两种方式,都已经介绍的很详细,关键如果放在一个工程中,大家不容易看。因为东西太多了

      2.4 接口回调的方式,  很方便,快捷

      2.5 观察者模式  下面着重介绍观察者模式。

3.代码演示

    先把简单的说了,再来难的  在 MainActivity 生成两个数  int 0 开始递增    char A 递增到 Z

new Timer().schedule(new TimerTask() {
    @Override
    public void run() {
        //生成两个一直动态变换的数据 1000周期
        count++;
        Log.i("dachen main", "count:" + count + "");
        if (achar == 'Z') {
            achar = 'A';
        }
        achar = (char) (achar + 1);
        Log.i("dachen main", "tmp:" + new String(new char[]{achar}));  //char 转字符串
    }
}, 0, 1000);

  3.1 Activity和Activity通信:

//这种方式 没什么卵用,根本不靠谱
Intent intent1 = new Intent(this, BroadcastActivity.class);
intent1.putExtra(IStatus.IStatus_Act2ActKey, IStatus.IStatus_Act2Actvalue);
startActivity(intent1);

3.2 Activity传数据到Fragment

MainActivity中代码为:

Bundle bundle1 = new Bundle();   
bundle1.putString(IStatus.IStatus_Act2FragKey1, IStatus.IStatus_Act2FragValue1);
bundle1.putString(IStatus.IStatus_Act2FragKey2, IStatus.IStatus_Act2FragValue2);
bundle1.putString(IStatus.IStatus_Act2FragKey3, IStatus.IStatus_Act2FragValue3);
if (fragmentTest1 != null) {
    fragmentTest1.setArguments(bundle1);
}  这种方式有一个空指针异常的问题,看代码中的巧妙解决的方法,这边就给出重点代码

Fragment中代码为:

if (isAdded()) {
         //此处也有处理空指针异常的方法,万一不让读者混乱,放在了代码中显示
        String a1 = getArguments().getString(IStatus.IStatus_Act2FragKey1);
        String a2 = getArguments().getString(IStatus.IStatus_Act2FragKey2);
        String a3 = getArguments().getString(IStatus.IStatus_Act2FragKey3);
        Log.i("dachen", "Frag1  Bundle方式接受来自Activity的数据为 " + "a1:" + a1 + ",a2:" + a2 + ",a3:" + a3);
}

3.3 Fragment向Activity中传递数据

      

//通过回调函数传递值
Fragment中代码为
在线程中将 数据
if (myCallBackListener != null) {
    myCallBackListener.onDataChange2(i + "");
} 传出去
private MyCallBackListener myCallBackListener;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    myCallBackListener = (MyCallBackListener) context;
}

public interface MyCallBackListener {
    public abstract void onDataChange2(String data);
}

   MainActivity 中实现接口 

FragmentTest1.MyCallBackListener  然后数据就来了。

3.4 Service向MainActivity中传递数据

       Service和Activity的区别就是一个看得见,一个看不见,所以都得在Androidmanifest中注册。

      Service中代码,继承Service的类

@Override
public IBinder onBind(Intent intent) {
    return new Binder2();
}


//全部返回回去
public class Binder2 extends Binder {
    public MySerice2 getService() {
        return MySerice2.this;
    }
}

@Override
public void onCreate() {
    super.onCreate();
    connecting = true;
    new Thread(new Runnable() {
        @Override
        public void run() {
            int i = 0;
            while (connecting == true) {
                i++;
                if (callBack2 != null) {
                    callBack2.onDataChange2(i + "");
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
}

public void setCallback2(CallBack2 callback2) {
    this.callBack2 = callback2;

}

public static interface CallBack2 {
    void onDataChange2(String data);
}

@Override
public void onDestroy() {
    super.onDestroy();
    connecting = false;
}
在MainActivity中的接受,
bindService(new Intent(this, MySerice2.class), serviceConnection2, BIND_AUTO_CREATE);  先绑定
ServiceConnection serviceConnection2 = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service2) {
        MySerice2.Binder2 binder2 = (MySerice2.Binder2) service2;
        final MySerice2 mySerice2 = binder2.getService();
        mySerice2.setCallback2(new MySerice2.CallBack2() {
            @Override
            public void onDataChange2(String data) {
               Log.i("dachen","接受来自Service的数据:"+data);
            }
        });
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
};    //这样就不需要实现接口,但是也可以实现 ServiceConnection 的接口, 数据来了

4  观察者模式

    准确的来说,观察者模式,不是Android特定的,以上的有些方法,必须在Android中才可以使用,现在观察者模式 C++,Java,php 都有,这只是一种思想。简单的来说,观察者模式,可以简单的认为就是广播,和EventBus都是类似的东西。个人理解为,就是对一个构造类的 set() get() 方法,做到了代码的耦合性,便于管理,观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。

     首先观察者模式自己实现,或是利用官方给的接口。

    以下   目标类(被观察者)  具体的目标类       观察者    具体的观察者      这些需要 Java的基础,不懂的可以仔细的去研究一下,观察者模式是行为型设计模式,需要一定(创建,构造的思想)。但是你如果只是简单的想传递数据的话,按我的方法,一个发送,一个接受就完事了,很简单。

    但是,不能坑大家,我还是得介绍一下记住了:     观察者是实现接口     对象是继续父类

     原理 A 创建观察者接口  

                 public interface Observer {
                        //将观察的对象传进来
                    public abstract void update(Subject1 subject1);
                 }

             B 创建对象的类 Subject1

public class Subject1 {

    protected List<Observer> list = new ArrayList<>();  //存放观察主题对象的所有的观察者

    public void registerNewObserver(Observer obs) {   //增加新的观察者
        list.add(obs);
    }

    public void removeOldObserver(Observer obs) {  //删除旧的观察者
        list.remove(obs);
    }

    //通知所有的观察者更新状态
    public void notifyAllObservers() {
        for (Observer obs : list) {
            obs.update(this);
        }
    }
}

C  实例化  类  

public class ConcreteSubject extends Subject1 {

    private int state;    //具体的方法

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        this.notifyAllObservers();    //目标对象的值发生改变通知所有的观察者
    }
}

D 实例化观察者  接口

public class ConcreteObserver implements Observer {
    public int getMyState() {
        return myState;
    }

    public void setMyState(int myState) {
        this.myState = myState;
    }

    private int myState;   //myState需要跟目标对象的state值保持一致

    @Override
    public void update(Subject1 subject1) {
        myState = ((ConcreteSubject) subject1).getState();
    }
}

然后测试一下

//观察者模式测试
private void ModelOfObserver() {
    //创建目标对象
    ConcreteSubject subject = new ConcreteSubject();

    //创建多个观察者
    ConcreteObserver concreteObserver1 = new ConcreteObserver();
    ConcreteObserver concreteObserver2 = new ConcreteObserver();
    ConcreteObserver concreteObserver3 = new ConcreteObserver();

    //添加观察者  添加到 subject的容器中去
    subject.registerNewObserver(concreteObserver1);
    subject.registerNewObserver(concreteObserver2);
    subject.registerNewObserver(concreteObserver3);

    //改变 subject 的状态
    subject.setState(3000);
    Log.i("dachen", concreteObserver1.getMyState() + "");
    Log.i("dachen", concreteObserver2.getMyState() + "");
    Log.i("dachen", concreteObserver3.getMyState() + "");

    subject.setState(30);
    Log.i("dachen", concreteObserver1.getMyState() + "");
    Log.i("dachen", concreteObserver2.getMyState() + "");
    Log.i("dachen", concreteObserver3.getMyState() + "");
}   
 package为observer

  大家注意了,,,,,数据的改变是在目标的那个类里面,监听的改变是在观察者的那个类里面,main只是作为一个类似缓冲区的地方,数据不是在 main 中监听的,打印出来只是为了方便大家看,,我代码中具体的有演示效果。

       这是原理,大家一看头疼,太多了,实现一个数据传递要这么多东西,所以我们可以直接用官方的,继承 和 接口  同样数据也是在里面实现的,,大家需要观察的数据对象继承类实现,放在线程中变换数据,需要得到的数据的类实现观察者的接口,理论比较抽象,看代码   package 为 modelofobserver   不懂的代码中注释多多,程序员,不要天天看文字。我是很讨厌看文字。

       那么问题来了,觉得这样子好烦,每次要获得一个数据,都要实现接口,能不能有种向以前的那种方法,比如说 MainActivity中扔出一个数据,谁要,谁去接受,当然可以,参考别人的博客https://blog.csdn.net/wbwjx/article/details/51587887

      我自己做了实现 package observer , 你们用的时候,直接把三个文件复制进去进行了

       假设  MainActivity 传数据给 Fragment 则这个样子写

        Main中  

Object notify1 = ObservableManager.newInstance()
        .notify(IStatus.IStatus_ObserverKey1, "使用观察者模式COPY传递数据:", count, achar);

      就这么简单    IStatus.IStatus_ObserverKey1    KEY 

                            "使用观察者模式COPY传递数据:", count, achar   Value   想传多少传多少,都不要list了 很方便了

     Fragment中    

ObservableManager.newInstance().registerObserver(IStatus.IStatus_ObserverKey1, this);  注册  实现接口
@Override
public Object function(Object[] data) {
    Log.i("dachen fragment1", String.valueOf(data[0]) + "," + String.valueOf(data[1]));
    return "我是fragment1的返回结果";
}     数据来了   他还有反馈    很人性化  很方便  

   差不多就结束了,,强烈建议大家,对照着代码来看,作者全部实现成功了。

   还有个小问题,就是存在多个 Fragment 但是,又不想每个 fragment 启动后都接受数据,或是启动 切换不销毁,但是只想在 有View的时候接受数据,我的代码中已经处理好了。简单的介绍一下吧,这是具体问题的处理方法。

   首先如何切换 Fragment  android 4.3   和 Android5.1 以后的方法是不一样的,需要获得  getSupportFragmentManager();

   然后切换的方式,我自己用过的有两种,一个是 replace 一个是 hide ,还有一个是 viewpager 大家有兴趣自己看,我没有亲自实践,所以不介绍。

   replace 是 切换的时候直接将前面的一个销毁了, hide只是隐藏了,我个人喜欢hide   避免不必要的错误。

   讲一下 fragment的生命周期,学习https://www.jianshu.com/p/c8f34229b6dc 他的博客

hide的方法时:

  • Fragment1 的生命周期变化为:onCreate()、onCreateView、onStart()、onResume() 回调 onHiddenChanged() 方法

  • Fragment2 的生命周期变化为: onCreate()、onCreateView、onStart()、onResume()

  • Fragment 2 再次返回到 Fragment 1:不走任何生命周期方法但是回调 onHiddenChanged()方法


replace的方法时:

  • 载入Fragment 1时:

Fragment 1的生命周期:onCreate()、onCreateView()、onStart()、onResume()

  • 切换到Fragment2时:

Fragment 1的生命周期:onPause()、onStop()、onDestroyView()、onDestroy()

Fragment 2的生命周期:onCreate()、onCreateV()、onStart()、onResume()

  • Fragment 2切换回Fragment 1时:

Fragment2的生命周期:onPause()、onStop()、onDestroyView()、onDestroy()

Fragment 1的生命周期:onCreate()、onCreateV()、onStart()、onResume()

 hide 方法,将数据变化方法 onhiddenchange 里面 ,上面的数据传递的处理

    ObservableManager.newInstance().removeObserver(this);
} else
    ObservableManager.newInstance().registerObserver("MAINSEND1", this);

 不足之处,请大家不吝赐教,如果侵权,请尽快联系作者。

 

 

 

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值