Handler機制的原理
Android 的 Handler 機制(也有人叫消息機制)目的是爲了跨線程通訊,也就是多線程通訊。之因此需
要跨線程通訊是由於在 Android 中主線程一般只負責 UI 的建立和修改,子線程負責網絡訪問和耗時操做,
所以,主線程和子線程須要常常配合使用才能完成整個 Android 功能。
Handler 機制能夠近似用圖 1 展現。MainThread 表明主線程,newThread 表明子線程。
MainThread 是 Android 系統建立並維護的,建立的時候系統執行了 Looper.prepare();方法,該方法內部
建立了 MessageQueue 消息隊列(也叫消息池),該消息隊列是 Message 消息的容器,用於存儲經過 handler
發送過來的 Message。MessageQueue 是 Looper 對象的成員變量,Looper 對象經過 ThreadLocal 綁定在
MainThread 中。所以咱們能夠簡單的這麼認爲:MainThread 擁有惟一的一個 Looper 對象,該 Looper 對象
有用惟一的 MessageQueue 對象,MessageQueue 對象能夠存儲多個 Message。
MainThread 中須要程序員手動建立 Handler 對象,並覆寫 Handler 中的 handleMessage(Message msg)
方法,該方法未來會在主線程中被調用,在該方法裏通常會寫與 UI 修改相關的代碼。
MainThread 建立好以後,系統自動執行了 Looper.loop();方法,該方法內部開啓了一個「死循環」不斷
的去以前建立好的 MessageQueue 中取 Message。若是一有消息進入 MessageQueue,那麼立刻會被
Looper.loop();取出來,取出來以後就會調用以前建立好的 handler 對象的 handleMessage(Message)方法。
newThread 線程是咱們程序員自定 new 出來的子線程。在該子線程中處理完咱們的「耗時」或者網絡
訪問任務後,調用主線程中的 handler 對象的 sendMessage(msg)方法,該方法一被執行,內部將就 msg
添加到了主線程中的 MessageQueue 隊列中,這樣就成爲了 Looper.loop()的盤中餐了,等待着被消費。這是html
一個很複雜的過程,可是 Android 顯然已經將這種模式給封裝起來了,就叫 Handler 機制。咱們使用時只須要在主線程中建立 Handler,並覆寫 handler 中的handleMessage 方法,而後在子線程中調用 handler 的 sendMessage(msg)方法便可。
java
圖1 Handler原理圖android
案例
網頁源碼查看器:程序員
activity_layout.xml:網絡
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context="com.seachal.htmlviewer.MainActivity"
-
- >
-
- <LinearLayout
- android:id="@+id/llay_top"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <EditText
- android:id="@+id/et_url"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:hint="請輸入網絡地址"
- android:text="http://www.baidu.com" />
-
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:onClick="load"
- android:text="肯定" />
- </LinearLayout>
-
- <ScrollView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@id/llay_top"
- >
-
- <TextView
- android:id="@+id/tv_content"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/hello_world" />
- </ScrollView>
-
- </RelativeLayout>
工具類將字節流轉化爲字符串 StreamUtls.java:多線程
- public class StreamUtils {
-
- public static String inputStream2String(InputStream inputStream)
- throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- int len = -1;
- byte[] buffer = new byte[1024];
- while ((len = inputStream.read(buffer)) != -1) {
- baos.write(buffer, 0, len);
- }
- inputStream.close();
- return new String(baos.toByteArray());
-
- }
-
- <span style="font-size:18px;"><strong>}</strong></span>
MainActivity.javaapp
最後在AndroidManifest.xml 中添加網絡訪問的權限ide
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.seachal.htmlviewer"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="16"
- android:targetSdkVersion="19" />
- <uses-permission android:name="android.permission.INTERNET"/>
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <activity
- android:name=".MainActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
- </manifest>
而後就大功告成了,運行一下去看看效果吧。若是有用就收藏一下吧!工具