在run()中,我如何调用方法而不使我的应用程序崩溃(Java/Android)?
我想做一个简单的小程序,每秒递增一个数字。在本例中,我实现了一个线程,它应该每秒循环一次,每次循环时向“土豆”添加1。在返回到display方法potatoDisp()之前,它工作正常。由于某种原因,这会导致我的应用程序崩溃。从run()中删除potatoDisp()可以解决此问题,但显示不会随着“土豆”的增加而更新在run()中,我如何调用方法而不使我的应用程序崩溃(Java/Android)?,java,android,Java,Android,我想做一个简单的小程序,每秒递增一个数字。在本例中,我实现了一个线程,它应该每秒循环一次,每次循环时向“土豆”添加1。在返回到display方法potatoDisp()之前,它工作正常。由于某种原因,这会导致我的应用程序崩溃。从run()中删除potatoDisp()可以解决此问题,但显示不会随着“土豆”的增加而更新 public int potato = 0; @Override protected void onCreate(Bundle savedInstanceState) {
public int potato = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
potatoDisp();
start();
}
public void potatoDisp() {
TextView text = (TextView) findViewById(R.id.textView1);
text.setText("You currently have " + potato + " potatoes");
}
public void start() {
Thread thread = new Thread(this);
thread.start();
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
potato++;
potatoDisp();
}
}
如果有帮助的话,我是为Android应用程序做这件事的。我尝试过寻找答案,但对于如何正确处理线程,我感到非常困惑。在后台更新
UI
可能会遇到异常。因为,potatoDisp()
是从后台线程调用的
,但该函数会更新UI
,它会给您带来问题。您需要使用runOnUiThread()
调用它
类似的东西应该可以使用。您需要这样一个可运行/处理程序:
private Runnable potatoRun = new Runnable() {
@Override
public void run () {
potatoDisp();
}
};
然后改变
potatoDisp();
致:
当您不在UI线程上时,无法更新视图。问题是您试图在主UI线程以外的线程上更新UI(调用
text.setText(…)
)
虽然我建议使用TimerTask
而不是调用Thread.sleep(…)
,但有两种主要方法可以编辑当前代码,使其按预期工作
--使用处理程序
定义一个处理程序
类,该类将接受消息并根据需要更新UI。例如:
private final String POTATO_COUNT = "num_potatoes";
Handler handler = new Handler() {
public void handleMessage(Message msg) {
int numPotatoes = msg.getData.getInt(POTATO_COUNT);
mText.setText("You currently have " + numPotatoes + " potatoes");
}
}
然后,无论您是否在主UI线程上,在要调用处理程序以更新文本视图的代码中,执行以下操作:
Bundle bundle = new Bundle();
bundle.putInt(POTATO_COUNT, potato);
Message msg = new Message();
msg.setData(bundle);
handler.sendMessage(msg);
--调用runOnUiThread(…)
我认为您应该使用异步任务从一个线程更新UI:哦,那些土豆!发布崩溃日志。为什么要在主活动中重写run方法?你试过在一个单独的线程中运行你的计数器吗?现在不要使用logcat,但将来你应该发布它。这通常会帮助我们更容易地帮助你。看看我的答案,谢谢!这正是我要找的。不客气,很高兴我能帮上忙。很好的资源,@Eric这应该是一个评论。虽然这里可以使用
AsyncTask
,但OP的操作方式应该可以,他们只需要合并runOnUiThread()
。另外,AsyncTask
对于计算和更新单个TextView
来说可能有些过分。但是为什么不使用内置的功能来运行一个线程,该线程将更新用户界面,该界面也会为您处理线程池,并且(希望)不会导致任何应用程序延迟呢?注意:虽然您不太可能遇到更新之间暂停1秒的问题,但此处的runOnUiThread示例(以及在其他解决方案中)包含更新UI的主线程和更新计数器的另一个线程之间的争用条件。Handler
方法(或者让potatoDisp
接受马铃薯计数的int值)可以解决这个问题。
private final String POTATO_COUNT = "num_potatoes";
Handler handler = new Handler() {
public void handleMessage(Message msg) {
int numPotatoes = msg.getData.getInt(POTATO_COUNT);
mText.setText("You currently have " + numPotatoes + " potatoes");
}
}
Bundle bundle = new Bundle();
bundle.putInt(POTATO_COUNT, potato);
Message msg = new Message();
msg.setData(bundle);
handler.sendMessage(msg);
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
potato++;
runOnUiThread(new Runnable()
{
public void run()
{
potatoDisp();
}
}
}
}