如何动态修改TextView?Android线程异常问题求助
看起来你遇到了Android开发中非常常见的线程操作UI问题,从错误日志可以明确定位到问题根源:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Android有严格的UI线程规则:只有创建View层级的主线程(也就是UI线程)才能操作UI控件,你的代码在子线程直接更新TextView,触发了这个异常。
问题代码分析
你在getHTMLArticoli方法中通过ExecutorService开启了子线程,在子线程里同步获取HTML内容后,调用了getBodyArticoli方法,而这个方法里直接执行了:
textView.setText(String.valueOf(DoveSono);
这行代码运行在子线程中,违反了Android的UI操作规则,直接导致应用崩溃。另外注意这行代码还有语法错误——少了一个右括号,修正后应为textView.setText(String.valueOf(DoveSono));。
解决方案
方案1:临时修复——切换到主线程更新UI
最简单的修改方式是把更新TextView的逻辑包裹在runOnUiThread中,强制UI操作在主线程执行:
// 替换你原来的setText代码块 if(CONTACAMPO.equals(QuantiCampi)){ CONTACAMPO = 0; myDB.insertArtServer(appBODYart[0], appBODYart[1], appBODYart[2], appBODYart[3], appBODYart[4], appBODYart[5], appBODYart[6], appBODYart[7], appBODYart[8]); DoveSono +=0; // 切换到主线程更新TextView runOnUiThread(new Runnable() { @Override public void run() { textView.setText(String.valueOf(DoveSono)); } }); }
方案2:更优解——利用Ion的异步回调(推荐)
Ion库本身就支持异步回调,且默认在主线程执行回调逻辑,完全不需要手动创建ExecutorService,从根源避免线程问题:
修改你的getHTMLArticoli方法:
private void getHTMLArticoli(){ // progressDialog = new SpotsDialog(articoli.this, R.style.Custom); // progressDialog.show(); Ion.with(getApplicationContext()) .load("WEBSITEIP") .asString() .setCallback(new FutureCallback<String>() { @Override public void onCompleted(Exception e, String htmlresultart) { if (e != null) { e.printStackTrace(); return; } if (htmlresultart != null) { htmlresultart = htmlresultart.replace("</td>", "\n"); getTableArticoli(); getTestataArticoli(); getBodyArticoli(); // progressDialog.cancel(); } } }); }
这样onCompleted回调会在主线程执行,后续调用的getBodyArticoli里直接更新TextView就不会有线程问题了,还省去了手动管理线程的麻烦。
额外小建议
你的getBodyArticoli方法中的字符串截取循环逻辑比较复杂,要注意处理数组越界风险——确保appBODYart的长度足够容纳QuantiCampi个元素,避免出现ArrayIndexOutOfBoundsException。
内容的提问来源于stack exchange,提问作者John K

