第八章--Handler的二三事(一)

这个是接着Handler的二三事写的。

基本用法

我们已经知道,Handler主要做两件事情:更新ui;发送消息

  • 首先说说更新ui:
public class MainActivity extends AppCompatActivity {

    Handler mHandler = new Handler();
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.textView);
        
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                System.out.println("" + Thread.currentThread());
                mTextView.setText("用handler更新了ui");
            }
        });
    }
}

然后看到后台打印了

09-01 15:55:28.716 11152-11152/com.example.myactionbardemo I/System.out: Thread[main,5,main]

这说明post这个方法是运行在主线程中的,我们知道谷歌规定只有在ui线程也就是主线程中才能执行更新ui的操作,所以handler.post()这个方法就能完成这个行为。那么既然是这样我们是不是可以把它放在工作线程中更新ui呢?当然是可以的,这就为我们工作线程和主线程之间的通信提供了一个思考问题的方向。最后基本上可同理postDelay()--延时执行。这个也是运行在主线程当中。

  • 然后是发送消息

在线程中发送消息,代码如下

        new Thread(){
            @Override
            public void run() {
                Message message = mHandler.obtainMessage();

                mHandler.sendEmptyMessage(1);
                //message.sendToTarget();
            }
        }.start();

首先是创建了一个是Message对象,我们一般不用new Message()来创建,而是使用Handler的obtainMessage()方法来创建,可以去看一下源码,源码中是这样return Message.obtain(this);,返回一个这样的Message对象,然后我们进入obtain()方法中,原来传入的this就是Handler本身,m.target = h;这个的意思就是把这个消息和handler绑定了。然后里面还有一个没有参数的obtain()方法,点进去看了一眼,好像是用链表处理的啊啊,我在这方面实在是有点欠缺,不过上面的英语的意思就是生成一个了新的Meesage。说了这么多废话其实就是这个方法可以生成一个和Handler有关系的Message。
然后是处理消息,依然是运行在主线程中,可以修改Ui。

    Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            mTextView.setText("99");

        }
    };

最后说一点Handler里面还有一个参数Callback。代码如下:

    Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            System.out.println("1");
            return false;
        }
    }){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            System.out.println("2");
        }
    };

当返回false的时候处理执行第一条语句后,也会继续执行第二个语句:

09-01 20:23:45.333 25527-25527/com.example.myactionbardemo I/System.out: 1
09-01 20:23:45.333 25527-25527/com.example.myactionbardemo I/System.out: 2

返回true,就只会执行第一个handleMessage()里面的语句

09-01 20:32:40.169 2336-2336/com.example.myactionbardemo I/System.out: 1

这样我们就可以拦截消息(这是慕课网上的老师说的),感觉很厉害的样子。

与线程相关的handler

其实我很早以前以为在线程中的handler就是属于线程当中的,后来发现不是,handler在哪不重要,我觉得是看它的Looper在哪创建的,或者使用的是哪个Looper。
虽然前一篇贴过代码,那我就不贴了。现在说一下多线程并发的一个小问题。看代码。

public class MainActivity extends AppCompatActivity {

    private TextView mTextView;

    private Handler mHandler;

     class myThread extends Thread{

         public Handler mHandler;
         public Looper mLooper;
         @Override
         public void run() {
             super.run();
             Looper.prepare();
             mLooper = Looper.myLooper();
             mHandler = new Handler(){
                 @Override
                 public void handleMessage(Message msg) {
                     super.handleMessage(msg);
                     System.out.println("" + Thread.currentThread());
                 }
             };
             Looper.loop();
         }
     }

    private myThread mThread;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.textView);

        mThread = new myThread();
        mThread.start();

        mHandler = new Handler(mThread.mLooper){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                System.out.println("" + Thread.currentThread());
            }
        };

        mHandler.sendEmptyMessage(1);
    }
}

当运行上面程序的时候就会出错闪退,原因就是当工作线程mThread执行的时候,主线程当中与之关联的handler可能已经执行到获取工作线程的looper了,然而这个时候looper是空的就是没有执行到mLooper = Looper.myLooper();所以会报错。自定义Handler可能就会遇到这种问题。
然后就介绍HeadlerThread可以避免这种问题。

    private HandlerThread mHandlerThread;

    private Handler mHadler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.textView);

        mHandlerThread = new HandlerThread("handler thread");
        mHandlerThread.start();

        mHadler = new Handler(mHandlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                System.out.println("" + Thread.currentThread());
            }
        };

        mHadler.sendEmptyMessage(1);
    }

创建HandlerThread中传入的对象是线程的名字,当该线程创建并star()之后,再关联handler,就可以得到了该线程的Looper对象,并且打印出来handlerMessage是运行在工作线程当中的。这样就可以在主线程发一个消息,然后在工作线程中执行一些比较耗时的操作,哎呀好方便啊啊啊。这是不是线程间通信啦。
这个就写到这了。


线程一定要start()阿门。
昨天看了一篇文章,就是说在写这类文章的时候,只有自己懂是远远不够,还要让别人也看的懂,当时就觉得特别的惭愧,自己写的自己不一定完全理解,别人就更不一定了。后来我想想,也许是自己的知识水平还没有提升到一个层次,所以对有一些东西还是停留在前人的一些思考上面,很少有自己的想法,写起来奇奇怪怪。如果是自己初次接触到这个东西还看不看得懂呢,这大概是我需要想想的一个问题。
推荐一个博客帅气的stormzhang的博客,理由就是最近他好像做父亲,沾沾喜气喽。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容