一、一般我們都會在子線程完成一些耗時的操作。
1、Android中消息機制:
2、知識點:
Message:消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理。
Handler:處理者,負責Message的發送及處理。使用Handler時,需要實現handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。
MessageQueue:消息隊列,用來存放Handler發送過來的消息,並按照FIFO規則執行。當然,存放Message並非實際意義的保存,而是將Message以鏈表的方式串聯起來的,等待Looper的抽取。
Looper:消息泵,不斷地從MessageQueue中抽取Message執行。因此,一個MessageQueue需要一個Looper。
Thread:線程,負責調度整個消息循環,即消息循環的執行場所。
子線程更新uI界面方法一:用Handler
1、我們將在上張AsyncTask的案例中進行操作,我們將之前點擊調用事件中的調用方法注釋。
public class MainActivity extends Activity { private SimpleAdapter sa; private Button btn; private TextView tv; private List<Userinfos> list=new ArrayList<Userinfos>(); private BaseAdapter adapter; private ListView lv; private Runnable doInBackground1; private Runnable doInBackground2; private Runnable doInBackground3; private Handler handler; private Thread th; private Thread th2; @Override protected void onCreate(Bundle savedInstanceState) { //這里是UI主線程 super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); for (int i = 0; i < 5; i++) { Userinfos u = new Userinfos(); u.setName("小明"+i); u.setSex("男"+i); list.add(u); } lv=(ListView)this.findViewById(R.id.listView1); tv=(TextView)findViewById(R.id.textView1); btn=(Button)findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener(){ //模擬數據訪問產生數據 @Override public void onClick(View v) { // TODO Auto-generated method stub /*Take tk=new Take(MainActivity.this);//同步任務 tk.execute(list,adapter);//參數是傳給doInBackground*/ Thread t1=new Thread(doInBackground1); t1.start(); Thread t2=new Thread(doInBackground2); t2.start(); Thread t3=new Thread( doInBackground3); t3.start(); }});
handler=new Handler() { public void handleMessage(android.os.Message msg) { int what=msg.what; Log.i("handler","已經收到消息,消息what:"+what+",id:"+Thread.currentThread().getId()); if(what==1) { Log.i("handler已接受到消息",""+what); tv.setText("子線程一"); } if(what==2) { Log.i("handler已接受到消息",""+what); adapter.notifyDataSetChanged(); } if(what==3) { Log.i("handler已接受到消息",""+what); adapter.notifyDataSetChanged(); btn.setText("子線程三"); } }; }; //子線程一 doInBackground1=new Runnable(){ @Override public void run() { // TODO Auto-generated method stub 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("dd","子線程一已發送消息給handler"); }}; //子線程二 doInBackground2=new Runnable(){ @Override public void run() { // TODO Auto-generated method stub try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message mge=new Message(); mge.what=2; handler.sendMessageDelayed(mge,200); for(Userinfos us:list) { us.setName("李麗"); } Log.i("dd","子線程二已發送消息給handler"); }}; //子線程三 doInBackground3=new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { Thread.sleep(9000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message mge=new Message(); mge.what=3; handler.sendMessageDelayed(mge,200); for(Userinfos us:list) { us.setSex("女"); } Log.i("dd","子線程三已發送消息給handler"); }};
1、子線程發消息,通知Handler完成UI更新:
2、Handler的handleMessage方法進行消息處理,接收到消息進行UI界面更新。
注:方法一的Handler對象必須定義在主線程中,如果是多個類直接互相調用,就不是很方便,需要傳遞content對象或通過接口調用。
效果圖:
子線程更新uI界面方法二:用用Activity對象的runOnUiThread方法更新
通過runOnUiThread方法進行UI界面更新
public void onClick(View v) { // TODO Auto-generated method stub /*Take tk=new Take(MainActivity.this);//同步任務 tk.execute(list,adapter);//參數是傳給doInBackground*/ /*Thread t1=new Thread(doInBackground1); t1.start(); Thread t2=new Thread(doInBackground2); t2.start(); Thread t3=new Thread( doInBackground3); t3.start();*/ th.start(); th2.start(); }});
th= new Thread() { @Override public void run() { //這兒是耗時操作,完成之后更新UI; runOnUiThread(new Runnable() { //更新UI @Override public void run() { // TODO Auto-generated method stub btn.setText("runOnUiThread子線程一"); } }); super.run(); } }; th2=new Thread() { public void run() { runOnUiThread(new Runnable() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // TODO Auto-generated method stub tv.setText("runOnUiThread子線程二"); } }); }; };
1、通過runOnUiThread方法New 一個Runnable實現run方法進行UI界面更新。
如果在非上下文類中(Activity),可以通過傳遞上下文實現調用;
效果圖片: