標籤:app 不同 alt 資料庫 code color 資料 state image
一、Handler的定義:
主要接受子線程發送的資料, 並用此資料配合主線程更新UI。
解釋:當應用程式啟動時,Android首先會開啟一個主線程 (也就是UI線程) , 主線程為管理介面中的UI控制項, 進行事件分發, 比如說, 你要是點擊一個 Button ,Android會分發事件到Button上,來響應你的操作。 如果此時需要一個耗時的操作,例如: 連網讀取資料, 或者讀取本地較大的一個檔案的時候,你不能把這些操作放在主線程中,如果你放在主線程中的話,介面會出現假死現象, 如果5秒鐘還沒有完成的話,會收到Android系統的一個錯誤提示 "強制關閉"。 這個時候我們需要把這些耗時的操作,放在一個子線程中,因為子線程涉及到UI更新,,Android主線程是線程不安全的, 也就是說,更新UI只能在主線程中更新,子線程中操作是危險的。 這個時候,Handler就出現了。,來解決這個複雜的問題 ,由於Handler運行在主線程中(UI線程中), 它與子線程可以通過Message對象來傳遞資料, 這個時候,Handler就承擔著接受子線程傳過來的(子線程用sedMessage()方法傳弟)Message對象,(裡麵包含資料) , 把這些訊息放入主線程隊列中,配合主線程進行更新UI。
二、Handler一些特點
handler可以分發Message對象和Runnable對象到主線程中, 每個Handler執行個體,都會綁定到建立他的線程中(一般是位於主線程),它有兩個作用:
(1)安排訊息或Runnable 在某個主線程中某個地方執行;
(2)安排一個動作在不同的線程中執行。
Handler中分發訊息的一些方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post類方法允許你排列一個Runnable對象到主線程隊列中,
sendMessage類方法, 允許你安排一個帶資料的Message對象到隊列中,等待更新。
三、Handler執行個體
listview顯示資料,布局和上一篇一樣,MainActivity類代碼
package com.example.multithreadind01;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity { private String fromDb_str1 = ""; private Button btn; private TextView tv; private ListView lv; private BaseAdapter adapter; private List<User> userList = new ArrayList<User>(); private Runnable doInBackground1; private Runnable doInBackground2; //1.跟著主線程走,可以碰UI //2.能夠接受子線程發送的訊息(Message) // 子線程類本身不可以發資訊 private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("UI_MainThread","id:"+Thread.currentThread().getId()); for (int i = 0; i < 5; i++) { User u = new User(); u.setUsername("小明"+i); u.setSex("女"+i); userList.add(u); } tv =(TextView)findViewById(R.id.textView1); btn =(Button)findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //1.訪問資料庫或者互連網(但會卡的) //2.更新介面 Thread t1 = new Thread(doInBackground1); t1.start(); Thread t2 = new Thread(doInBackground2); t2.start(); } }); adapter = new BaseAdapter(){ @Override public int getCount() { // TODO Auto-generated method stub return userList.size(); } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = MainActivity.this.getLayoutInflater(); View view; if (convertView==null){ view = inflater.inflate(R.layout.item, null); } else{ view = convertView; } TextView tv_username = (TextView)view.findViewById(R.id.username); TextView tv_sex = (TextView)view.findViewById(R.id.sex); tv_username.setText(userList.get(position).getUsername()); tv_sex.setText(userList.get(position).getSex()); return view; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } }; lv = (ListView)findViewById(R.id.listView1); lv.setAdapter(adapter); handler = new Handler(){ //1.訊息msg來自於子線程 //2.訊息可以多個,採用msg.what識別 //3.處理訊息,一般就會更新UI //4.此方法可以參考onPostExecute @Override public void handleMessage(Message msg) { super.handleMessage(msg); int msgwhat = msg.what; Log.i("handler","已經收到訊息,訊息what:"+msgwhat+",id:"+Thread.currentThread().getId()); if (msgwhat==1){ //更新helloworld tv.setText("子線程讓我更新"+msgwhat); } if (msgwhat==2){ //更新ListView adapter.notifyDataSetChanged(); } } }; //子線程代碼1 doInBackground1 = new Runnable() { @Override public void run() { Log.i("sub_Thread","子線程1啟動,id:"+Thread.currentThread().getId()); try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //1.訪問資料庫或者互連網,不在UI進程,所以不卡 Message msg = new Message(); //對訊息一個識別號,便於handler能夠識別 msg.what = 1; handler.sendMessage(msg); Log.i("sub_Thread","子線程1已經發送訊息給handler"); } }; //子線程代碼1 doInBackground2 = new Runnable() { @Override public void run() { Log.i("sub_Thread","子線程2啟動,id:"+Thread.currentThread().getId()); try { Thread.sleep(6000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message msg = new Message(); //對訊息一個識別號,便於handler能夠識別 msg.what = 2; //handler.sendMessage(msg); handler.sendMessageDelayed(msg, 500); //訪問互連網,下載最新的,更新data,但不碰介面 for (User user : userList) { user.setSex("女"); } Log.i("sub_Thread","子線程2已經發送訊息給handler"); } }; }}
:
四、總結:
1)android系統是單線程系統,為了實現多線程的效果,採用了message queue。
2)為實現多線程,可採用runOnUiThread,post,handle,AsyncTask技術實現。
Android--Handler