Android编程中,发生android.view.ViewRoot$CalledFromWrongThreadException异常的解决方案

本文介绍了在Android应用开发过程中如何正确地从非UI线程更新用户界面的方法,避免出现CalledFromWrongThreadException异常。提供了两种实用解决方案:使用Handler类处理消息及利用Activity.runOnUiThread(Runnable)方法。

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

  也就是说必须在一般必须在程序的主线程(也就是ui)线程中进行更新界面显示的工作。可以采用下面的方法之一来解决:

  解决方案1:在Activity.onCreate(Bundle savedInstanceState)中创建一个Handler类的实例, 在这个Handler实例的handleMessage回调函数中调用更新界面显示的函数。例如:

  view plaincopy to clipboardprint?

  public class ExampleActivity extends Activity {

  Handler h = null;

  @Override

  public void onCreate(Bundle savedInstanceState){

  h = new Handler(){

  @Override

  public void handleMessage(Message msg){

  // call updateGui method.

  }

  };

  }

  }

  public class ExampleActivity extends Activity {

  Handler h = null;

  @Override

  public void onCreate(Bundle savedInstanceState){

  h = new Handler(){

  @Override

  public void handleMessage(Message msg){

  // call updateGui method.

  }

  };

  }

  }

  在其它的函数中,利用 send族或post族函数向这个h发送或邮寄消息即可。

  解决方案2:利用Activity.runOnUiThread(Runnable)

  把更新ui的代码创建在Runnable中,然后在需要更新ui时,把这个Runnable对象传给Activity.runOnUiThread(Runnable)。 这样Runnable对像就能在ui程序中被调用。

 

http://www.cnmsdn.com/html/201009/1284080180ID7930.html

 

`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(); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值