android 37 线程通信Looper
安卓程序的主线程也叫UI线程。
工作线程和主线程的差别:安卓主线程已经调用了Looper.prepare()方法了,已经有一个MessageQueue对象了,所以才可以在工作线程用Handler发消息到主线程:因为主线程有消息队列,发的消息都存在队列里面,并且主线程已经有Looper进行取消息了。
自己创建的工作线程是没有MessageQueue和Looper,所以不能向工作线程发消息,因为没有存消息的地方和取消息的东西。但是他可以有MessageQueue和Looper。
MessageQueue是消息队列,Looper轮训从消息队列中取消息,Handler用于发送和处理消息。
mainActivity:
package com.sxt.day06_02; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { ProgressBar mProgressBar; TextView mtvProgress; static final int DOWNLOAD_START=0; static final int DOWNLOADING=1; static final int DOWNLOAD_FINISH=2; Handler mMainHanlder,mWokrThreadHanler;//主线程和工作线程的Handler,分别处理消息。 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initMainHandler(); setListener();//下载按钮的监听器 createWorkThread(); } private void createWorkThread() { new Thread(){//工作线程 public void run() {//Looper和mWokrThreadHanler都是在工作线程创建 Looper.prepare();//创建Looper对象和工作线程中的MessageQueue mWokrThreadHanler=new Handler(){ public void handleMessage(Message msg) { if(msg.what==DOWNLOAD_START){ Log.i("main","work thread start downlad"); for(int i=1;i<=100;i++){ SystemClock.sleep(20); Message msg2 = Message.obtain(); msg2.what=DOWNLOADING; msg2.arg1=i; mMainHanlder.sendMessage(msg2);//发送到主线程的消息队列,然后主线程的Looper从主线程消息队列取出来,调用mMainHanlder处理 mProgressBar.setProgress(i); } //循环结束后发送完成消息 Message msg2 = Message.obtain(); msg2.what=DOWNLOAD_FINISH; mMainHanlder.sendMessage(msg2);//发送到主线程 } }; }; Looper.loop();//轮询MessageQueue,取到消息后交给mWokrThreadHanler的handleMessage()方法进行处理(上面的方法), }; }.start(); } private void setListener() { findViewById(R.id.btnStartDownload).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //工作线程Handler向自己工作线程发送消息,发送至工作线程的消息队列MessageQueue中,空消息通知工作线程开始下载 mWokrThreadHanler.sendEmptyMessage(DOWNLOAD_START); } }); } private void initMainHandler() { mMainHanlder=new Handler(){//在主线程new,所以为主线程服务 @Override public void handleMessage(Message msg) { switch (msg.what) { case DOWNLOADING: mtvProgress.setText(msg.arg1+"%"); break; case DOWNLOAD_FINISH: Toast.makeText(MainActivity.this, "下载完成", 2000).show(); break; } } }; } private void initView() { mProgressBar=(ProgressBar) findViewById(R.id.pb); mtvProgress=(TextView) findViewById(R.id.tvProgress); } }
页面:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btnStartDownload" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="开始下载" /> <ProgressBar android:id="@+id/pb" android:layout_width="match_parent" android:layout_height="wrap_content" style="@android:style/Widget.ProgressBar.Horizontal" android:max="100"/> <TextView android:id="@+id/tvProgress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="0%"/> </LinearLayout>