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();

  

时间: 2024-10-14 13:53:34

Android多线程更新UI的方式的相关文章

Android异步更新UI的方式之使用AsyncTask异步任务

由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中更新UI,给大家介绍一种方式:使用AsyncTask异步任务. 下面用这种方式更新一个TextView: 注:更新UI的操作只能在onPostExecute(String result)方法中. package com.example.runonuithreadtest;  import android.app.Activity;  import android.os.AsyncTask;  import android.

Android异步更新UI的方式之使用Handler的post(Runnabel r)方法

由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中更新UI,给大家介绍一种方式:使用Handler的post(Runnabel r)方法 下面用这种方式更新一个TextView: package com.example.runonuithreadtest;  import android.app.Activity;  import android.os.Bundle;  import android.os.Handler;  import android.widget.T

Android异步更新UI的方式之使用runOnUiThread(action)方法

由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中更新UI,给大家介绍一种方式:使用runOnUiThread(action)方法 下面用这种方式更新一个TextView: 1.  package com.example.runonuithreadtest; 2.  import android.app.Activity; 3.  import android.os.Bundle; 4.  import android.widget.TextView; 5.  publi

Android异步更新UI的方式之使用Handler消息传递机制

由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中更新UI,给大家介绍一种方式:使用Handler消息传递机制. 下面用这种方式更新一个TextView: package com.example.runonuithreadtest; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; public

Android中多线程编程(三)Handler更新UI的方式

Handler更新UI的方式和原因以及遇到的问题 1.方式: 只能通过Handler来更新UI. 代码如下: package com.chengdong.su.handlerdemo; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.

Android攻城狮 Android中更新UI的几种方式

Android中更新UI的几种方式: 1. Activity 的 runOnUiThread() 2. Handler 的 post() 3. Handler 的 sendMessage() 4. View 的 post() 1 public class FiveActivity extends Activity { 2 3 private TextView textView; 4 5 private Handler handler = new Handler() { 6 public void

android异步更新UI界面的方法

在android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处理,然后更新用户界面显示.但是,在主线线程之外的线程中直接更新页面显示的问题是:系统会报这个异常,android.view.viewroot$calledfromwrongthreadexception: only the original thread that created a view hierarchy can touch its views. (只有原始创建这个视图层次(view hierach

Android 线程更新UI报错 : Can't create handler inside thread that has not called Looper.prepare()

MainActivity中有一个按钮,绑定了save方法 public void save(View view) { String title = titleText.getText().toString(); String timelength = lengthText.getText().toString(); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new NewsService(getApp

android中子线程更新UI的方式浅析

一.为何写作此文 ??你是不是经常看到很多书籍中说:不能在子线程中操作ui,不然会报错.你是不是也遇到了如下的疑惑(见下面的代码): @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); Threa