赵雅智_handler

直接在UI线程中开启子线程来更新内容,运行程序我们会发现,如下错误:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

翻译过来就是:只有创建这个控件的线程才能去更新该控件的内容。

所有的UI线程要去负责View的创建并且维护它,例如更新冒个TextView的显示,都必须在主线程中去做,我们不能直接在UI线程中去创建子线程,要利用消息机制:handler,如下就是handler的简单工作原理图:

 

handler基本使用:

 

在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中提供收到消息后相应的处理方法即可

我们使用myThreadHandler.sendEmptyMessage(0);发送一个message对象,那么Handler是如何接收该message对象并处理的呢?我先画一个数据结构图:

 

从这个图中我们很清楚可以看到调用sendEmptyMessage后,会把Message对象放入一个MessageQueue队列,该队列属于某个Looper对象,每个Looper对象通过ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取Message对象,并把Message对象交由Handler处理,调用HandlerdispatchMessage方法。

 

实例:使用handler在视图中显示服务器显示信息。运行如下图所示:

  


主要代码:布局文件同上篇(http://blog.csdn.net/zhaoyazhi2129/article/details/26624399

package com.example.android_http;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.example.util.StreamTools;

public class LoginActivity extends Activity {
	private EditText et_username;
	private EditText et_password;

	private TextView tv_result;
	private final int CHANGETEXTVIEW = 1;
	
	//消息处理者
	private Handler handler = new Handler(){

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			int what = msg.what;//标识
			switch (what) {
			case CHANGETEXTVIEW://这个消息就改变TextView控件的操作
				String result = (String) msg.obj;//附带的对象
				tv_result.setText(result);//改变控件内容
				Toast.makeText(LoginActivity.this, result, Toast.LENGTH_LONG).show();
				break;

			default:
				break;
			}
		}
		
	};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_login);
		findView();

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.login, menu);
		return true;
	}

	public void findView() {
		et_password = (EditText) findViewById(R.id.editpass);
		et_username = (EditText) findViewById(R.id.editusername);
		tv_result = (TextView) findViewById(R.id.tv_result);
	}

	public void login(View v) {
		// 获取点击控件的id
		int id = v.getId();
		// 根据id进行判断
		switch (id) {
		case R.id.btn_login:// 进行登录操作
			// Toast.makeText(getApplicationContext(), "--", 0).show();
			// 获取用户名密码
			final String userName = et_username.getText().toString();
			final String userPass = et_password.getText().toString();

			// 判断是否为空
			if (TextUtils.isEmpty(userName) || TextUtils.isEmpty(userPass)) {
				Toast.makeText(getApplicationContext(), "用户名或者密码不能为空", 0)
						.show();
			} else {
				Toast.makeText(getApplicationContext(), "發送請求道服務器", 0)
				.show();
				// 访问网络(需要一个网络的权限)
				// 访问网络(好事操作)子线程,避免阻塞主线程UI
				// http://172.16.237.200:8080/video/login.do?username=chj&userpass=123

				// 所有耗時操作都要在子線程中
				new Thread() {
					public void run() {
						try {
							// 请求地址
							String spec = "http://172.16.237.200:8080/video/login.do?username="
									+ userName + "&userpass=" + userPass;
							// 根据地址创建URL对象(网络访问url)
							URL url = new URL(spec);
							// 采用http协议打开的连接对象
							HttpURLConnection urlConnection = (HttpURLConnection) url
									.openConnection();
							urlConnection.setRequestMethod("GET");// 以get方式发起请求
							urlConnection.setReadTimeout(5000);// 设置超时
							urlConnection.setConnectTimeout(5000);// 设置连接超时
							urlConnection
									.setRequestProperty("User-Agent",
											"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0");
							// 获取相应的 code 400 200 505 302
							if (urlConnection.getResponseCode() == 200) {
								// 得到网络返回的输入流
								InputStream is = urlConnection.getInputStream();
								//通过工具类处理
								String result = StreamTools.streamToStr(is);
								
								Message msg = new Message();
								msg.what = CHANGETEXTVIEW;//消息的唯一标志
								msg.obj = result;//改变的内容通过object传过去
								
								handler.sendMessage(msg);//发送消息
								
								System.out.println("返回的数据是:" + result);
							} else {
								System.out.println("请求url失败");
							}

						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					};
				}.start();

			}
			break;

		default:
			break;
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值