我花了一段时间试图找出为什么我的仿真器一直结冰,原来是因为我引入了一个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封装我的代码,也会出现相同的结果。我尝试了两种方法,但没有发现不同之处。
真诚地感谢任何人能帮我解决这个问题。
发布于 2016-10-13 19:05:23
不要在UI操作中使用while(true),这就是为什么您一直停滞不前,更多的是根本不使用Even (True)--这是糟糕的实践。
如果您需要运行一些重复的操作--使用计时器--您可以启动/停止定时器,也可以启动另一个定时器,甚至一次启动几个)
不要在线程中执行UI操作,而只在UI线程上执行它们。
对于硬操作,使用异步任务-当所有硬操作完成后,更新UI。(在异步任务中,您可以通过发布进度来更新UI ),在堆叠溢出的大量异步任务示例上。
OnKeyListener -在非UI线程上运行,但请阅读上面的内容,并避免使用while(true)。
最新答复:
好的,如果您想像这样运行,并且不想有延迟,那么请执行以下操作:
创建计时器-不需要在runOnUIThread中启动它。所有具有计算的代码都会移动ti异步任务,您将在计时器中启动该任务,在运行停止计时器之前在异步任务中执行异步任务以避免再次运行,在异步任务中进行所有计算,在结束异步任务时更新ui和(或者您可以更新发布进度),在async任务结束时您可以再次启动计时器。如果下一次运行前需要延迟,请使用Handler和postDelayed
https://stackoverflow.com/questions/40028759
复制相似问题