笔记55 | 处理CalledFromWrongThreadException错误问题

来源:互联网 发布:mdb数据库编辑器 编辑:程序博客网 时间:2024/05/18 20:35

报错说明

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

12-20 15:39:04.730: E/AndroidRuntime(2763):     FATAL EXCEPTION: Timer-012-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();    }}

我的Android征途

原创粉丝点击