您的位置:首页 > 其它

笔记55 | 处理CalledFromWrongThreadException错误问题

2017-12-21 10:06 316 查看

报错说明

直接在子线程更新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();
}
}


我的Android征途

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐