android中Handler的初步认识(三)

  在上一个例子中,最终我们发现,其实用到的线程只有一个,那就是程序的主线程(UI线程)。那么怎么把那个例子改成用新建的线程来实现呢,今天我尝试了一下,写了下面这个小程序。

        当然,首先要声明一下,今天的这个例子并不是推荐的写法,而是我为了学习多线程而写的例子(貌似更常用的是AsyncTask,而不是Thread和Handler去更新UI)。


        在今天的这个例子中,我用到了Looper,先说说Looper是什么


在API中是这么解释Lopper的:Class used to run a message loop for a thread。我的理解是Looper是用来控制message queue的类


Looper常用的几个用法有:

Looper.prepare()                安卓的主线程中会默认调用这个方法来创建消息队列。但是,如果我们自己新建的线程,如果需要消息队列,则需要手动调用这个方法。

Looper.loop()                     这个方法用在prepare()方法之后,调用该方法之后,进入消息循环。

Looper.getMainLooper()  我在代码中用到了这个方法,这个方法的作用是获得主线程的Looper实例

Looper.myLooper()            这个方法用到获取当前线程的Looper实例


今天这个例子和第二篇中实现的功能一下,我只不过改了一个写法而已,下面是代码:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. package com.example.handler2;  

  2.   

  3. import android.app.Activity;  

  4. import android.os.Bundle;  

  5. import android.os.Handler;  

  6. import android.os.Looper;  

  7. import android.os.Message;  

  8. import android.util.Log;  

  9. import android.view.View;  

  10. import android.view.View.OnClickListener;  

  11. import android.widget.Button;  

  12. import android.widget.ProgressBar;  

  13.   

  14. public class MainActivity extends Activity {  

  15.   

  16.     Button startButton = null;  

  17.     Button stopButton = null;  

  18.     ProgressBar progressbar = null;  

  19.     Thread counter = null;  

  20.   

  21.     //获取主线程的looper  

  22.     Looper looper = Looper.getMainLooper();  

  23.   

  24.       

  25.     @Override  

  26.     protected void onCreate(Bundle savedInstanceState) {  

  27.         super.onCreate(savedInstanceState);  

  28.         setContentView(R.layout.activity_main);  

  29.           

  30.         startButton = (Button) findViewById(R.id.startButton);  

  31.         stopButton = (Button) findViewById(R.id.stopButton);  

  32.         progressbar = (ProgressBar) findViewById(R.id.progressBar);  

  33.           

  34.         //为button绑定onclicklistener  

  35.         startButton.setOnClickListener(new ButtonOnclickListener());  

  36.         stopButton.setOnClickListener(new stopOnclickListener());  

  37.     }  

  38.   

  39.     class ButtonOnclickListener implements OnClickListener{  

  40.         public void onClick(View v) {  

  41.             progressbar.setVisibility(View.VISIBLE);  

  42.             counter = new Thread(){  

  43.                 int i = 1;  

  44.                 @Override  

  45.                 public void run() {  

  46.                     // TODO Auto-generated method stub  

  47.                     i += 10;  

  48.                     Message msg = handler.obtainMessage();  

  49.                     msg.arg1 = i;  

  50.                       

  51.                     //让线程延迟一秒  

  52.                     try {  

  53.                         Thread.sleep(1000);  

  54.                     } catch (Exception e) {  

  55.                         e.printStackTrace();  

  56.                     }  

  57.                     Log.i("run", "run "+i+"%");  

  58.                     Log.i("run", Thread.currentThread().getName());  

  59.                     msg.sendToTarget();               

  60.               

  61.                 }  

  62.             };  

  63.             counter.start();  

  64.         }         

  65.     }  

  66.       

  67.     class stopOnclickListener implements OnClickListener{  

  68.         public void onClick(View v) {         

  69.             //从message queue 中去掉run  

  70.             handler.removeCallbacks(counter);  

  71.             //让progressbar置成隐藏  

  72.             progressbar.setVisibility(View.GONE);  

  73.         }         

  74.     }  

  75.       

  76.     //将handler与主线程关联  

  77.     Handler handler = new Handler(looper){  

  78.         public void handleMessage(android.os.Message msg) {  

  79.               

  80.             int i =msg.arg1;  

  81.             //根据message中传来的参数控制进度条  

  82.             progressbar.setProgress(i);  

  83.               

  84.             Log.i("run", Thread.currentThread().getName());  

  85.   

  86.                           

  87.             if(i<100){  

  88.                 handler.post(counter);  

  89.             }else{  

  90.                 handler.removeCallbacks(counter);  

  91.                 progressbar.setVisibility(View.GONE);  

  92.             }  

  93.         };  

  94.     };    

  95. }  


       
         这段代码,和第二篇中最大的差别就是,当我点击启动按钮后,调用的不是主线程的run,而是我新建的线程。

        但是因为安卓不允许我们在主线程之外的线程中对UI进行修改,所以我在新建的线程中只是进行计数,然后将计数的结果通过message传递到主线程中,在主线程中更新进度条。

         


遗留问题:

         本来这个例子到这里就结束了,但是,我为了深入了解一下就在我新建的线程的run中和主线程Handler的handlerMessage方法中打印了当前线程的名称:

结果如下:


        


        按照我最初的理解,在日志中应该是主线程和我的线程交替写入日志,但是实际的情况是在第一次是counter线程,后面打印的都是主线程

        请问各位,有谁知道这是为什么吗?


        我看到在API中Handler的post方法是这么说明的:Causes the Runnable r to be added to the message queue. The runnable will be run on the thread to which this handler is attached.

         难道是,我使用了post方法,就相当于把counter线程的run中的代码拷贝中主线程中去执行了吗?如果有谁知道麻烦为我解答一下,不甚感激!


转载于:https://my.oschina.net/tslin/blog/370216

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值