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/

      

  • 相关阅读:
    ExecuteScalar requires the command to have a transaction when the connection assigned to the command is in a pending
    如何从vss中分离程序
    String or binary data would be truncated
    the pop3 service failed to retrieve authentication type and cannot continue
    The POP3 service failed to start because
    IIS Error he system cannot find the file specified _找不到页面
    pku2575Jolly Jumpers
    pku2940Wine Trading in Gergovia
    pku3219二项式系数
    pku1029false coin
  • 原文地址:https://www.cnblogs.com/fengtengfei/p/3969520.html
Copyright © 2011-2022 走看看