Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one,

call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

 class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}

(1)提出问题:正如上面所说, 一个线程默认是没有Looper用来处理message队列的。但为什么我们在主线程时又没有自己创建Looper呢?

 public class Looper {
private static final String TAG = "Looper"; // sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); //(1)又见到了眼熟的ThreadLocal,里面存放的是每个线程的Looper
private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue;
final Thread mThread;
volatile boolean mRun; private Printer mLogging; /** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
} private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
} /**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper(); //(2)为主线程的Looper赋值
}
} /** Returns the application's main looper, which lives in the main thread of the application.
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
} /**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static Looper myLooper() { //(3)为主线程Looper赋值的其实就是调用ThreadLocal的get()
return sThreadLocal.get();
} }

2.如果不知道ThreadLocal是什么意思,自己去查API,我没这么大气和你讲。

3.所以我们可以这样用:

 public class MainActivity extends Activity {

       private ProgressDialog mpDialog;
private int mCount = 0; private Handler handler = new Handler(){ @Override
public void handleMessage(Message msg) {
//update UI
System.out.println("----------update ui ok--------------"+Thread.currentThread().getId()); // Thread id 为1 说明在主线程中执行。
System.out.println("message arg1 : "+ msg.arg1); //因为这是主线程,所以可以在这时更新UI
super.handleMessage(msg);
}
}; private Thread downThread = new Thread(){ @Override
public void run() { try{
while(mCount<=100){
mpDialog.setProgress(mCount++);
Thread.sleep(100); //模拟下载过程
}
// This is essentially the same as calling dismiss(),
//but it will also call your DialogInterface.OnCancelListener (if registered).
mpDialog.cancel();
System.out.println("------------download ok----------");
Message message = handler.obtainMessage();
message.arg1 = 10;
handler.sendMessage(message);
}catch(Exception ex){
mpDialog.cancel();
}
} }; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button= (Button) this.findViewById(R.id.button);
imageView = (ImageView) this.findViewById(R.id.imageView01);
button.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View view) {
System.out.println("--------------download start----------------"+Thread.currentThread().getId()); //主线程的id为1
mCount = 0;
mpDialog = new ProgressDialog(MainActivity.this);
mpDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mpDialog.setTitle("dialogʾ");
mpDialog.setIcon(R.drawable.ic_launcher);
mpDialog.setMessage("好消息");
mpDialog.setMax(100);
mpDialog.setProgress(0);
mpDialog.setSecondaryProgress(50);
mpDialog.setIndeterminate(false);
mpDialog.setCancelable(true);
mpDialog.setButton("取消", new DialogInterface.OnClickListener(){ @Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel(); } });
downThread.start();
mpDialog.show();
} });
} }

4.正如上面所说,一个新线程在默认情况下是没有Looper相关联的。所以需要自己创建。但android提供了一个HandlerThread,方便我们使用Looper。

 public class HandlerThread extends Thread {

     Looper mLooper;

     /**
* Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
*/
protected void onLooperPrepared() {
} public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
} /**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason is isAlive() returns false, this method will return null. If this thread
* has been started, this method will block until the looper has been initialized.
* @return The looper.
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
} // If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
} }

最新文章

  1. Python新建动态命名txt文件
  2. [LintCode] Maximal Rectangle 最大矩形
  3. mysql 获得当前月1号的日期 和 0点日期方法
  4. HDOJ 3177 Crixalis&amp;#39;s Equipment
  5. 什么是Intent(意图)
  6. oracle 11gR2 RAC安装手册
  7. vo与po
  8. 下载使用前端开发工具sublime,并汉化
  9. Charles for MAC配置与使用
  10. Windows批处理 -- 打造MySQLCleaner
  11. unity与安卓通讯的一些事儿
  12. .NET笔试题集(三)
  13. 20145109竺文君、20145106石晟荣 java实验三
  14. 项目中使用protobuf
  15. 开篇~试试word写博客
  16. Android Studio -导入项目 gradle处理
  17. 微信小程序列表加载更多
  18. Java分布式:消息队列(Message Queue)
  19. 【BZOJ】3670: [Noi2014]动物园(KMP)
  20. 纯 js 让浏览器不缓存 ajax 请求

热门文章

  1. 关于PullToRefreshView bug 的修复
  2. 从PC端(Ubuntu)挂载nfs网络文件系统ARM9+Linux板子上
  3. 使用node新建一个socket服务器连接Telnet客户端并且进行输入的显示
  4. 由于更换硬盘没有删除系统自启动读取挂载硬盘导致系统报错:fsck.ext4 unable to resolve &#39;UUID=a4a7a0f7-b54f-4774-9fb1&#39;
  5. web基础-----&gt;jersey整合jetty开发restful应用(一)
  6. Elasticsearch学习之ES节点类型以及各种节点的分工
  7. POJ 3579 Median(二分答案)
  8. ThinkPHP-5.0.23新的RCE漏洞测试和POC
  9. docker搭建gitlab、Redmine
  10. 我的node+express小例子