CountdownTimer崩溃的应用程序。试图在tick上更新UI线程

问题描述 投票:1回答:5

我希望countdowntimer在一个单独的线程上,并让它在每个tick上更新UI。每次我点击启动应用程序只是关闭,我得到'应用程序已停止'错误消息。

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();
}
}

我已经假设创建一个CountDownTimer给它自己的线程?

java android multithreading countdown
5个回答
1
投票

你可以使用Handler。我为你写了一个样本

此代码每隔一秒增加一个计数器,并在textView上显示和更新计数器值。

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();
    }
}

0
投票

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

如果你不需要其他线程(如果这只是关于你没有的计数器)你可以检查Handler类和postAtTime(Runnable,long),postDelayed(Runnable,long)方法。或者您可以创建Handler类的子类并使用sendMessageDelayed(android.os.Message,long)和重写的handleMessage()的组合。


0
投票

这是你的问题:

countdownText.setText(timeUntilFinished);

您已将整数传递给setText(int)方法,该方法实际上需要显示字符串资源ID而不是整数。你应该使用方法setText(String)

试试这个:

countdownText.setText(String.valueOf(timeUntilFinished));

0
投票

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

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);
        }
    });
}
}

0
投票

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

也,

TextView countdownText = (TextView) findViewById(R.id.countdown);

在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();
© www.soinside.com 2019 - 2024. All rights reserved.