Android异常:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original

本文介绍了在Android开发中如何解决子线程更新UI的问题,详细解释了Handler机制的工作原理,并给出具体的实现代码示例。

Android异常:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

出现这个异常的原因是你在子线程中修改了主线程中的组件的状态或数据。.翻译过来就是:只有创建这个控件的线程才能去更新该控件的内容。

android规定:只有在原始线程中(主线程,UI线程)才能修改显示组件。

解决方案:1、使用Handler机制。2、使用AsyncTask

方案1概述:handler机制

如下就是handler的简单工作原理图:


既然android给我们提供了Handler机制来解决这样的问题,请看如下代码:

class MyOnclickListener implements OnClickListener {
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		// 响应Handler异步方式
		case R.id.downbtn1:
			// 显示进度对话框,这里也可以使用进度条,在handleMessage方法中更新进度
			dialog = ProgressDialog.show(DownLoadImageActivity.this, "",
					"正在下载,请稍等···");
			// 新建一个子线程来发送消息
			new Thread() {
				@Override
				public void run() {
					try {
						// 让ProgressDialog显示一会儿。。。。
						Thread.sleep(2000);
						URL url = new URL(PATH);
						// 建立网络连接
						HttpURLConnection conn = (HttpURLConnection) url
								.openConnection();
						InputStream inputStream = conn.getInputStream();
						// 获取图片数据
						bitmap = BitmapFactory.decodeStream(inputStream);
						inputStream.close();
						Message message = new Message();
						message.what = 1;
						// 发送消息到消息队列中
						handler.sendMessage(message);
					} catch (Exception e) {
						Message message = new Message();
						message.what = -1;
						handler.sendMessage(message);
						e.printStackTrace();
					}
				}
			}.start();
			break;
		// 响应AsyncTask异步方式
		case R.id.downbtn2:
			new DownImageTask().execute(PATH);
			break;
		}
	}
}

// Handler异步方式下载图片
private Handler handler = new Handler() {
	public void handleMessage(android.os.Message msg) {
		ImageView imageView;
		switch (msg.what) {
		case 1:
			// 下载成功
			imageView = (ImageView) findViewById(R.id.image);
			dialog.dismiss();
			imageView.setImageBitmap(bitmap);
			break;
		case -1:
			// 下载失败使用默认图片
			imageView = (ImageView) findViewById(R.id.image);
			dialog.dismiss();
			imageView.setBackgroundResource(R.drawable.icon);
			break;
		}
	};
};


        我们就通过Handler机制来处理了子线程去更新UI线程控件问题,Andrid开发中要经常用到这种机制。
方式2以后再做介绍。


`android.view.ViewRootImpl$CalledFromWrongThreadException` 异常表明在非创建视图层次结构的原始线程中尝试访问或修改视图,而 Android 要求只能在主线程(也称为 UI 线程)中对视图进行操作。以下是几种常见的解决方法: ### 使用 Handler `Handler` 可以将消息从子线程发送到主线程的消息队列中,从而在主线程中处理视图操作。示例代码如下: ```java @SuppressLint("HandlerLeak") private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == COMPLETED) { right.setVisibility(View.GONE); } } }; // 延时 Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { Log.d("这里!!!!","111"); Message msg = new Message(); msg.what = COMPLETED; handler.sendMessage(msg); } }, 3700); ``` ### 使用 Activity 的 runOnUiThread 方法 `Activity` 提供了 `runOnUiThread` 方法,可将一个 `Runnable` 对象传递给该方法,让其在主线程中运行。示例如下: ```java new Thread(new Runnable() { @Override public void run() { // 模拟耗时操作 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // 在主线程中更新 UI runOnUiThread(new Runnable() { @Override public void run() { // 进行视图操作 right.setVisibility(View.GONE); } }); } }).start(); ``` ### 使用 View 的 post 方法 `View` 类的 `post` 方法也可以将一个 `Runnable` 对象放入消息队列中,该 `Runnable` 会在主线程中执行。示例如下: ```java new Thread(new Runnable() { @Override public void run() { // 模拟耗时操作 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // 在主线程中更新 UI right.post(new Runnable() { @Override public void run() { right.setVisibility(View.GONE); } }); } }).start(); ``` ### 使用 AsyncTask(适用于较旧的 Android 版本) `AsyncTask` 是 Android 提供的一个抽象类,用于在后台线程执行异步任务,并在主线程中更新 UI。示例如下: ```java private class MyTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... voids) { // 模拟耗时操作 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { // 在主线程中更新 UI right.setVisibility(View.GONE); } } // 执行任务 new MyTask().execute(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值