1

I'm trying to implement a Countdown Timer which shows on the UI, I thought this was a clean and elegant solution but Logcat throws

AndroidRuntime(3282): java.lang.RuntimeException: An error occured while executing doInBackground()

,

private class UpdateCountdownTask extends AsyncTask<Long, Long, Void> {
    @Override
    protected Void doInBackground(Long... millisUntilFinished) {

        new CountDownTimer(millisUntilFinished[0], 1000) {

            @Override
            public void onTick(long millisUntilFinished) {
                publishProgress(millisUntilFinished);
            }

            @Override
            public void onFinish() {
                ((TextView) findViewById(R.id.answer)).setText(answer);
            }
        };
        return null;
    }

    @Override
    protected void onProgressUpdate(Long... millisUntilFinished) {
        super.onProgressUpdate(millisUntilFinished);
        ((TextView) findViewById(R.id.timer)).setText(""
                + millisUntilFinished[0] / 1000);
    }
}

Still don't fully understand threads. Can anyone tell me what I'm doing wrong?

Thanks.

UPDATE: Very Sorry. I am an absolut incompetent. I had forgotten to call the metod start() on the counter. :P I finally went for implementing the countdown with the CountDownTimer by itself. Sill don't know if this actually runs on a separate thread or not but it works now.

    CountDownTimer myCounter = new CountDownTimer(millisUntilFinished, 1000) {

        @Override
        public void onTick(long millisUntilFinished) {
            ((TextView) findViewById(R.id.timer)).setText(""
                    + millisUntilFinished / 1000);
            System.out.println("I am ticking");
        }

        @Override
        public void onFinish() {
        }
    };

    myCounter.start();
eskalera
  • 1,072
  • 2
  • 21
  • 36
  • Only main UI thread may update UI like TextView, thus you cannot update view from another thread. You should wrapp your textView.setText("123") inside something like this mTextView.post(new Runnable(){}) either runOnUIThread() http://stackoverflow.com/q/12850143/2163045 – murt Aug 03 '16 at 11:53

3 Answers3

3

I think the problem is the onFinish() method inside CountDownTimer. Here you're modifiying the UI thread, and you cannot do this from a background thread. So you have to put ((TextView) findViewById(R.id.answer)).setText(answer); inside onPostExecute() method. I mean:

protected void onPostExecute(String result) {
super.onPostExecute(result);
((TextView) findViewById(R.id.answer)).setText(answer);
}

I hope this works.

MByD
  • 135,866
  • 28
  • 264
  • 277
icastell
  • 3,495
  • 1
  • 19
  • 27
0

You will not be able to connect the UI when doing somthing in background.In my opinion what you want is possible if you use a thread.This will make your work much more easier.A small piece of code is shown below.I hope this may help you.I am trying to set an image instead you can settext.Here i had done using a thread and a handler.Its impossible to connect the UI inside the thread.In assynctask When you are doing something in background you are compleatly inside the thread.Thats why you are getting a error here.Otherwinse you can do it in Postexecute()

Thread animator = new Thread() {
        public void run() {
            int i = 0;
            try {
                sleep(2000);
                while (i < 4) {
                    sleep(50);
                    handler.sendMessage(handler.obtainMessage(i));
                    i++;
                }
            } catch (Exception e) {

            }
        }
    };
    animator.start();
    handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0) {
                animatedimage.setImageResource(R.drawable.sub1);
            } else if (msg.what == 1) {
                animatedimage.setImageResource(R.drawable.sub2);
            } else if (msg.what == 2) {
                animatedimage.setImageResource(R.drawable.sub3);
            } else if (msg.what == 3) {
                animatedimage.setImageResource(R.drawable.sub4);
            }
        }

    };
Sreedev
  • 6,563
  • 5
  • 43
  • 66
  • I was using AsyncTask as an Android recommendation. I think is more clear. Still, even if I move the onFinish() piece of code as I told @isidoro-castell-egea I still get the error. The fact I modify a View from the onProgressUpdate() shouldn't be a problem since that's suppossed to be called from UI, isn't it? – eskalera May 02 '12 at 11:42
  • Can you make it lil more clear??This error usually occurs when one tries to update the UI from inside thread or if its an assync then from background. – Sreedev May 02 '12 at 11:50
0

Have you consider using Handler to update UI every second?

checkout http://developer.android.com/resources/articles/timed-ui-updates.html

Veer
  • 2,071
  • 19
  • 24
  • Thx @Veer, I'd seen this a couple of days ago. I decided to go for AsyncTasks following Android guidelines. Also I think is more clear. I'll go for this one if I can't figure it out. – eskalera May 02 '12 at 11:43
  • Link is broken. You should provide the relevant code. – Kalel Wade Apr 02 '15 at 20:32