zoukankan      html  css  js  c++  java
  • Android多线程更新UI的方式

    Android下,对于耗时的操作要放到子线程中,要不然会残生ANR,本次我们就来学习一下Android多线程更新UI的方式。

      首先我们来认识一下anr:

      anr:application not reponse:应用程序无响应
      主线程:UI线程
      anr产生的原因:主线程需要做很多重要的事情,响应点击事件,更新ui,如果在主线程里面阻塞时间过久,应用程序就会无响应,为了避免应用程序出现anr,所有的耗时的操作,都应该放在子线程中执行。

      认识了anr后,我们就来学习一下怎样在Android下开启多线程,并更新ui了。一共有两种方式:

    第一种采用:Handler。

      Handler获取当前线程中的looper对象,looper用来从存有Message的Message Queue里取出message,再由Handler进行message的分发和处理。

    handler进制的原理

      android提供了handler和looper来满足线程间的通信。Handler先进先出原则。looper用来管理特定线程内对象之间的消息交换(message Exchange).

         1)looper:一个线程可以产生一个looper对象,由它来管理此线程里的message queue(消息队列)

          2)handler:你可以构造一个handler对象来与looper沟通,以便push新消息到messagequeue里;或者接收looper(从messagequeue里取出)所送来的消息。

    我们使用的时候呢,需要在子线程中定义message,并把要返回的obj对象,传递给msg,同时由于handler不止要处理这一种类型,所以我们还要定义what的类型,以便让handler分类处理。

    	Message msg = new Message();
    	msg.what = CHANGE_UI;
    	msg.obj = result;
    	handler.sendMessage(msg);
    

    好的接下来我们就实例来使用handler。

    		   new Thread(){
    			   public void run() {
    				   try {
    					URL url = new URL(path);
    					HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    					conn.setRequestMethod("GET");
    					conn.setConnectTimeout(5000);
    					conn.setRequestProperty("User-Agent", "");
    					
    					int code = conn.getResponseCode();
    					if(code==200){
    						InputStream is = conn.getInputStream();
    						String result = StreamTools.readInputStream(is);
    						
    						//tv_content.setText(result);
    						Message msg = new Message();
    						msg.what = CHANGE_UI;
    						msg.obj = result;
    						handler.sendMessage(msg);
    						
    						
    					}else{
    						Message msg = new Message();
    						msg.what = ERROR;
    						handler.sendMessage(msg);
    					}
    					
    				} catch (Exception e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    					
    					Message msg = new Message();
    					msg.what = ERROR;
    					handler.sendMessage(msg);
    					
    					
    				}
    				   
    				   
    			   };
    		   }.start();
    

     这里采用的 StreamTools.readInputStream的实现是这样的,目的是把输入流转化为字符串。

    /**
    	 * 把输入流转化为字符串
    	 * @param is
    	 * @return
    	 */
    	public static String readInputStream(InputStream is){
    		try {
    			ByteArrayOutputStream baos = new ByteArrayOutputStream();
    			int len = 0;
    			byte[] buffer = new byte[1024];
    			while((len = is.read(buffer))!=-1){
    				baos.write(buffer,0,len);
    			}
    			is.close();
    			baos.close();
    			byte[] result = baos.toByteArray();
    			
    			//试着解析网址返回的字符串,
    			String temp = new String(result);
    			if(temp.contains("utf-8")){
    				return temp;
    			}else if(temp.contains("gbk")){
    				return new String(result,"gbk");
    			}
    			
    			return temp;
    			//return new String(result);
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    			return "获取失败";
    		}
    		
    	}
    

    其中handler的实现是这样的。

    	
    	private Handler handler = new Handler(){
    		public void handleMessage(android.os.Message msg) {
    			switch (msg.what) {
    			case ERROR:
    				Toast.makeText(MainActivity.this, "获取数据失败", 0).show();
    				break;
    			case CHANGE_UI:
    				tv_content.setText(msg.obj+"");
    				Toast.makeText(MainActivity.this, "获取数据失败", 0).show();
    				break;
    
    			}
    		};
    	};
    

     这样呢,我们便可以用handler,也即消息处理机制来更新UI了,

    第二种方式。

      采用runOnUiThread(new Runnable()),这要实现Runnable借口,我们可以直接在这个线程中进行UI的更新。是api提供的方法,较为便捷。

      

    	new Thread(){
        		@Override
        		public void run() {
        			final String result = LoginServices.loginByGet(username, password);
        			if(result != null){
        				//成功
        				runOnUiThread(new Runnable() {
    						
    						@Override
    						public void run() {
    							// TODO Auto-generated method stub
    							Toast.makeText(MainActivity.this, result, 0).show();
    						}
    					});
        			}else{
        				//请求失败
        				runOnUiThread(new Runnable() {
    						
    						@Override
    						public void run() {
    							// TODO Auto-generated method stub
    							Toast.makeText(MainActivity.this, "请求失败", 0).show();
    						}
    					});
        			}
        			
        		};
        	}.start();
    

    源码:https://github.com/darren90/ChengeUI

    作者:Darren

    微博:@IT_攻城师

    出处:http://www.cnblogs.com/fengtengfei/

      

  • 相关阅读:
    细看JS中的BOM、DOM对象
    IE假死,文本框不能录入div模拟模式对话框释放不干净
    发布一个cmd 设置IP地址的脚本.
    解决一个用Request.Form 取checkbox 取不到值的问题.
    在Global.asax中实现URL 的重写.
    .net 递归生成树,根据编码进行递归.
    发布一篇 DataTable 转化为适合 jquery easyui tree,combotree 的json 函数
    批量插入数据sql
    添加背景音乐由icon控制
    echarts使用macarons主题
  • 原文地址:https://www.cnblogs.com/fengtengfei/p/3969520.html
Copyright © 2011-2022 走看看