为什么我的Thread会导致整个Android应用崩溃?
解决TextView闪烁导致应用崩溃的问题
问题根源
你在自定义线程里直接调用lastletter.setVisibility()修改UI控件状态——Android明确规定所有UI操作必须在主线程(UI线程)中执行,非UI线程操作UI会触发CalledFromWrongThreadException,直接导致应用崩溃。
修复方案
方案1:用runOnUiThread包裹UI操作
把修改TextView可见性的代码放到runOnUiThread的Runnable中,让UI操作切换回主线程执行:
Thread blinkThread = new Thread(){ @Override public void run() { for(int i = 0; i < 10; i++){ // 切换到主线程设置可见 runOnUiThread(() -> lastletter.setVisibility(View.VISIBLE)); try { sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } // 切换到主线程设置隐藏 runOnUiThread(() -> lastletter.setVisibility(View.INVISIBLE)); try { sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } };
方案2:用Handler实现线程通信
创建主线程Handler,子线程通过发送消息让Handler处理UI操作:
// 在MainActivity中定义Handler private Handler blinkHandler = new Handler(Looper.getMainLooper()){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what == 0){ lastletter.setVisibility(View.VISIBLE); } else if(msg.what == 1){ lastletter.setVisibility(View.INVISIBLE); } } }; // 线程代码修改为: Thread blinkThread = new Thread(){ @Override public void run() { for(int i = 0; i < 10; i++){ blinkHandler.sendEmptyMessage(0); try { sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } blinkHandler.sendEmptyMessage(1); try { sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } };
方案3:推荐用属性动画实现(更简洁优雅)
不用手动管理线程,直接用Android的属性动画控制TextView的透明度,自动处理UI线程问题:
// 在onCreate中直接启动动画 ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(lastletter, "alpha", 1f, 0f, 1f); alphaAnimator.setDuration(1000); // 一次闪烁周期(显示+隐藏)1000ms alphaAnimator.setRepeatCount(9); // 重复9次,总共执行10次闪烁 alphaAnimator.start();
如果需要无限循环闪烁,把setRepeatCount替换为alphaAnimator.setRepeatMode(ValueAnimator.RESTART);即可。
内容的提问来源于stack exchange,提问作者Matteo Passaro
相关产品推荐
相关产品推荐

