前言:
handler的第二个例子是利用progressBar来分析handler的消息队列和线程队列,虽然不知道哪里出了bug导致无法像视频中那样实现,但是还是想要分析并总结下程序运行的过程以及新的知识点以便于巩固。
直接上代码:
package com.dengchao.handlerteat_2; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; public class MainActivity extends Activity { private Button startButton; private ProgressBar bar; int i=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //根据控件的id得到控件的对象,并为按钮设置监听器 startButton=(Button)findViewById(R.id.startButtonId); bar=(ProgressBar)findViewById(R.id.progressId); startButton.setOnClickListener(new ButtonListener()); } //当点击startButton按钮时就会执行onclick方法 class ButtonListener implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub //把progressBar设置为可见状态 bar.setVisibility(View.VISIBLE); updateBarHandler.post(updateThread); } } //使用匿名内部类来复写handler中的handlerMessage这个方法 Handler updateBarHandler = new Handler(){ public void handlerMessage (Message msg){ bar.setProgress(i); updateBarHandler.post(updateThread); } }; //线程类,该类使用匿名内部类的方式进行时声明 Runnable updateThread =new Runnable() { @Override public void run() { // TODO Auto-generated method stub //打印Begin Thread System.out.println("Begin Thread"); i=i+10; //得到一个消息对象Message类是由andorid提供 //在handler这个类中存在两个队列 ,一个是线程队列,一个是消息队列 Message msg= updateBarHandler.obtainMessage();//这里有些疑问,姑且以为是获取handler获取消息队列当中的message吧 //将msg对象的arg1参数的值设置为i,用arg1和arg2传递消息,优点是系统性能消耗较少 msg.arg1=i; try { //线程睡眠1000ms Thread.sleep(1000); } catch (InterruptedException e) { // TODO: handle exception e.printStackTrace(); } //将msg对象加入到消息队列中 updateBarHandler.sendMessage(msg); if(i==100) { //当i的值为100时就将线程对象从handler中移出 updateBarHandler.removeCallbacks(updateThread); } } }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
这个程序是利用线程来实现进度条的效果,程序运行过程是:
当点击startButton的时候,监听器就会监听到点击事件,因此激活OnClick方法,OnClick方法中有两个函数:bar.setVisibility(View.VISIBLE);
updateBarHandler.post(updateThread);
第一个是将progressBar显示出来(因为在布局文件中设置的是开始隐藏),第二个是将updateThread这个线程加入到线程队列中去,updateThread这个线程事先用Runnable接口建立,并利用匿名内部类复写函数,当Thread进入线程队列之后开始运行其中的run方法,即首先在logcat中打印一个Begin Thread,然后i=i+10;然后利用Message类建立一个值为handler消息队列中的消息的值的msg对象(说的有些绕,其实就建立一个msg对象,让获取消息队列中的消息的值,把值付给msg,如果消息队列为空,则值为空,这是我自己理解的),然后把msg对象的arg1参数的值设置为i,之后休眠1s,后利用updateBarHandler.sendMessage(msg);将msg对象发送到消息队列中,然后我们在看消息队列,msg对象进入队列中后就开始执行,执行在updateBarHandler中的handlerMessage方法,即将进度条的值设置为msg的arg1的值,然后继续将updateThread线程放入线程队列,这就又回复到一开始的位置,行成了一个循环,循环的结果是i的值一直在增加10,也就说进度条一直在往前伸展,直到i=100,之后利用updateBarHandler.removeCallbacks(updateThread);将线程对象移出队列,队列为空,进程结束。
这就有点像c语言中的循环语句,不过是利用线程来实现的,首先将线程加入线程队列,执行线程(执行后线程为空),生成消息,加入到消息队列,执行消息(消息队列为空),再将线程加入线程队列,周而复始,直到到达临界条件的时候,将线程对象从线程队列中取出(此时线程正在执行但是没有执行完,所以此时队列中这个线程还存在),线程队列为空,进程结束。这就是我自己理解的整个过程。