Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 倒计时程序崩溃。正在尝试更新勾号上的UI线程_Java_Android_Multithreading_Countdown - Fatal编程技术网

Java 倒计时程序崩溃。正在尝试更新勾号上的UI线程

Java 倒计时程序崩溃。正在尝试更新勾号上的UI线程,java,android,multithreading,countdown,Java,Android,Multithreading,Countdown,我希望倒计时是在一个单独的线程,并为它更新用户界面上的每一个滴答声。每次单击“启动”时,应用程序都会关闭,并显示“应用程序已停止”错误消息 public class Activity_MultiplayerGame extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setCon

我希望倒计时是在一个单独的线程,并为它更新用户界面上的每一个滴答声。每次单击“启动”时,应用程序都会关闭,并显示“应用程序已停止”错误消息

public class Activity_MultiplayerGame extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity__multiplayer_game);
}

public void btnStart_onClick(View view){
    CountDownTimer timer = new CountDownTimer(15000, 1000){

        @Override
        public void onTick(final long millisUntilFinished) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    TextView countdownText = (TextView) findViewById(R.id.countdown);
                    Integer timeUntilFinished = (int) millisUntilFinished/1000;
                    countdownText.setText(timeUntilFinished);
                }
            });
        }

        @Override
        public void onFinish() {
            TextView countdownText = (TextView) findViewById(R.id.countdown);
            countdownText.setText("Finished");
        }
    };

    timer.start();
}
}

我假设创建一个倒计时给它自己的线程?

除了android上的主(UI)线程之外,你不能从其他线程更新UI。有很多方法可以解决这个问题,但是如果你真的需要另一个线程,我想你应该从它开始。检查doInBackround和onProgressUpdate方法

如果您不需要其他线程(如果这只是关于您不需要的计数器),您可以检查class和posttime(Runnable,long)、postdayed(Runnable,long)方法。或者,您可以创建Handler类的子类,并使用sendMessageDelayed(android.os.Message,long)和Overrided handleMessage()的组合。以下是您的问题:

countdownText.setText(timeUntilFinished);
您已经将integer传递给
setText(int)
方法,该方法实际上采用字符串资源id,而不是要显示的整数。您应该使用方法
setText(String)

试试这个:

countdownText.setText(String.valueOf(timeUntilFinished));
您可以使用。我给你写了一个样本

此代码每隔一秒钟增加一个计数器文本视图上显示和更新计数器值

public class MainActivity extends Activity {


    private Handler handler = new Handler();
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        startTimer();
    }


    int i = 0;
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            i++;
            textView.setText("counter:" + i);
            startTimer();
        }
    };

    public void startTimer() {
        handler.postDelayed(runnable, 1000);
    }

    public void cancelTimer() {
        handler.removeCallbacks(runnable);
    }

    @Override
    protected void onStop() {
        super.onStop();
        cancelTimer();
    }
}

此代码还可以减少计数器(或增加任何您想要的),并在文本视图中显示您也可以通过单击相同的按钮停止或重置计数器

public class MainActivity extends AppCompatActivity {


TextView textView;
Button count;

boolean timelapseRunning = true;
int NUM_OF_COUNT=15;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView=(TextView)findViewById(R.id.textview);
    count=(Button)findViewById(R.id.count);
    runTimer();

}
public void onclick(View view){
    if (!timelapseRunning) {
       timelapseRunning=true;
    } else {
        timelapseRunning = false;

    }
    if(NUM_OF_COUNT==0){
        NUM_OF_COUNT=15;
    }
}
private void runTimer() {
           final Handler handler = new Handler();
    handler.post(new Runnable() {
        @Override
        public void run() {
            textView.setText(""+NUM_OF_COUNT);
            if (!timelapseRunning && NUM_OF_COUNT>0) {
                NUM_OF_COUNT--;
            }
            handler.postDelayed(this, 1000);
        }
    });
}
}

CountDownTimer
在创建它的同一线程上发出回调。因此,如果在UI线程上调用了
CountDownTimer
构造函数,则绝对不需要
onTick
中的
runOnUiThread

而且

在onTick方法中被调用是一种糟糕的设计,因为
findViewById
方法消耗了大量的处理能力

最后,Nabin Bhandari指出的实际问题是传递给
setText
方法的整数值。你需要把它包装成细绳。 这个代码就足够了

final TextView countdownText = (TextView) findViewById(R.id.countdown);
    CountDownTimer timer = new CountDownTimer(15000, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            countdownText.setText(String.valueOf(millisUntilFinished/1000));
        }

        @Override
        public void onFinish() {
            countdownText.setText("Finished");
        }
    };
    timer.start();

提供堆栈跟踪。错误是什么?但是处理程序没有绑定到UI线程吗?所以当它调用setText时,这不会导致UI的延迟或冻结吗?我希望用户能够输入到一个文本框和互动按钮,而倒计时生效。这是工作!我在手机上测试过。在ExoPlayer使用此代码更新progressbar之前,我也看到过videoplayer@Jamanfi它被绑定到UI线程,并且还可以。您不能从andriod上的main/UI线程以外的其他线程操作UI。您不需要担心冻结UI,因为它阻塞线程的唯一时间是在Runnable中执行代码的过程中,而且它不是长时间运行的代码。当处理程序等待1000毫秒等待另一个倒计时步骤时,没有任何内容被阻止或冻结。请标记为正确答案,如果它对您有帮助,请投票
final TextView countdownText = (TextView) findViewById(R.id.countdown);
    CountDownTimer timer = new CountDownTimer(15000, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            countdownText.setText(String.valueOf(millisUntilFinished/1000));
        }

        @Override
        public void onFinish() {
            countdownText.setText("Finished");
        }
    };
    timer.start();