• Handler具体解释


    首先下载Android api 进行查阅 ,API下载地址:http://pan.baidu.com/s/1i33dTGT

    以下的描写叙述假设那里错了,请大家吐槽,我也是第一次学习,共同进步

    Handler能够分发Message对象和Runnable对象到主线程中,每一个Handler实例,都会绑定到创建他的线程中(通常是位于主线程),它有两个作用:

     (1): 安排消息或Runnable 在某个主线程中某个地方运行,

     (2)安排一个动作在不同的线程中运行。

    Looper 是管理Message queue的类。

    能够通过Looper.getMainLooper();获取主线程

    以下通过两个实例来測试一下吧:

    ============================================ONE=================================================

    第一个小Demo就是两个Button和一个ProgressBar ,xml文件的内容就不写了,直接看Activity的代码吧

    package com.example.handler;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.os.Message;
    import android.app.Activity;
    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 {
    	
    	//声明各个控件
    	private Button start=null;
    	private Button end=null;
    	private ProgressBar progressbar=null;
    	private Thread thread=null;
    	//获取主线程(具体请看Android API 文档)
    	Looper looper=Looper.getMainLooper();
    	
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		//通过id找到他们
    		start=(Button)findViewById(R.id.start);
    		end=(Button)findViewById(R.id.end);
    		progressbar=(ProgressBar)findViewById(R.id.progressbar);
    	//	为Button设置监听器
    		start.setOnClickListener(new StartButtonOnclickListener());
    		end.setOnClickListener(new EndButtonOnclickListener());
    		
    	}
    	
    	//声明点解開始类
    	class StartButtonOnclickListener implements OnClickListener{
    
    		@Override
    		public void onClick(View v) 
    		{
    			progressbar.setVisibility(View.VISIBLE); 
    			thread=new Thread(){
    				int i=0;
    				public void run(){
    					i+=10;
    					Message msg=handler.obtainMessage();
    					msg.arg1=i;
    					//让线程延迟
    					try{
    						Thread.sleep(2000);
    					}catch(InterruptedException e){
    						e.printStackTrace();
    					}
    					//Log.i("run", "run "+i+"%");  
                        Log.i("run", Thread.currentThread().getName()+"====");  
                        msg.sendToTarget();
    				}
    			};
    			thread.start();
    		}
    		
    	}
    	//结束的类
    	class EndButtonOnclickListener implements OnClickListener{
    
    		@Override
    		public void onClick(View v) {
    			//从message queue 中去掉run  
                handler.removeCallbacks(thread);  
                //让progressbar置成隐藏  
                progressbar.setVisibility(View.GONE); 
    		}
    		
    	}
    	
    	 Handler handler = new Handler(looper){  
    	        public void handleMessage(android.os.Message msg) {  
    	              
    	            int i =msg.arg1;  
    	            //依据message中传来的參数控制进度条  
    	            /*
    	             * 由于安卓不同意我们在主线程之外的线程中对UI进行改动,所以我在新建的线程中仅仅是进行计数
    	             * 然后将计数的结果通过message传递到主线程中,在主线程中更新进度条。
    	             */
    	            progressbar.setProgress(i);  
    	            Log.i("run", Thread.currentThread().getName());  
    	            if(i<100){  
    	                handler.post(thread);  
    	            }else{  
    	                handler.removeCallbacks(thread);  
    	                progressbar.setVisibility(View.GONE);  
    	            }  
    	        };  
    	    };    
    
    	/*
    	 * 第一次打印线程是在另外一个线程中,后面你的循环使用handler.post的话,这个runnable不会跑在子线程中,
    	 * 而是把runnable放入了handler绑定的target(在此为主线程)中相应的队列,然后在handleMessage中通过looper
    	 * 从队列取出runnable运行
    	 */
    }
    
    当我点击启动button后,调用的不是主线程的run,而是我新建的线程。 可是由于安卓不同意我们在主线程之外的线程中对UI进行改动,所以我在新建的线程中仅仅是进行计数,然后将计数的结果通过message传递到主线程中,在主线程中更新进度条。第一次运行,是在onclick中运行thread.start(); 这条语句运行的,所以第一次计数是在新的线程里;然后在新的线程里,又运行了msg.sendToTarget(); 这个触发了Handler的handleMessage()方法,在这种方法里通过handler.post(thread);第二次运行了计数(通过这样形成了循环),因为post的机制,是把post的内容放到Handler绑定的线程(代码中绑定的是主线程(looper获取的是主线程))的message queue中,所以我们看打印的结果是这种:


    所以仅仅有一次是次线程运行的,剩余的都是主线程运行的。



    ====================================================================================SECOND===============================================================================

    经过改进后:


    package com.example.handler;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.os.Message;
    import android.app.Activity;
    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 {
    
    	private Button start=null;
    	private Button end=null;
    	private ProgressBar progressbar=null;
    	private Thread thread=null;
    	
    	private static boolean running=true;
    	//获取主线程
    	Looper looper=Looper.getMainLooper();
    	
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		//通过id找到他们
    		start=(Button)findViewById(R.id.start);
    		end=(Button)findViewById(R.id.end);
    		progressbar=(ProgressBar)findViewById(R.id.progressbar);
    		
    		start.setOnClickListener(new StartButtonOnclickListener());
    		end.setOnClickListener(new EndButtonOnclickListener());
    		
    	}
    	
    	class StartButtonOnclickListener implements OnClickListener{
    
    		@Override
    		public void onClick(View v) 
    		{
    			progressbar.setVisibility(View.VISIBLE);
    			thread=new Thread(){
    				int i=0;
    				public void run(){
    					while(running){
    						i+=10;
    						Message msg=handler.obtainMessage();//返回从全局消息池中一个新的消息
    						msg.arg1=i;
    						//让线程延迟
    						try{
    							Thread.sleep(2000);
    						}catch(InterruptedException e){
    							e.printStackTrace();
    						}
    	                    Log.i("run", Thread.currentThread().getName()+"====");  
    	                    msg.sendToTarget();
    	                    if(i>100){
    	                    	 //当计数超过一百时,跳出循环  
                                running = false; 
    	                    }
    					}
    					
    				}
    			};
    			thread.start();
    		}
    		
    	}
    	Handler handler = new Handler(looper){  
            public void handleMessage(android.os.Message msg) {  
                int i =msg.arg1;  
                progressbar.setProgress(i);  
                Log.i("run", Thread.currentThread().getName());  
                if(i>100){     
                    //假设进度条慢,进度条隐藏  
                    progressbar.setVisibility(View.GONE);  
                }  
            };  
        };    
    	class EndButtonOnclickListener implements OnClickListener{
    		@Override
    		public void onClick(View v) {
    			//点击取消button,分线程不再循环计数  
                running = false;  
                //让progressbar置成隐藏  
                progressbar.setVisibility(View.GONE);  
    		}
    	}
    	
    }
    

    通过设置一个Boolean变量后,runningtrue时,循环计数,并调用handler.sendMessage(msg)为主线程传递计数结果

    执行后是:



    这种话就能够看出主次线程一次运行,通过次线程传值给主线程后,主线程改变ProgressBar的值。(这里记住安卓不同意我们在主线程之外的线程中对UI(主线程)进行改动)!

    大家吐槽吧。。。



  • 相关阅读:
    python基础(set)补充
    运算
    初识正则表达式
    xml中俩种解析方式
    Android Studio 调用夜神模拟器
    Android Studio 配置虚拟设备的镜像文件的存放路径
    Allegro PCB Design GXL (legacy) 使用slide推挤走线,走线的宽度就发生改变的原因
    OrCAD Capture CIS 16.6 在原理图页面内放置图片
    OrCAD Capture CIS 16.6 修改原理图的页面大小
    ESD选型指南
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/3802670.html
Copyright © 2020-2023  润新知