Android的Handler Looper Message機制應用執行個體與詳解(一)

來源:互聯網
上載者:User

標籤:android   looper   handler   線程間通訊   

    Android的UI操作不是安全執行緒的(出於提高效能考慮,避免實現多線程同步等機制所引入的延時),若多個線程同時對UI元素進行操作,可能導致安全執行緒問題。因此,Android中做了嚴格的規定:只有UI主線程才能對UI進行設定與操作。

    在實際編程中,為了避免UI介面長時間得不到響應而導致的ANR(Application Not Responding)異常,通常將網路訪問、複雜運算等一些耗時的操作被放在子線程中執行。這就需要子線程在運行完畢後將結果返回到主線程並通過UI進行顯示。在Android中,是通過Handler+Loop+MessageQueue實現線程間通訊的。

    先看兩個執行個體:

    執行個體1:類比通過網路下載資料並返回UI顯示。

    操作過程為:1.UI線程獲得使用者請求。2.啟動子線程完成網路資料下載(網路下載過程通過強制子線程休眠若干秒來類比)。3.子線程將下載的資料返回UI線程並顯示。

    主要代碼如下:

public class MainActivity extends ActionBarActivity {private Button mButton;private TextView mTextView;private Handler mHandler;private Thread mNetAccessThread;private ProgressDialog mProgressDialog;private int mDownloadCount = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.fragment_main);mButton = (Button) findViewById(R.id.btReqNet);mTextView = (TextView) findViewById(R.id.tvDownload);//設定按鈕的點擊事件監聽器mButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {showProgressDialog("","正在下載...");//啟動子線程進行網路訪問類比mNetAccessThread = new ChildTread();mNetAccessThread.start();}});//繼承Handler類並覆蓋其handleMessage方法mHandler = new Handler(){//覆蓋Handler類的handleMessage方法//接收子線程傳遞的資料並在UI顯示@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 1:mTextView.setText((String) msg.obj);dismissProgressDialog();break;//可以添加其他情況,如網路傳輸錯誤//case...default:break;}}};}class ChildTread extends Thread {@Overridepublic void run() {//休眠6秒,類比網路訪問延遲try {Thread.sleep(6000);} catch (InterruptedException e) {e.printStackTrace();}//將結果通過訊息返回主線程Message msg = new Message();msg.what = 1;mDownloadCount ++;msg.obj = new String("第"+mDownloadCount+"次從網上下載的資料");mHandler.sendMessage(msg);}};/**        * 開啟progressDialog.        *        * @param title 對話方塊標題.        * @param content 對話方塊本文.        */protected void showProgressDialog(String title,String content) {mProgressDialog = new ProgressDialog(this);if(title != null)mProgressDialog.setTitle(title);if(content != null)mProgressDialog.setMessage(content);mProgressDialog.show();}/**        * 關閉progressDialog.        *        */protected void dismissProgressDialog() {if(mProgressDialog != null){mProgressDialog.dismiss();}}}

    程式運行效果:

    點擊下載按鈕,UI線程通過handler.sendMessage()向子線程發送訊息,子線程收到訊息後啟動資料下載(通過休眠線程類比)。

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/4C/36/wKioL1Q45jnRyNfNAAB1lcKvu-o305.jpg" title="360手機小幫手1011_15_54_01.png" style="float:none;" alt="wKioL1Q45jnRyNfNAAB1lcKvu-o305.jpg" />

    下載完畢,子線程將下載資料返回主線程並顯示。

 650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/4C/37/wKioL1Q4563zuwMZAACM4fmNrKU067.jpg" title="360手機小幫手1011_15_56_02.png" alt="wKioL1Q4563zuwMZAACM4fmNrKU067.jpg" />

    執行個體2:類比子線程向主線程發送訊息。

    操作過程為:1.UI線程獲得使用者輸入的訊息內容。2.通過Handler將訊息發送給子線程。3.子線程獲得訊息並通過Toast將內容列印。

    主要代碼如下:

public class MainActivity extends ActionBarActivity {private EditText mEditText;private Button mButton;private Handler mHandler;private Thread mChildTread;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.fragment_main);mEditText = (EditText) findViewById(R.id.etEditText);mButton = (Button) findViewById(R.id.btButton);// 設定按鈕的點擊事件監聽器mButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Message msg = new Message();msg.what = 1;msg.obj = mEditText.getText();//將訊息發送到子線程mHandler.sendMessage(msg);mEditText.setText("");}});//啟動子線程進行msg接收mChildTread = new ChildTread();mChildTread.start();}/*** 子線程為內部類,可以直接存取其外部類的mHandler變數**/class ChildTread extends Thread {    @Override    public void run() {        //以下三步是handler looper機制工作的固定模式Looper.prepare();mHandler = new Handler() {    public void handleMessage(Message msg) {        // process incoming messages hereswitch (msg.what) {case 1:    //子線程無權操作UI,只能通過Toast.makeText將收到的訊息顯示    String st = msg.obj.toString();    if (st == null || st.equals(""))          st = "收到的訊息內容為空白";    else        st = "收到來自主線程的訊息:" + st;    Toast.makeText(MainActivity.this, st, 6000).show(); break;//可以添加其他情況,如傳輸錯誤//case...default:break;}    }};Looper.loop();    }};}程式運行效果:

    650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/4C/37/wKioL1Q46pnjjJMDAAB3ZtMgIgY620.jpg" title="360手機小幫手1011_15_54_01.png" alt="wKioL1Q46pnjjJMDAAB3ZtMgIgY620.jpg" />650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/4C/37/wKioL1Q46neDgzh5AACNfaspK8Y747.jpg" title="360手機小幫手1011_15_56_02.png" alt="wKioL1Q46neDgzh5AACNfaspK8Y747.jpg" />


小結:Android通過Handler+Looper+MessageQueue機制實現線程間的通訊,本文通過兩個簡單的執行個體分別基於該機制實現了UI線程到子線程和子線程到UI線程的訊息傳遞。下一篇博文將會對Handler Looper機制的原理進行深入研究。

本文出自 “sprocessor” 部落格,請務必保留此出處http://sprocessor.blog.51cto.com/160089/1562589

Android的Handler Looper Message機制應用執行個體與詳解(一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.