Android错误:只有创建视图层次结构的原始线程才能触摸其视图[重复]
Posted
技术标签:
【中文标题】Android错误:只有创建视图层次结构的原始线程才能触摸其视图[重复]【英文标题】:Android Error: Only the original thread that created a view hierarchy can touch its views [duplicate] 【发布时间】:2013-06-15 03:02:28 【问题描述】:出现错误:android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触其视图。 我真的不知道为什么。
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button generate = (Button) findViewById(R.id.gen);
final TextView dice1 = (TextView) findViewById(R.id.dice1);
final TextView dice2 = (TextView) findViewById(R.id.dice2);
final TextView dice3 = (TextView) findViewById(R.id.dice3);
generate.setOnClickListener(new View.OnClickListener()
public void onClick(View v)
dice1.setText(" ");
dice2.setText(" ");
dice3.setText(" ");
Thread thread = new Thread()
@Override
public void run()
try
while(true)
sleep(2000);
setText("lol", "lol", "lol");
catch (InterruptedException e)
e.printStackTrace();
;
thread.start();
);
public void setText(String d1, String d2, String d3)
dice1.setText(d1);
dice2.setText(d2);
dice3.setText(d3);
感谢您的帮助。
【问题讨论】:
【参考方案1】:您遇到此错误是因为您在 UI 线程之外的另一个线程中操作视图。
你的setText
方法修改了3个TextView的文本(dice1
,dice2
,dice3
)。
你应该像这样用runOnUiThread
调用这个方法:
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button generate = (Button) findViewById(R.id.gen);
final TextView dice1 = (TextView) findViewById(R.id.dice1);
final TextView dice2 = (TextView) findViewById(R.id.dice2);
final TextView dice3 = (TextView) findViewById(R.id.dice3);
generate.setOnClickListener(new View.OnClickListener()
public void onClick(View v)
dice1.setText(" ");
dice2.setText(" ");
dice3.setText(" ");
Thread thread = new Thread()
@Override
public void run()
try
while(true)
sleep(2000);
runOnUiThread(new Runnable()
@Override
public void run()
setText("lol", "lol", "lol");
);
catch (InterruptedException e)
e.printStackTrace();
;
thread.start();
);
public void setText(String d1, String d2, String d3)
dice1.setText(d1);
dice2.setText(d2);
dice3.setText(d3);
【讨论】:
在线程内睡眠是一个糟糕的设计。 developer.android.com/training/articles/perf-anr.html @Raghunandan 如果您在主线程上调用 sleep() 是的,但在这种情况下不是。但是,可以肯定的是,例如使用AsynTask 可能比每次用户单击“生成”按钮时创建一个线程要好... 如果你实现了Thread or HandlerThread
,确保你的UI线程在等待工作线程完成时不会阻塞——do not call Thread.wait() or Thread.sleep()
。引用自文档。
是的,意思是“不要在UI线程上调用Thread.wait()等待另一个线程调用Thread.notify() i> 例如。在 UI 线程之外的另一个线程上调用 Thread.sleep()(或 Thread.wait())不会导致 ANR。
它阻塞了工作线程。所以不好。我不是说它会导致anr。【参考方案2】:
从字面上看,您是在尝试从错误的线程中设置视图中的字段。您的 OnClickListener 会创建一个新线程,但只有创建视图及其层次结构的线程才能更改这些视图。
你可以重构使用http://developer.android.com/reference/java/util/concurrent/ScheduledThreadPoolExecutor.html
或者,您可以将 setter 代码包装在 runOnUiThread 块内。此站点上有一个示例,并提醒您为什么这可能不是一个好主意:Android: RunOnUiThread vs AsyncTask。
【讨论】:
【参考方案3】:您将 setText 设置在一个单独的线程上。将调用操作 UI 组件的方法放在 runOnUiThread 块中。
【讨论】:
以上是关于Android错误:只有创建视图层次结构的原始线程才能触摸其视图[重复]的主要内容,如果未能解决你的问题,请参考以下文章
Android中的错误“只有创建视图层次结构的原始线程才能触摸其视图”[重复]
Android “只有创建视图层次结构的原始线程才能接触其视图。” for循环中的错误[重复]
CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触视图
致命例外:JavaBridge - 只有创建视图层次结构的原始线程才能接触其视图
android.view.ViewRootImpl $CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图[重复]