笔记55 | 处理CalledFromWrongThreadException错误问题

报错说明

直接在子线程更新UI会报CalledFromWrongThreadException错,错误如下:

12-20 15:39:04.730: E/AndroidRuntime(2763):     FATAL EXCEPTION: Timer-0
12-20 15:39:04.730: E/AndroidRuntime(2763):     android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4775)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:833)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.View.requestLayout(View.java:15499)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.View.requestLayout(View.java:15499)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.View.requestLayout(View.java:15499)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.View.requestLayout(View.java:15499)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:318)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.View.requestLayout(View.java:15499)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.View.setFlags(View.java:8450)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at android.view.View.setVisibility(View.java:5720)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at com.evan.http.MainActivity.NETData(MainActivity.java:41)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at com.evan.http.MainActivity.access$0(MainActivity.java:29)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at com.evan.http.MainActivity$5.run(MainActivity.java:72)
12-20 15:39:04.730: E/AndroidRuntime(2763):     at java.util.Timer$TimerImpl.run(Timer.java:284)

为什么会出现这个问题,这里有一篇大神的解答关于为什么不能再子线程中更新UI的讨论大神对代码的解读能力让人兴叹,总结来说是因为子线程没有创建Looper.prepare()这个与子线程不能Toast的问题是一样的Toast为什么不可以在子线程里面运行


解决方案

1.  Activity.runOnUiThread(Runnable);
   2.  Handler(sendMessage(Message) or post(Runnable));
   3.  AsyncTask ;

我用的是第一种方案: 把这个Runnable对象传给runOnUiThread(Runnable)。 这样Runnable对像就能在ui程序中被调用

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myClickHandler();
        initTime();
        initView();
    }

    private void NETData() {
        tv_net.setVisibility(View.GONE);
        if (net) {
            runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.i("md", "ture");
            }
        });
        new Thread(){
        }.start();
        }else{
            tv_net.setVisibility(View.VISIBLE);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.i("md", "false");
                }
            });
            new Thread(){
            }.start();
        }
    }

    TextView tv_net;
    private void initView() {
        tv_net=(TextView) findViewById(R.id.tv_netinfo);
    }

    Timer timer;
    TimerTask timerTask;
    private void initTime() {
        if (timer==null) {
            timer = new Timer();
        }
        if (timerTask!=null) {
            timerTask.cancel();
        }
        timerTask = new TimerTask() {

            @Override
            public void run() {
                myClickHandler();
                NETData();
            }
        };
        timer.schedule(timerTask,50,5000);
    }

    public void myClickHandler() {
        ConnectivityManager connMgr = (ConnectivityManager)
                getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    networking(timei);
                    timei=(int) SystemClock.uptimeMillis();
                    net=true;
                }
            });
            new Thread(){
            }.start();
        } else {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Netend(timei);
                    net=false;
                }
            });
            new Thread(){
            }.start();
        }
    }

    int timei;
    boolean net;
    private void networking(int i) {
            if (((int) SystemClock.uptimeMillis()-timei)>5050) {
                Toast.makeText(MainActivity.this, "连接到网络!", 0).show();
            }
    }
    private void Netend(int i) {
                Toast.makeText(MainActivity.this, "当前无网络!", 0).show();
    }
}

原文发布于微信公众号 - 项勇(xiangy_life)

原文发表时间:2017-12-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏转载gongluck的CSDN博客

cocos2dx 打灰机

#include "GamePlane.h" #include "PlaneSprite.h" #include "BulletNode.h" #include...

5486
来自专栏码匠的流水账

聊聊NettyConnector的start及shutdown

reactor-netty-0.7.6.RELEASE-sources.jar!/reactor/ipc/netty/NettyConnector.java

881
来自专栏魂祭心

原 canvas绘制clock

4104
来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2546
来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

31810
来自专栏Ceph对象存储方案

Luminous版本PG 分布调优

Luminous版本开始新增的balancer模块在PG分布优化方面效果非常明显,操作也非常简便,强烈推荐各位在集群上线之前进行这一操作,能够极大的提升整个集群...

3145
来自专栏菩提树下的杨过

Flash/Flex学习笔记(23):运动学原理

先写一个公用的小球类Ball: package{ import flash.display.Sprite; //小球 类 public class B...

25310
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4868
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

6868
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4035

扫码关注云+社区