zoukankan      html  css  js  c++  java
  • Android之Handler探索

    Handler背景理解: 

     Handler被最多的使用在了更新UI线程中,但是,这个方法具体是什么样的呢?我在这篇博文中先领着大家认识一下什么是handler以及它是怎么样使用在程序中,起着什么样的作用。

      示例说明:

        首先先建立两个按钮:一个是start按钮,作用是开启整个程序。另一个是终止按钮end,作用是结束整个的程序。这两个按钮的相互对比就会让大家明白Handlerd的基本的工作原理。

    运行结果截图:

    MainActivity.class

    package com.example.testhandler;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    
    public class MainActivity extends Activity {
    	
    	private Button start,end;
    
    	//实例化一个handler对象
    	private Handler handler = new Handler();
    	//开启一个新的线程:开启线程有两种方式,一种是使用普通的Thread方法,另一个中是使用Runnable方法
    	Runnable update = new Runnable() {
    		
    		@Override
    		public void run() {
    			System.out.println("update");
    			handler.postDelayed(update, 3000);
    		}
    	};
    	
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		start = (Button)this.findViewById(R.id.btn_start);
    		end = (Button)this.findViewById(R.id.btn_end);
    		
    		start.setOnClickListener(new OnClickListener() {
    			
    			@Override
    			public void onClick(View v) {
    				//加入到队列中去执行
    				handler.post(update);
    			}
    		});
    		
    		end.setOnClickListener(new OnClickListener() {
    			
    			@Override
    			public void onClick(View v) {
    				//将消息移除队列中去
    				handler.removeCallbacks(update);
    			}
    		});
    		
    	}
    
    }
    

      当点击Start按钮时的效果图如下:

    当点击end按钮时的效果图如下:

    注意:

      Handler中的post方法并没有开启一个新的线程,他的操作是在主线程中执行的。下面咱们就来验证一下这个观点。

      首先先贴一下运行截图:

      

      等过10s之后的运行结果是:

      

    这里只是测试一下handler的post()方法是否是在主线程中进行的。所以没有布局。

    设计思路:

    在主线程中输出主线程当前的ID和Name,然后使用Runnable方式新建一个线程,在这个新线程中让程序睡眠10s,将这个线程使用Handler的post()方法发送到主线程中,看是否是执行异步加载。也就是验证handler是否是异步加载方式。结论:Handler不是异步加载方式。

    MainActivity:

    package com.example.handlertest1;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.app.Activity;
    import android.view.Menu;
    
    public class MainActivity extends Activity {
    
    	private Handler mhandler = new Handler();
    	
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		//将多线程发送到消息队列中
    		mhandler.post(r);
    		//不会立刻加载界面,这说明了handler并不是开辟了一个新的线程而是在主线程中进行的。
    		setContentView(R.layout.activity_main);
    		System.out.println("Activity-->"+Thread.currentThread().getId());
    		System.out.println("Activity-->"+Thread.currentThread().getName());
    	}
    
    	Runnable r = new Runnable() {
    		public void run() {
    			System.out.println("Handler--->"+Thread.currentThread().getId());
    			System.out.println("handler--->"+Thread.currentThread().getName());
    			try {
    				Thread.sleep(10000);
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    	};
    	
    }
    

    LogCat文件的输出:

     

    在这里通过ID号很明显的看出这不是执行的是多线程加载

    在上面的主线程中重新新建一个线程则实现了多线程的加载:

    将上面的onCreate()中的代码替换为:

    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //将多线程发送到消息队列中
    //        mhandler.post(r);
            //不会立刻加载界面,这说明了handler并不是开辟了一个新的线程而是在主线程中进行的。
            setContentView(R.layout.activity_main);
            //这是另外开启了一个新的线程,会发现这里输出的速率会比上次的快很多
            Thread t = new Thread(r);
            t.start();
            System.out.println("Activity-->"+Thread.currentThread().getId());
            System.out.println("Activity-->"+Thread.currentThread().getName());
        }

    效果截图如下:

    LogCat文件中的输出结果截图为:

    在这里通过ID号很明显的看出了这是执行了多线程加载。

      Handler要想开辟一个新的线程需要使用HanderThread()方法。下面就是HandlerThread()的用法:

    设计思路:

      通过使用handler方法传输数据,然后使用HandlerThread,实现了使用Looper来处理消息队列的功能。输出当前的Activity的ID和Name,以及Handler的ID和Name以及传输的数据

    代码如下:

     1 package com.example.handlertest1;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.os.Handler;
     6 import android.os.HandlerThread;
     7 import android.os.Looper;
     8 import android.os.Message;
     9 
    10 public class HandlerTest2 extends Activity{
    11 
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         setContentView(R.layout.activity_main);
    16         
    17         //打印当前线程的ID和当前线程的名字
    18         System.out.println("Activity-->"+Thread.currentThread().getId());
    19         System.out.println("Activity-->"+Thread.currentThread().getName());
    20         
    21         //HandlerThread是以键值对的形式进行存储的,这里的handler_thread就是该handler的键名
    22         //生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能。这是有android来提供的并不是java中的Thread提供
    23         HandlerThread handlerthread = new HandlerThread("handler_thread");
    24         handlerthread.start();
    25         MyHandler myhandler = new MyHandler(handlerthread.getLooper());
    26         Message msg = myhandler.obtainMessage();
    27         //传送多的数据的时候使用的setData()方法,使用Bundle()将数据包装
    28         Bundle b = new Bundle();
    29         b.putInt("age", 20);
    30         b.putString("name", "张三");
    31         msg.setData(b);
    32         //将消息发送给目标,目标就是生成该msg对象的handler
    33         msg.sendToTarget();
    34         
    35     }
    36     
    37     class MyHandler extends Handler{
    38         
    39         public MyHandler(){
    40             
    41         }
    42         public MyHandler(Looper looper){
    43             super(looper);
    44         }
    45         
    46         @Override
    47         public void handleMessage(Message msg) {
    48             Bundle b = msg.getData();
    49             int age = b.getInt("age");
    50             String name = b.getString("name");
    51             System.out.println("age is"+age+",name"+name);
    52             System.out.println("Handler--->"+Thread.currentThread().getId());
    53             System.out.println("Handler--->"+Thread.currentThread().getName());
    54             System.out.println("handlermessage");
    55         }
    56         
    57     }
    58     
    59 }

    好了,就这么多了,具体的关于Handler、Looper、Message三者的关系,参考http://blog.csdn.net/lmj623565791/article/details/38377229个人感觉不错

  • 相关阅读:
    hadoop2.2.0 centos6.4 编译安装详解
    Hadoop 2.2.0的高可用性集群中遇到的一些问题(64位)
    Visual Studio 常用快捷键
    Android(1)—Mono For Android 环境搭建及破解
    IbatisNet SqlMap.config配置节导致的程序无法通过
    CAD数据分块,偏移校准,加载到百度地图、高德地图、谷歌等地图上
    数据库SQL优化大总结
    Scratch 3下载,最新版Scratch下载,macOS、Windows版
    高性能网站设计之缓存更新的套路
    【验证无效】MySQL的count(*)的优化,获取千万级数据表的总行数
  • 原文地址:https://www.cnblogs.com/bingbingliang-xiaomonv/p/5462685.html
Copyright © 2011-2022 走看看