溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android的Handler Looper Message機制應用實例與詳解(一)

發布時間:2020-06-26 12:11:04 來源:網絡 閱讀:1627 作者:sprocessor 欄目:移動開發

    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;
	
	@Override
	protected 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() {
			
			@Override
			public void onClick(View v) {
				showProgressDialog("","正在下載...");
				//啟動子線程進行網絡訪問模擬
				mNetAccessThread = new ChildTread();
				mNetAccessThread.start();
			}
		});
		
		//繼承Handler類并覆蓋其handleMessage方法
		mHandler = new Handler(){
			//覆蓋Handler類的handleMessage方法
			//接收子線程傳遞的數據并在UI顯示
			@Override
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case 1:
					mTextView.setText((String) msg.obj);
					dismissProgressDialog();
					break;
				//可以添加其他情況,如網絡傳輸錯誤
				//case...
				default:
					break;
				}
			}
		};
		
		
	}
	
	class ChildTread extends Thread {
		@Override
		public 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()向子線程發送消息,子線程收到消息后啟動數據下載(通過休眠線程模擬)。

Android的Handler Looper Message機制應用實例與詳解(一)

    下載完畢,子線程將下載數據返回主線程并顯示。

 Android的Handler Looper Message機制應用實例與詳解(一)

    實例2:模擬子線程向主線程發送消息。

    操作過程為:1.UI線程獲得用戶輸入的消息內容。2.通過Handler將消息發送給子線程。3.子線程獲得消息并通過Toast將內容打印。

    主要代碼如下:

public class MainActivity extends ActionBarActivity {

	private EditText mEditText;
	private Button mButton;
	private Handler mHandler;
	private Thread mChildTread;

	@Override
	protected 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() {
			@Override
			public 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 here
			switch (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();
	    }
	};
}

程序運行效果:

    Android的Handler Looper Message機制應用實例與詳解(一)Android的Handler Looper Message機制應用實例與詳解(一)


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

附件:http://down.51cto.com/data/2364939
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女