android中Handler的初步认识(二)

    通过第一个小程序,我们对Handler有了一个最基本的认识

    接下来,看一下我们第二个例子

    在第一个例子的基础上,我们假设提出了新的需求:当用户点击启动按钮后,界面上会出现进度条,当进度条到100%后,进度条消失。我们也可以通过取消按钮来取消进度条

    刚看到这个例子的时候,我是这么写的:相对于第一个例子,我在布局文件中加入了一个progressBar的空间,并将它的显示类型默认置成gone

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:visibility="gone" />

然后activity中这么写的:

package com.example.handler2;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends Activity {

	Button startButton = null;
	Button stopButton = null;
	ProgressBar progressbar = null;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		startButton = (Button) findViewById(R.id.startButton);
		stopButton = (Button) findViewById(R.id.stopButton);
		progressbar = (ProgressBar) findViewById(R.id.progressBar);
		
		//为button绑定onclicklistener
		startButton.setOnClickListener(new ButtonOnclickListener());
		stopButton.setOnClickListener(new stopOnclickListener());
	}

	class ButtonOnclickListener implements OnClickListener{
		public void onClick(View v) {
			//让progressbar显示在界面上
			progressbar.setVisibility(View.VISIBLE);
			//将run放入message queue中
			handler.post(run);
		}		
	}
	
	class stopOnclickListener implements OnClickListener{
		public void onClick(View v) {		
			//从message queue 中去掉run
			handler.removeCallbacks(run);
			//让progressbar置成隐藏
			progressbar.setVisibility(View.GONE);
		}		
	}
	
	Runnable run = new Runnable() {
		int i = 1;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			i += 10;
			Message msg = handler.obtainMessage();
			msg.arg1 = i;
			
			//让线程延迟一秒
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			Log.i("run", "run "+i+"%");
			
			handler.sendMessage(msg);
			
			//当progressbar满了之后,停止计数,并隐藏进度条
			if(i>100){
				handler.removeCallbacks(run);
				progressbar.setVisibility(View.GONE);
			}			
		}
	};
	
	Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			
			//根据message中传来的参数控制进度条
			progressbar.setProgress(msg.arg1);
			//将run放入message queue中
			handler.post(run);
		};
	};	

}
     然后执行一下,发现刚开始都没问题

一开始的界面是这样:

android中Handler的初步认识(二)

点击开始按钮之后,进度条出现,并开始变化:

android中Handler的初步认识(二)

    如果我什么都不错,进度条满了之后,自动消失,我刚开始以为,这样就没问题了,但是当我看控制台的日志时发现,虽然进度条消失了,但是我后台计数动作仍然在执行(如果我点击取消按钮,计数就停止了)

android中Handler的初步认识(二)


关于这个问题,我在网上查了一下,大家的回答也没有一个十分准确的结论。

    结合网上其他人的解释,加上我自己的理解,我认为是这样的:当前的计数动作是放在message queue中系统根据队列自动执行的,当运行到run中方法的时候,我调用handler的removeCallBack时,相当于run把自己从队列中踢掉,这个逻辑显然是不合理的。(如果有知道这个具体原因的麻烦告诉我,这是我自己瞎猜的原因)

    而如果在取消按钮的onclicklistener中调用handler的removeCallBack,相当于从外部把run从队列中去掉,所以可以执行。

    在没有看到更准确的结论之前,我只能这么说服自己了。


    其实这个代码只要简单改一下,就可以实现提前提出的需求了

    把run中的判断改成

			if(i<100){
				handler.sendMessage(msg);				
			}else{
				progressbar.setVisibility(View.GONE);
			}

    这样只要进度条没满,那么发送message,把run放到队列中。知道进度条满了,在将其隐藏就好了。

    其实这样写,逻辑更加的清楚,也不知道自己第一次写的什么为什么要写得那么别扭,不过我看网上也有很多人出现和我一样的问题。哈哈,大家共勉吧

    到这个例子,我对Handler有了一个初步的认识,但是目前我们的程序还只是在主线程中操作,在下个例子中我将学习handler在多个线程中的应用。


android中Handler的初步认识(二),布布扣,bubuko.com

android中Handler的初步认识(二)

上一篇:(转)Android ViewGroup中事件触发和传递机制


下一篇:android 辅助工具类—— 图片缓冲池