1).Android 价值千万   java线程专题:Wait¬ify&join&Yield

http://blog.csdn.net/whb20081815/article/details/65627387

2).Android 价值千万    java多线程同步 <二>Callable和Future&FutureTask

http://blog.csdn.net/whb20081815/article/details/65630694

3).Android 价值千万    java多线程<三>生产者消费者模型四种实现方法

http://blog.csdn.net/whb20081815/article/details/65635647

 4).Android 价值千万    java多线程同步 <四> synchronized&Lock&Atomic6种方式

http://blog.csdn.net/whb20081815/article/details/66971983

 

5).Android 价值千万java多线程同步 <五>CountDownLatch(计数器)和Semaphore(信号量)

http://blog.csdn.net/whb20081815/article/details/68498371

6).Android AsyncTask 那些你不知道的事

https://blog.csdn.net/WHB20081815/article/details/70332209

7).Android 厉害了ThreadLocal的工作原理和实例分析

https://blog.csdn.net/WHB20081815/article/details/66974651

8).Android Handle消息机制:秒懂Looper、Handler、Message三者关系

https://blog.csdn.net/WHB20081815/article/details/67639060

9).Android 性能优化<八> 多线程优化和线程管理

https://blog.csdn.net/WHB20081815/article/details/77775444

一般情况下,在主线程中我们绑定了Handler,并在事件触发上面创建新的线程用于完成某些耗时的操作,当子线程中的工作完成之后,会对Handler发送一个完成的信号,而Handler接收到信号后,就进行主UI界面的更新操作。

Handler机制主要为了解决以下2个问题

1.  不要阻塞UI线程;
2.  不要在UI线程之外访问UI组件,即不能在子线程访问UI组件,只能在UI线程访问。

1、Looper

对于Looper主要是prepare()和loop()两个方法。

 

首先看prepare()方法

 

 

private static void prepare(boolean quitAllowed) {    if (sThreadLocal.get() != null) {        throw new RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper(quitAllowed));}

ThreadLocal保证了一个线程中只有一个Looper实例

 

 

 

 

在构造方法中,创建了一个MessageQueue(消息队列)。

 

private Looper(boolean quitAllowed) {    mQueue = new MessageQueue(quitAllowed);    mThread = Thread.currentThread();}

Loop方法:里面一个For循环,阻塞队列,不断的取消息

 

 

public static void loop() {    final Looper me = myLooper();    if (me == null) {        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");    }    final MessageQueue queue = me.mQueue;    // Make sure the identity of this thread is that of the local process,    // and keep track of what that identity token actually is.    Binder.clearCallingIdentity();    final long ident = Binder.clearCallingIdentity();    for (;;) {        Message msg = queue.next(); // might block        if (msg == null) {            // No message indicates that the message queue is quitting.            return;        }

Looper主要作用:
1、 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
2、 loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。
好了,我们的异步消息处理线程已经有了消息队列(MessageQueue),也有了在无限循环体中取出消息的哥们,现在缺的就是发送消息的对象了,于是:Handler登场了。

 

 

public Handler(Callback callback, boolean async) {    if (FIND_POTENTIAL_LEAKS) {        final Class<? extends Handler> klass = getClass();        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                (klass.getModifiers() & Modifier.STATIC) == 0) {            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                klass.getCanonicalName());        }    }    mLooper = Looper.myLooper();    if (mLooper == null) {        throw new RuntimeException(            "Can't create handler inside thread that has not called Looper.prepare()");    }    mQueue = mLooper.mQueue;    mCallback = callback;    mAsynchronous = async;}

发送消息:把消息添加到了MessageQueue队列里面

 

 

移除消息:通过MessageQueue

 

public final void removeMessages(int what) {    mQueue.removeMessages(this, what, null);}

总结流程:

 

 

1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。

2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。

3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。

4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。

5.报错Can't create handler inside thread that has not called Looper.prepare(),没有调用Looper.loop().UI线程默认调用了Looper.prepare()和Looper.loop()方法。Looper.prepare()和Looper.loop()方法。

 

列子:

 

public void testHandler2(final TextView textView){    mHandler=new Handler();    new Thread(new Runnable() {        @Override        public void run() {            while (true){                i++;                mHandler.post(new Runnable() {                    @Override                    public void run() {                        textView.setText(""+i);                        Log.d("mHandler",""+i);                    }                });                try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }).start();}

错误代码如下:

 

 

/**     * Error,while死循环,主线程做了耗时的操作     * @param textView     */    public void testHandler(final TextView textView){        mHandler=new Handler(getMainLooper());        mHandler.post(new Runnable() {            @Override            public void run() {//                textView.setText(""+i);                while (true){                    Log.d("mHandler",""+i+"ThreadName"+Thread.currentThread().getName());                    i++;                    if(i%1000==0){                        textView.setText(""+i);                    }                }            }        });    }

 

AS代码地址:不知道为什么上传不了

更多相关文章

  1. 【Android M】Monkey命令源码及是否处于monkey测试的判断方法
  2. Bugly Android 这个错误 Cleartext HTTP traffic to android.bug
  3. Android应用程序消息处理机制(Looper、Handler)源码分析
  4. FregServer进程,启动Binder线程池,睡眠等待在proc->wait
  5. Android中,把XML文件转换成Object对象的方法
  6. Android 死机问题分析方法收集
  7. android]Android 线程优先级修改
  8. Android中通过资源文件获取drawable的几种方法

随机推荐

  1. Android获得本应用本次开机后的流量
  2. Android(安卓)给应用定制皮肤
  3. android进度条修改教程(颜色,高度)
  4. 安卓开发实例 Android开发实例
  5. android中动态给EditText获得焦点并弹起
  6. Android(安卓)Activity生命周期和堆栈管
  7. Android Studio 3.0-3.1 汉化包
  8. Android中完全退出APP的方法
  9. 分享一个整理了很多Android开发工具类的
  10. java中Arraylist复制方法