android报错android.view.ViewRootImpl$CalledFromWrongThreadException【本文转载】

报错信息:android.view.ViewRootImpl$CalledFromWrongThreadException

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)

报错原因:操作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();
        }
    }

3、如果是初次使用线程的新手先确认一下是否必须使用线程,之前遇到过在主线程中没有任何程序,却在里面建立一个子线程,进行跑程序

————————————————
版权声明:本文为CSDN博主「lujx_1024」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/LJX_ahut/article/details/89432576

猜你喜欢

转载自www.cnblogs.com/hahayixiao/p/12132428.html