信件:Message

QuibblerQuibbler 2019-12-25 约 9 分钟 1743 次阅读

信件:Message

刚接触Android开发,子线程中进行数据处理完毕之后,如何将数据传到主线程让我困惑一段时间。那么如何将数据传到主线程呢?这需要借助Android的Handler传递消息机制,原理详见Handler、Looper、MessageQueue消息机制原理。

1、获取Message

通常在子线程中处理完毕,需要借助Message向主线程发送消息,通知主线程,

1.1、直接创建

构造函数直接创建Message实例:

Message message = new Message();
    message.what = 1;

1.2、obtain()对象池获取

推荐使用obtain()从消息池获取Message对象,而不是直接new一个新的Message对象:

Message message = Message.obtain();

可以查看源码,知晓其中的实现方式,即便一开始没有Message对象可以获取,也会新建一个对象,所以不用担心使用Message.obtain()这个方法会得到一个为null的Message对象:

/**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

而这里的sPool就是所谓的“对象池”,其中最大存放50个Message对象可以重复使用:

/** @hide */
    private static Message sPool;
    private static int sPoolSize = 0;
    private static final int MAX_POOL_SIZE = 50;

仔细一看发现对象池sPool怎么是一个Message对象,难道不应该是一个集合吗?在继续追溯源码可以发现Message本身的实现就类似一个链表,保存了下一个Message对象的引用,当然这部分是不对外开放的,不能直接调用:

// sometimes we store linked lists of these things
    @UnsupportedAppUsage
    /*package*/ Message next;

2、发送Message

有了Message对象,向其中存放数据等信息。往往通过Bundle类携带数据,关于Bundle后面介绍:Android“包裹”:Bundle。

2.1、包裹“消息”

除了可以给Message.what设置int类型的消息标志(一般都是这么做的),还可以向里面添加数据。借助Bundle类,Message.setData(Bundle data)方法向Message对象添加所需携带的数据:

Bundle bundle = new Bundle();
    
    //可以添加各种基本类型的数据
    bundle.putString("key", "data");
    
    //还支持添加集合数据,不过其中的对象要实现Parcelable接口:<? extends Parcelable>
    List<Parcelable> result = new ArrayList<>();
    bundle.putParcelableArrayList("list", (ArrayList<? extends Parcelable>) result);
    
    message.setData(bundle);

给Bundle这个“包裹”塞了一堆数据之后直接调用Message.setData(Bundle)将“包裹”交给Message既可以了(这里是将Bundle赋值给了Message内部的一个Bundle data成员变量)。

Message还真是全能,Bundle也是能“装”,这些谷歌都做了大量的封装,方便开发者使用。

2.2、发送“消息”

好了最后数据都准备好了,直接发个消息个主线程的Handler对象:

mHandler.sendMessage(message);

2.3、主线程处理“消息”

之后主线程的活就来了,实现定义好的在主线程等待已久的Handler:

private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Bundle bundle = msg.getData();
            
            String str = bundle.getString("key");
            List<Parcelable> result = bundle.getParcelableArrayList("list");
            
            Map<String, String> map = (Map<String, String>) msg.obj;
        }
    };

去Message消息中取出包裹:

Bundle bundle = msg.getData();

从包裹中再取出数据,层层拆包,虽然麻烦,但是相比子线程和主线程的通信那可简化了很多:

String str = bundle.getString("key");
    List<Parcelable> result = bundle.getParcelableArrayList("list")

除了Bundle中的数据,别忘了Message本身也携带了一个Object通用“包裹”obj,可以用来携带一个任意类型的对象:

Map<String, String> map = (Map<String, String>) msg.obj;

至此,如何从子线程将数据传递到主线程的方法大抵如此。至于底层的实现如Handler、Looper是如何协同完成这些的以后再深入研究。

参考博客:

        Android 子线程中得到的键值对数组数据传递给主线程

        Android 主UI线程与子线程之间传递数据Bundle

        Android 中 Message详解

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w