操作UI时报错,先贴上完整的异常信息栈。简单翻译一下就是,线程调用异常:只有创建了视图层级的原始线程才可以修改这个视图

 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6648)        at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:976)        at android.view.ViewGroup.invalidateChild(ViewGroup.java:5084)        at android.view.View.invalidateInternal(View.java:12743)        at android.view.View.invalidate(View.java:12707)        at android.view.View.invalidate(View.java:12691)        at android.widget.TextView.checkForRelayout(TextView.java:7168)        at android.widget.TextView.setText(TextView.java:4357)        at android.widget.TextView.setText(TextView.java:4214)        at android.widget.TextView.setText(TextView.java:4189)        at org.lujx.MainActivity$2.run(MainActivity.java:148)        at java.lang.Thread.run(Thread.java:818)

这个问题是这样产生的,在Honeycomb SDK 版本,也就是level 11以上的安卓版本,要求将网络请求等耗时操作放在一个单独的线程中进行而不是在UI线程,在这个独立的线程处理完毕后,有时候需要将返回的信息放在UI界面中显示,由于android的线程安全机制问题,UI线程不允许其他线程直接修改UI组件的内容,所以抛出这个异常。

问题的解决办法有两种:

1.使用handler接收单独立的网络请求线程的返回结果,并处理UI。

Handler handler = new Handler() {    @Override    public void handleMessage(Message msg) {       super.handleMessage(msg);       if (msg.what == 1) {         Bundle data = msg.getData();         String val = data.getString("value");         //设置UI         tvCode.setText(val);         Log.i(TAG, "请求结果:" + val);       } else if (msg.what ==0) {         Toast.makeText(getApplicationContext(),"请求资源不成功",Toast.LENGTH_LONG).show();       }  }};/** * 处理网络请求的线程 */private class RequestThread extends Thread {  @Override  public void run() {          //网络请求     String string = 请求结果     Message msg = new Message();     Bundle data = new Bundle();    //将获取到的String装载到msg中     data.putString("value", string);     msg.setData(data);     msg.what = 1;     //发消息到主线程     handler.sendMessage(msg);               }}//点击事件启动新线程public void test(View v){   new RequestThread().start();}

2.使用 runOnUiThread API接口,先看一下官方文档的解释,使用这个API可直接在其他线程中处理UI事件,不必担心线程安全问题。因为sdk已经帮我们想好了办法。

    /**     * Runs the specified action on the UI thread. If the current thread is the UI     * thread, then the action is executed immediately. If the current thread is     * not the UI thread, the action is posted to the event queue of the UI thread.     *     * 执行特定的UI线程上的操作,如果当前线程就是UI线程,此操作会立即执行。     * 如果不是,该操作会被发送到UI线程中的事件消息队列中     * @param action the action to run on the UI thread     */    public final void runOnUiThread(Runnable action) {        if (Thread.currentThread() != mUiThread) {            mHandler.post(action);        } else {            action.run();        }    }

具体使用方法如下

public void test(View v){     final String str  = 网络请求结果;     runOnUiThread(new Runnable() {         @Override         public void run() {          //更改UI;          tvCode.setText(str);        }     }); }

两种方法中,后面一种比较简单,如果只是修改UI,建议使用第二种,但是handler可以携带很多的数据,这一点第二种是无法做到了,所以在需要往主线中传递数据时,选择第一种。总之,视需要而定。

更多相关文章

  1. android http post请求
  2. Android原生SQLite操作以及greenDao框架操作SQLite
  3. android对sqlite数据库操作(创建 增 删 改 查)
  4. [android] Http Post 请求
  5. Android中ProgressDialog的使用
  6. Poco库使用 CMake 编译,支持 NetSSL
  7. android 反编译操作
  8. 有关Intent的android的API
  9. Android中线程的处理

随机推荐

  1. android 6.0 logcat机制(三)logd处理请求lo
  2. Android开发学习系列(一)——Android按钮圆
  3. Capacitor+Vue+Vant移动端打包总结
  4. Android使用控件ImageView加载图片的方法
  5. Android Studio Gradle自动打包文档
  6. Android中Service服务详解(一)
  7. Android 滑动效果进阶篇(六)—— 倒影效果
  8. Android自定义UI手势密码改进版源码下载
  9. Android应用开发揭秘(笔记) 第六章 Android
  10. Android集成第三方支付