当前位置: 代码迷 >> Android >> Android多线程(3)
  详细解决方案

Android多线程(3)

热度:93   发布时间:2016-04-27 22:42:36.0
Android多线程(三)

  上次讲了关于Android多线程中通信中Thread、Handler、Looper等的基础概念和基本用法,用现实世界两个人写信交流的过程来理解是再好不过了。但是不得不说这一套完整的细节的确很繁琐,好在Android中为我们提供了另一个简化的API——HandlerThread,通过使用HandlerThread,我们可以以一种简单的方式开启线程、进行线程通信。Let's do it!

三、HandlerThread

  1)参考文档:http://developer.android.com/reference/android/os/HandlerThread.html

  前面的连篇文章中我都贴出来相应内容的官方文档地址,也斗胆说了一下读文档的重要性。这次我们换一种方式——读源代码,好的代码本身就是一份文档,除了会写还得能读!如何找到Android的源码?不管你用的是不再更新的ADT+Eclipse还是AS(Android studio),你的电脑里一定得下载sdk,在sdk目录下有个叫sources的文件夹,里面放的就是Android的系统源码。(开源大法好!)如果你没有,那就“FQ”下一份,如何快速更新sdk我会在下一篇博客里写......

  2)HandlerThread源码:

  我在这把源码贴出来方便查看(我电脑上的源码是Android-22的)

package android.os;/** * Handy class for starting a new thread that has a looper. The looper can then be  * used to create handler classes. Note that start() must still be called. */public class HandlerThread extends Thread {    //线程的优先级    int mPriority;    //线程id    int mTid = -1;    //与线程绑定的Looper对象    Looper mLooper;    public HandlerThread(String name) {        super(name);        mPriority = Process.THREAD_PRIORITY_DEFAULT;    }        /**     * Constructs a HandlerThread.     * @param name     * @param priority The priority to run the thread at. The value supplied must be from      * {@link android.os.Process} and not from java.lang.Thread.     */    public HandlerThread(String name, int priority) {        super(name);        mPriority = priority;    }        /**     * Call back method that can be explicitly overridden if needed to execute some     * setup before Looper loops.     * 这里是你需要实现的部分,你的在这里实现对Handler的准备工作,定义你的Hadnler并实现     *handlerMessage(Message msg)方法。     */    protected void onLooperPrepared() {    }    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }        /**     * This method returns the Looper associated with this thread. If this thread not been started     * or for any reason is isAlive() returns false, this method will return null. If this thread      * has been started, this method will block until the looper has been initialized.       * @return The looper.     */    public Looper getLooper() {        if (!isAlive()) {            return null;        }                // If the thread has been started, wait until the looper has been created.        synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }    /**     * Quits the handler thread's looper.     * <p>     * Causes the handler thread's looper to terminate without processing any     * more messages in the message queue.     * </p><p>     * Any attempt to post messages to the queue after the looper is asked to quit will fail.     * For example, the {@link Handler#sendMessage(Message)} method will return false.     * </p><p class="note">     * Using this method may be unsafe because some messages may not be delivered     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure     * that all pending work is completed in an orderly manner.     * </p>     *     * @return True if the looper looper has been asked to quit or false if the     * thread had not yet started running.     *     * @see #quitSafely     */    public boolean quit() {        Looper looper = getLooper();        if (looper != null) {            looper.quit();            return true;        }        return false;    }    /**     * Quits the handler thread's looper safely.     * <p>     * Causes the handler thread's looper to terminate as soon as all remaining messages     * in the message queue that are already due to be delivered have been handled.     * Pending delayed messages with due times in the future will not be delivered.     * </p><p>     * Any attempt to post messages to the queue after the looper is asked to quit will fail.     * For example, the {@link Handler#sendMessage(Message)} method will return false.     * </p><p>     * If the thread has not been started or has finished (that is if     * {@link #getLooper} returns null), then false is returned.     * Otherwise the looper is asked to quit and true is returned.     * </p>     *     * @return True if the looper looper has been asked to quit or false if the     * thread had not yet started running.     */    public boolean quitSafely() {        Looper looper = getLooper();        if (looper != null) {            looper.quitSafely();            return true;        }        return false;    }    /**     * Returns the identifier of this thread. See Process.myTid().     */    public int getThreadId() {        return mTid;    }}

  这里我们重点看两个方法:

   protected void onLooperPrepared() 这是一个在拓展类中需要重写的方法,它完成准备工作,一般是对Handelr进行定义。比如接受到主线程发来的消息时如何做出应对。在后面的示例中我就会对Handler进行定义,在handleMessage(Message msg)中定义行为。

  public void run() 再看这个方法里的内容是不是感到很熟悉,理解了Thread、Handler、Looper等概念后,是不是很容易就读懂了它的意思。对了,拓展HandlerThread时,如果要override run方法一定要记得调用父类的run() 。

  对于其他的方法,在这里就不赘述了,每个方法的前面的注释就详细说明了它们的作用。

  3)一个简单的示例:

  还是一样的,我用一个示例来说明HandlerThread的用法。还是一样的开启线程,等到接收到主线程发来的消息,然后打印打印日志。

布局:

 1  <TextView 2         android:layout_width="wrap_content" 3         android:layout_height="wrap_content" 4         android:layout_centerHorizontal="true" 5         android:text="HandlerThread"/> 6  7     <Button 8         android:id="@+id/button" 9         android:layout_width="match_parent"10         android:layout_height="wrap_content"11         android:layout_alignParentBottom="true"12         android:text="send message"/>

拓展的HandlerThread类:

 1 public class MyThread extends HandlerThread { 2  3     private static final String TAG = "MyThread"; 4     private Handler mHandler; 5  6     public MyThread() { 7         super(TAG); 8     } 9 10     @Override11     protected void onLooperPrepared() {12         super.onLooperPrepared();13         mHandler = new Handler(){14             @Override15             public void handleMessage(Message msg) {16                 super.handleMessage(msg);17                 if(msg.what == MainActivity.MSG_MAIN){18                     handlerRequest(msg.obj);19                 }20             }21         };22         return;23     }24 25     private void handlerRequest(Object obj){26         Log.d(TAG, "handlerRequest:" + obj + ",thread:" + Thread.currentThread().getName());27         Looper looper = Looper.getMainLooper();28         Handler handler = new Handler(looper);29         handler.post(new Runnable() {30             @Override31             public void run() {32                 Log.d(TAG,"message is handled,thread:"+Thread.currentThread().getName());33                 return;34             }35         });36         return;37     }38 39     public Handler getHandler() {40         return mHandler;41     }42 }

这次我使用了post方法很主线程进行通信。

Activity代码:

 1 public class MainActivity extends AppCompatActivity { 2  3     public static final int MSG_MAIN = 100; 4  5     @Override 6     protected void onCreate(Bundle savedInstanceState) { 7         super.onCreate(savedInstanceState); 8         setContentView(R.layout.activity_main); 9 10         final MyThread thread = new MyThread();11         thread.start();12         thread.getLooper();13 14         final Button sendButton = (Button) findViewById(R.id.button);15         sendButton.setOnClickListener(new View.OnClickListener() {16             @Override17             public void onClick(View view) {18                 Handler handler = thread.getHandler();19                 Message msg = handler.obtainMessage();20                 msg.what = MainActivity.MSG_MAIN;21                 msg.obj="testing HandlerThread";22                 handler.sendMessage(msg);23                 return;24             }25         });26     }27 }

  Logcat打印日志:

  10-08 11:45:47.152 13949-14004/comfallblank.github.handlerthread D/MyThread: handlerRequest:testing HandlerThread,thread:MyThread
  10-08 11:45:47.162 13949-13949/comfallblank.github.handlerthread D/MyThread: message is handled,thread:main

  这次我在日志中加入了线程名称,这样就可以看出任务执行的线程了。

  到这里,关于Android线程的内容算写完了,本来打算在国庆期间写完了,最后拖拖拉拉延迟了一天。还有国庆长假后第一天上课好累啊!就这样吧!下一篇关于如何快速更新sdk努力在这周写出来。

最后,欢迎大家交流,指正我不正确的地方。

邮箱:[email protected]:1054746297

 

  相关解决方案