首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程问题-只有创建视图层次结构的原始线程才能触摸其视图。

线程问题-只有创建视图层次结构的原始线程才能触摸其视图。
EN

Stack Overflow用户
提问于 2016-10-13 18:50:29
回答 1查看 400关注 0票数 0

我花了一段时间试图找出为什么我的仿真器一直结冰,原来是因为我引入了一个while循环。单击按钮后,输出一个随机数(LoadG1),4秒后消失。然后用户输入一个数字,如果它等于loadg1,他们得到一个点,程序是循环的,让另一个loadg1可用4秒,然后消失等等.

显然,除非它是自己的线程,否则我不能拥有这个循环。我为它做了一条线,然后试了一下。按下按钮后,整个应用程序都没有冻结,但是当loadg1启动4秒时,应用程序就关闭了。这就好像第一行循环成功了,然后在4秒结束后失败了。我收到以下错误:

android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图。

在查询完这个之后,我发现我需要把它放在一个runOnUiThread中,所以我做到了,只是遇到了同样的问题。这是我的密码:

代码语言:javascript
复制
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();

                }
            });

            }
        });
    }

}

我觉得我是如此接近解决这个问题,会非常感谢所有的帮助。

编辑:我尝试过一种没有循环的替代解决方案,这里的代码如下:

代码语言:javascript
复制
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封装我的代码,也会出现相同的结果。我尝试了两种方法,但没有发现不同之处。

真诚地感谢任何人能帮我解决这个问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-10-13 19:05:23

不要在UI操作中使用while(true),这就是为什么您一直停滞不前,更多的是根本不使用Even (True)--这是糟糕的实践。

如果您需要运行一些重复的操作--使用计时器--您可以启动/停止定时器,也可以启动另一个定时器,甚至一次启动几个)

不要在线程中执行UI操作,而只在UI线程上执行它们。

对于硬操作,使用异步任务-当所有硬操作完成后,更新UI。(在异步任务中,您可以通过发布进度来更新UI ),在堆叠溢出的大量异步任务示例上。

OnKeyListener -在非UI线程上运行,但请阅读上面的内容,并避免使用while(true)

最新答复:

好的,如果您想像这样运行,并且不想有延迟,那么请执行以下操作:

创建计时器-不需要在runOnUIThread中启动它。所有具有计算的代码都会移动ti异步任务,您将在计时器中启动该任务,在运行停止计时器之前在异步任务中执行异步任务以避免再次运行,在异步任务中进行所有计算,在结束异步任务时更新ui和(或者您可以更新发布进度),在async任务结束时您可以再次启动计时器。如果下一次运行前需要延迟,请使用HandlerpostDelayed

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40028759

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档