【发布时间】:2016-10-13 18:50:29
【问题描述】:
我花了一段时间试图找出为什么我的模拟器一直卡住,原来是因为我引入了一个 while 循环。点击按钮后,输出一个随机数(LoadG1),4秒后消失。然后用户输入一个数字,如果它等于 loadg1,他们得到一个点,程序通过让另一个 loadg1 可用 4 秒然后消失等来循环......
除非它显然是它自己的线程,否则我不能有循环。我为它做了一个线程然后尝试了。按钮按下后整个应用程序冻结并没有发生,但是当 loadg1 启动 4 秒时,应用程序关闭。就好像循环的第一行有效,然后在 4 秒结束后失败。我收到以下错误:
android.view.ViewRootImpl$CalledFromWrongThreadException: 只有 创建视图层次结构的原始线程可以触及其视图。
查询后我发现我需要将它放在一个runOnUiThread中,所以我这样做了,只是遇到了同样的问题。这是我的代码:
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.Random;
public class game1 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game1);
final Button loseStarter1;
loseStarter1 = (Button) findViewById(R.id.Starter1);
loseStarter1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loseStarter1.setVisibility(View.GONE);
final int[] score = {0};
Random generateG1 = new Random();
final int loadG1 = generateG1.nextInt(1000000)+10000;
final TextView number = (TextView) findViewById(R.id.number);
number.setText(" "+loadG1);
new CountDownTimer(18000, 1000) {
@Override
public void onTick (long millisUntilFinished) {
}
public void onFinish() {
TextView result = (TextView) findViewById(R.id.outcome);
result.setText("Score: "+ score[0]);
TextView prompt = (TextView) findViewById(R.id.prompt);
prompt.setVisibility(View.GONE);
}
}.start();
runOnUiThread(new Runnable() {
@Override
public void run() {
Runnable myRunnable = new Runnable() {
@Override
public void run() {
while (true) {
SystemClock.sleep(4000);
number.setVisibility(View.GONE);
final TextView prompt = (TextView) findViewById(R.id.prompt);
prompt.setText(" Enter the number");
final EditText input = (EditText) findViewById(R.id.enterAnswer);
input.setVisibility(View.VISIBLE);
input.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
Editable answer = input.getText();
int finalAnswer = Integer.parseInt(String.valueOf(answer));
int finalLoadG1 = Integer.parseInt(String.valueOf(loadG1));
input.setVisibility(View.GONE);
prompt.setVisibility(View.GONE);
if (finalAnswer == finalLoadG1) {
score[0]++;
}
return true;
default:
}
}
return false;
}
});
}
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();
}
});
}
});
}
}
我觉得我已经很接近解决这个问题了,非常感谢提供的所有帮助。
编辑:我尝试了一个没有循环的替代解决方案,代码在这里:
runOnUiThread(new Runnable() {
@Override
public void run() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(4000);
number.setVisibility(View.GONE);
final TextView prompt = (TextView) findViewById(R.id.prompt);
prompt.setText(" Enter the number");
final EditText input = (EditText) findViewById(R.id.enterAnswer);
input.setVisibility(View.VISIBLE);
input.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
Editable answer = input.getText();
int finalAnswer = Integer.parseInt(String.valueOf(answer));
int finalLoadG1 = Integer.parseInt(String.valueOf(loadG1));
input.setVisibility(View.GONE);
prompt.setVisibility(View.GONE);
if (finalAnswer == finalLoadG1) {
score[0]++;
}
return true;
default:
}
}
return false;
}
});
}
});
}
}, 0, 4000);
}
});
现在随机数生成并显示 4 秒,但当用户输入可用时,应用程序冻结。显然跳过了 238 帧(我相信每四秒钟就会显示一次),并且“主线程”正在做太多的工作。注意:即使没有 RUNONUITHREAD 封装我的代码,也会出现相同的结果。两种方法我都试过了,没有发现差异。
真诚地感谢任何可以帮助我解决此问题的人。
【问题讨论】:
-
while (true) {- 不好的做法) -
@MarkusKauppinen 那么如何在我的代码中更正此问题而不会导致应用崩溃?
-
代码随编辑更新。