Bagaimana cara mengatur timer di android?


325

Dapatkah seseorang memberikan contoh sederhana memperbarui bidang teks setiap detik?

Saya ingin membuat bola terbang dan perlu menghitung / memperbarui koordinat bola setiap detik, itu sebabnya saya perlu semacam timer.

Saya tidak mendapatkan apa-apa dari sini .



Jawaban:


463

ok karena ini belum dihapus belum ada 3 cara sederhana untuk menangani ini. Di bawah ini adalah contoh yang menunjukkan semua 3 dan di bagian bawah adalah contoh yang menunjukkan hanya metode yang saya percaya lebih disukai. Ingat juga untuk membersihkan tugas Anda di onPause, simpan kondisi jika perlu.


import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class main extends Activity {
    TextView text, text2, text3;
    long starttime = 0;
    //this  posts a message to the main thread from our timertask
    //and updates the textfield
   final Handler h = new Handler(new Callback() {

        @Override
        public boolean handleMessage(Message msg) {
           long millis = System.currentTimeMillis() - starttime;
           int seconds = (int) (millis / 1000);
           int minutes = seconds / 60;
           seconds     = seconds % 60;

           text.setText(String.format("%d:%02d", minutes, seconds));
            return false;
        }
    });
   //runs without timer be reposting self
   Handler h2 = new Handler();
   Runnable run = new Runnable() {

        @Override
        public void run() {
           long millis = System.currentTimeMillis() - starttime;
           int seconds = (int) (millis / 1000);
           int minutes = seconds / 60;
           seconds     = seconds % 60;

           text3.setText(String.format("%d:%02d", minutes, seconds));

           h2.postDelayed(this, 500);
        }
    };

   //tells handler to send a message
   class firstTask extends TimerTask {

        @Override
        public void run() {
            h.sendEmptyMessage(0);
        }
   };

   //tells activity to run on ui thread
   class secondTask extends TimerTask {

        @Override
        public void run() {
            main.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                   long millis = System.currentTimeMillis() - starttime;
                   int seconds = (int) (millis / 1000);
                   int minutes = seconds / 60;
                   seconds     = seconds % 60;

                   text2.setText(String.format("%d:%02d", minutes, seconds));
                }
            });
        }
   };


   Timer timer = new Timer();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        text = (TextView)findViewById(R.id.text);
        text2 = (TextView)findViewById(R.id.text2);
        text3 = (TextView)findViewById(R.id.text3);

        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
        b.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Button b = (Button)v;
                if(b.getText().equals("stop")){
                    timer.cancel();
                    timer.purge();
                    h2.removeCallbacks(run);
                    b.setText("start");
                }else{
                    starttime = System.currentTimeMillis();
                    timer = new Timer();
                    timer.schedule(new firstTask(), 0,500);
                    timer.schedule(new secondTask(),  0,500);
                    h2.postDelayed(run, 0);
                    b.setText("stop");
                }
            }
        });
    }

    @Override
    public void onPause() {
        super.onPause();
        timer.cancel();
        timer.purge();
        h2.removeCallbacks(run);
        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
    }
}


hal utama yang perlu diingat adalah bahwa UI hanya dapat dimodifikasi dari utas ui utama jadi gunakan handler atau activity.runOnUIThread (Runnable r);

Inilah yang saya anggap sebagai metode yang disukai.


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class TestActivity extends Activity {

    TextView timerTextView;
    long startTime = 0;

    //runs without a timer by reposting this handler at the end of the runnable
    Handler timerHandler = new Handler();
    Runnable timerRunnable = new Runnable() {

        @Override
        public void run() {
            long millis = System.currentTimeMillis() - startTime;
            int seconds = (int) (millis / 1000);
            int minutes = seconds / 60;
            seconds = seconds % 60;

            timerTextView.setText(String.format("%d:%02d", minutes, seconds));

            timerHandler.postDelayed(this, 500);
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_activity);

        timerTextView = (TextView) findViewById(R.id.timerTextView);

        Button b = (Button) findViewById(R.id.button);
        b.setText("start");
        b.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Button b = (Button) v;
                if (b.getText().equals("stop")) {
                    timerHandler.removeCallbacks(timerRunnable);
                    b.setText("start");
                } else {
                    startTime = System.currentTimeMillis();
                    timerHandler.postDelayed(timerRunnable, 0);
                    b.setText("stop");
                }
            }
        });
    }

  @Override
    public void onPause() {
        super.onPause();
        timerHandler.removeCallbacks(timerRunnable);
        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
    }

}



1
@ Dave.B, terima kasih atas contohnya. Apakah ada keuntungan / kerugian menggunakan satu metode vs metode lain yang telah Anda uraikan?
Gautam

2
@ Gautam Saya percaya semua metode di atas melakukan hampir sama. Saya pribadi lebih suka metode handler yang dijelaskan di atas dengan menjalankan Runnable dan Handler h2 karena ini adalah yang ditentukan oleh situs pengembang android dan menurut saya juga yang paling elegan.
Dave.B

6
Alangkah baiknya jika metode pilihan Anda dipisahkan dari sisa kode. Seperti Anda dapat memiliki satu contoh yang menunjukkan cara pilihan Anda dan yang lain menunjukkan alternatif. Memiliki ketiga metode bersama membuat lebih sulit untuk memahami apa yang terjadi (terutama untuk pemula yang android seperti saya). Mungkin terlalu banyak bertanya :)
Jesse Aldridge

4
@JesseAldridge Ide bagus. Saya melanjutkan dan menambahkan kode hanya dengan metode yang disukai.
Dave.B

1
@ Bene Jujur saya hanya tidak memikirkannya tapi ya itu akan bekerja dengan baik.
Dave.B

84

Itu sederhana! Anda membuat timer baru.

Timer timer = new Timer();

Kemudian Anda memperpanjang tugas penghitung waktu

class UpdateBallTask extends TimerTask {
   Ball myBall;

   public void run() {
       //calculate the new position of myBall
   }
}

Dan kemudian menambahkan tugas baru ke Timer dengan beberapa interval pembaruan

final int FPS = 40;
TimerTask updateBall = new UpdateBallTask();
timer.scheduleAtFixedRate(updateBall, 0, 1000/FPS);

Penafian: Ini bukan solusi yang ideal. Ini adalah solusi menggunakan kelas Timer (seperti yang diminta oleh OP). Di Android SDK, disarankan untuk menggunakan kelas Handler (ada contoh dalam jawaban yang diterima).


1
jika Anda membaca posting di atas Anda akan melihat mengapa ini bukan solusi yang ideal
Dave.B

2
Tentu saja. OP ingin melakukannya dengan TimerTask, yang saya tidak akan merekomendasikan untuk digunakan dalam game.
fiksi

3
Hah? OP tidak merinci bagaimana mereka ingin itu dilakukan. Mereka menautkan ke artikel yang menggunakan TimerTask, tetapi mereka tidak meminta itu dilakukan dengan cara itu.
ToolmakerSteve

1
Membantu banyak, Terima kasih @fiksi
Naveed Ahmad

1
jawaban yang bagus mudah diikuti.
JMASTER B

64

Jika Anda juga perlu menjalankan kode Anda pada utas UI (dan bukan pada utas timer), lihat di blog: http://steve.odyfamily.com/?p=12

public class myActivity extends Activity {
private Timer myTimer;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.main);

    myTimer = new Timer();
    myTimer.schedule(new TimerTask() {          
        @Override
        public void run() {
            TimerMethod();
        }

    }, 0, 1000);
}

private void TimerMethod()
{
    //This method is called directly by the timer
    //and runs in the same thread as the timer.

    //We call the method that will work with the UI
    //through the runOnUiThread method.
    this.runOnUiThread(Timer_Tick);
}


private Runnable Timer_Tick = new Runnable() {
    public void run() {

    //This method runs in the same thread as the UI.               

    //Do something to the UI thread here

    }
};
}

Demi kelengkapan, Anda mungkin dapat menyebutkan apa yang harus dilakukan untuk menghentikan timer, dan mungkin memulai kembali. (Saya menemukan info yang diperlukan di sini: stackoverflow.com/questions/11550561/… )
RenniePet

3
Apakah ada alasan Anda tidak dapat memanggil runOnUIThread langsung dari metode jalankan TimerTask? Tampaknya berfungsi dengan baik dan menghilangkan tingkat sarang lainnya.
RichieHH

Tentu, itu hanya metode didaktik untuk memahami semua langkah. Saya menyarankan standar ini untuk memiliki kode yang dapat dibaca.
Meir Gerenstadt

41

Jika seseorang hanya ingin menjadwalkan hitung mundur hingga waktu di masa mendatang dengan pemberitahuan reguler pada interval di sepanjang jalan, Anda dapat menggunakan kelas CountDownTimer yang tersedia sejak API level 1.

new CountDownTimer(30000, 1000) {
    public void onTick(long millisUntilFinished) {
        editText.setText("Seconds remaining: " + millisUntilFinished / 1000);
    }

    public void onFinish() {
        editText.setText("Done");
    }
}.start();

2
CountDownTimer hanya masuk akal jika Anda tahu bahwa Anda ingin itu hilang setelah beberapa eksekusi. Ini bukan pendekatan yang khas, juga tidak terlalu fleksibel. Yang lebih umum adalah timer yang berulang selamanya (yang Anda batalkan ketika tidak lagi diperlukan), atau pawang yang berjalan sekali, dan kemudian mulai sendiri lagi jika akan diperlukan lagi. Lihat jawaban lain.
ToolmakerSteve

1
Anda sepenuhnya benar. Dari nama kelas, ia menyediakan penghitung waktu mundur satu kali hingga selesai dan tentu saja menggunakan Handler dalam implementasinya.
Ahmed Hegazy

Bagaimana cara menunjukkan milidetik juga? Dalam format SS:MiMi? Terima kasih
Ruchir Baronia

26

Ini adalah beberapa kode sederhana untuk penghitung waktu:

Timer timer = new Timer();
TimerTask t = new TimerTask() {       
    @Override
    public void run() {

        System.out.println("1");
    }
};
timer.scheduleAtFixedRate(t,1000,1000);

12

Saya pikir Anda bisa melakukannya dengan cara Rx seperti:

 timerSubscribe = Observable.interval(1, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<Long>() {
                @Override
                public void call(Long aLong) {
                      //TODO do your stuff
                }
            });

Dan batalkan ini seperti:

timerSubscribe.unsubscribe();

Timer Rx http://reactivex.io/documentation/operators/timer.html


10

Karena pertanyaan ini masih menarik banyak pengguna dari pencarian google (tentang Android timer) saya ingin memasukkan dua koin saya.

Pertama-tama, kelas Timer akan ditinggalkan dalam Java 9 (baca jawaban yang diterima) .

Cara resmi yang disarankan adalah dengan menggunakan ScheduledThreadPoolExecutor yang lebih efektif dan kaya fitur yang juga dapat menjadwalkan perintah untuk dijalankan setelah penundaan yang diberikan, atau untuk mengeksekusi secara berkala. Plus, ini memberikan fleksibilitas dan kemampuan tambahan dari ThreadPoolExecutor.

Berikut adalah contoh penggunaan fungsi polos.

  1. Buat layanan pelaksana:

    final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);
  2. Jadwalkan saja jadwal Anda:

    final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit);
  3. Anda sekarang dapat menggunakan futureuntuk membatalkan tugas atau memeriksa apakah itu dilakukan misalnya:

    future.isDone();

Semoga Anda menemukan ini berguna untuk membuat tugas di Android.

Contoh lengkap:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Future<?> sampleFutureTimer = scheduler.schedule(new Runnable(), 120, TimeUnit.SECONDS);
if (sampleFutureTimer.isDone()){
    // Do something which will save world.
}

8

Saya terkejut bahwa tidak ada jawaban yang akan menyebutkan solusi dengan RxJava2 . Ini sangat sederhana dan menyediakan cara mudah untuk mengatur timer di Android.

Pertama, Anda perlu mengatur ketergantungan Gradle, jika Anda belum melakukannya:

implementation "io.reactivex.rxjava2:rxjava:2.x.y"

(ganti xdan ydengan nomor versi saat ini )

Karena kita baru saja memiliki TUGAS TAK BERKAS , sederhana , kita dapat menggunakan Completableobjek:

Completable.timer(2, TimeUnit.SECONDS, Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(() -> {
            // Timer finished, do something...
        });

Untuk REPEATING TASK , Anda dapat menggunakan Observablecara yang serupa:

Observable.interval(2, TimeUnit.SECONDS, Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(tick -> {
            // called every 2 seconds, do something...
        }, throwable -> {
            // handle error
        });

Schedulers.computation()memastikan bahwa timer kami berjalan di utas latar dan .observeOn(AndroidSchedulers.mainThread())berarti kode yang kami jalankan setelah timer selesai akan dilakukan pada utas utama.

Untuk menghindari kebocoran memori yang tidak diinginkan, Anda harus memastikan untuk berhenti berlangganan saat Aktivitas / Fragmen dihancurkan.


4
Ini adalah pendekatan terbersih!
Constantin

bagaimana cara membatalkan ini? yaitu ketika pengguna menekan tombol [STOP] pada UI dan Completable dibatalkan sebelum dieksekusi.
Seseorang di suatu tempat

@SomeoneSomewhere Cukup simpan Subscriptionkembali dengan .subscribe()metode dalam variabel dan kemudian panggil subscription.unsubscribe()ketika Anda ingin menghentikan timer.
Micer

2

Dia adalah solusi yang lebih sederhana, berfungsi dengan baik di aplikasi saya.

  public class MyActivity extends Acitivity {

    TextView myTextView;
    boolean someCondition=true;

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

            myTextView = (TextView) findViewById(R.id.refreshing_field);

            //starting our task which update textview every 1000 ms
            new RefreshTask().execute();



        }

    //class which updates our textview every second

    class RefreshTask extends AsyncTask {

            @Override
            protected void onProgressUpdate(Object... values) {
                super.onProgressUpdate(values);
                String text = String.valueOf(System.currentTimeMillis());
                myTextView.setText(text);

            }

            @Override
            protected Object doInBackground(Object... params) {
                while(someCondition) {
                    try {
                        //sleep for 1s in background...
                        Thread.sleep(1000);
                        //and update textview in ui thread
                        publishProgress();
                    } catch (InterruptedException e) {
                        e.printStackTrace(); 

                };
                return null;
            }
        }
    }

2

Anda ingin pembaruan UI Anda terjadi di utas UI yang sudah ada.

Cara terbaik adalah menggunakan Handler yang menggunakan postDelayed untuk menjalankan Runnable setelah penundaan (masing-masing menjalankan jadwal berikutnya); hapus callback dengan removeCallbacks.

Anda sudah mencari di tempat yang tepat, jadi lihat lagi, mungkin jelaskan mengapa contoh kode itu tidak seperti yang Anda inginkan. (Lihat juga artikel identik di Memperbarui UI dari Timer ).


Sayangnya, tautan Anda sudah mati. Saya tidak dapat dengan cepat menemukan artikel yang benar kembali.
Lekensteyn


1

Berikut ini cara yang andal dan sederhana ...

Masukkan kode berikut ke dalam Aktivitas Anda, dan metode centang () akan dipanggil setiap detik di utas UI saat aktivitas Anda dalam keadaan "dilanjutkan". Tentu saja, Anda dapat mengubah metode centang () untuk melakukan apa yang Anda inginkan, atau lebih sering dipanggil.

@Override
public void onPause() {
    _handler = null;
    super.onPause();
}

private Handler _handler;

@Override
public void onResume() {
    super.onResume();
    _handler = new Handler();
    Runnable r = new Runnable() {
        public void run() {
            if (_handler == _h0) {
                tick();
                _handler.postDelayed(this, 1000);
            }
        }

        private final Handler _h0 = _handler;
    };
    r.run();
}

private void tick() {
    System.out.println("Tick " + System.currentTimeMillis());
}

Bagi mereka yang tertarik, kode "_h0 = _handler" diperlukan untuk menghindari dua timer berjalan secara bersamaan jika aktivitas Anda dijeda dan dilanjutkan dalam periode centang.


2
Mengapa _h0pendekatan canggung ini , bukannya removeCallbacksmasuk onPause, seperti orang lain?
ToolmakerSteve

1

Anda juga dapat menggunakan animator untuk itu:

int secondsToRun = 999;

ValueAnimator timer = ValueAnimator.ofInt(secondsToRun);
timer.setDuration(secondsToRun * 1000).setInterpolator(new LinearInterpolator());
timer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
    {
        @Override
        public void onAnimationUpdate(ValueAnimator animation)
        {
            int elapsedSeconds = (int) animation.getAnimatedValue();
            int minutes = elapsedSeconds / 60;
            int seconds = elapsedSeconds % 60;

            textView.setText(String.format("%d:%02d", minutes, seconds));
        }
    });
timer.start();

0

Anda perlu membuat utas untuk menangani loop pembaruan dan menggunakannya untuk memperbarui textarea. Bagian yang sulit adalah bahwa hanya utas utama yang benar-benar dapat memodifikasi ui sehingga utas loop pembaruan perlu memberi sinyal utas utama untuk melakukan pembaruan. Ini dilakukan menggunakan Handler.

Lihat tautan ini: http://developer.android.com/guide/topics/ui/dialogs.html# Klik pada bagian berjudul "Contoh ProgressDialog dengan utas kedua". Ini adalah contoh dari apa yang perlu Anda lakukan, kecuali dengan dialog kemajuan alih-alih bidang teks.


Jangan lakukan ini. Ada kelas pengatur waktu sederhana yang melakukan ini semua untuk Anda. Dan pertanyaan ini sama sekali tidak ada hubungannya dengan progressdialogs, atau dialog sama sekali.
Falmarri

Apakah Anda melihat bagian tautan yang saya poskan atau hanya melihat dialog kata dan menganggapnya? Kode di sana 100% relevan. Juga FYI, jika Anda menggunakan timer, Anda masih membuat utas untuk menangani loop pembaruan. Anda masih harus menggunakan Handler seperti yang dijelaskan dalam tautan yang saya posting.
Nick

Sayangnya, halaman tertaut tidak lagi berisi bagian dengan judul yang disebutkan. Saat menautkan ke kode, orang harus selalu memasukkan potongan kunci langsung dalam jawaban Anda.
ToolmakerSteve

0
void method(boolean u,int max)
{
    uu=u;
    maxi=max;
    if (uu==true)
    { 
        CountDownTimer uy = new CountDownTimer(maxi, 1000) 
  {
            public void onFinish()
            {
                text.setText("Finish"); 
            }

            @Override
            public void onTick(long l) {
                String currentTimeString=DateFormat.getTimeInstance().format(new Date());
                text.setText(currentTimeString);
            }
        }.start();
    }

    else{text.setText("Stop ");
}

2
Mungkin beberapa lekukan kode dan penjelasan kode akan bermanfaat.
Raul Rene

0

Jika ada yang tertarik, saya mulai bermain-main dengan membuat objek standar untuk dijalankan pada utas aktivitas UI. Tampaknya bekerja ok. Komentar diterima. Saya ingin ini tersedia di perancang tata letak sebagai komponen untuk menarik ke Kegiatan. Tidak percaya sesuatu seperti itu belum ada.

package com.example.util.timer;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;

public class ActivityTimer {

    private Activity m_Activity;
    private boolean m_Enabled;
    private Timer m_Timer;
    private long m_Delay;
    private long m_Period;
    private ActivityTimerListener m_Listener;
    private ActivityTimer _self;
    private boolean m_FireOnce;

    public ActivityTimer() {
        m_Delay = 0;
        m_Period = 100;
        m_Listener = null;
        m_FireOnce = false;
        _self = this;
    }

    public boolean isEnabled() {
        return m_Enabled;
    }

    public void setEnabled(boolean enabled) {
        if (m_Enabled == enabled)
            return;

        // Disable any existing timer before we enable a new one
        Disable();

        if (enabled) {
            Enable();
        }
    }

    private void Enable() {
        if (m_Enabled)
            return;

        m_Enabled = true;

        m_Timer = new Timer();
        if (m_FireOnce) {
            m_Timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    OnTick();
                }
            }, m_Delay);
        } else {
            m_Timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    OnTick();
                }
            }, m_Delay, m_Period);
        }
    }

    private void Disable() {
        if (!m_Enabled)
            return;

        m_Enabled = false;

        if (m_Timer == null)
            return;

        m_Timer.cancel();
        m_Timer.purge();
        m_Timer = null;
    }

    private void OnTick() {
        if (m_Activity != null && m_Listener != null) {
            m_Activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    m_Listener.OnTimerTick(m_Activity, _self);
                }
            });
        }
        if (m_FireOnce)
            Disable();
    }

    public long getDelay() {
        return m_Delay;
    }

    public void setDelay(long delay) {
        m_Delay = delay;
    }

    public long getPeriod() {
        return m_Period;
    }

    public void setPeriod(long period) {
        if (m_Period == period)
            return;
        m_Period = period;
    }

    public Activity getActivity() {
        return m_Activity;
    }

    public void setActivity(Activity activity) {
        if (m_Activity == activity)
            return;
        m_Activity = activity;
    }

    public ActivityTimerListener getActionListener() {
        return m_Listener;
    }

    public void setActionListener(ActivityTimerListener listener) {
        m_Listener = listener;
    }

    public void start() {
        if (m_Enabled)
            return;
        Enable();
    }

    public boolean isFireOnlyOnce() {
        return m_FireOnce;
    }

    public void setFireOnlyOnce(boolean fireOnce) {
        m_FireOnce = fireOnce;
    }
}

Dalam aktivitas tersebut, saya memiliki ini di mulai:

@Override
protected void onStart() {
    super.onStart();

    m_Timer = new ActivityTimer();
    m_Timer.setFireOnlyOnce(true);
    m_Timer.setActivity(this);
    m_Timer.setActionListener(this);
    m_Timer.setDelay(3000);
    m_Timer.start();
}

1
Bung apa yang salah dengan ActivityTimerListener? Bundel ADT saya mengatakan bahwa tidak ada kelas seperti itu.
Sorokin Andrey

0
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

 CheckBox optSingleShot;
 Button btnStart, btnCancel;
 TextView textCounter;

 Timer timer;
 MyTimerTask myTimerTask;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  optSingleShot = (CheckBox)findViewById(R.id.singleshot);
  btnStart = (Button)findViewById(R.id.start);
  btnCancel = (Button)findViewById(R.id.cancel);
  textCounter = (TextView)findViewById(R.id.counter);

  btnStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {

    if(timer != null){
     timer.cancel();
    }

    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();

    if(optSingleShot.isChecked()){
     //singleshot delay 1000 ms
     timer.schedule(myTimerTask, 1000);
    }else{
     //delay 1000ms, repeat in 5000ms
     timer.schedule(myTimerTask, 1000, 5000);
    }
   }});

  btnCancel.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    if (timer!=null){
     timer.cancel();
     timer = null;
    }
   }
  });

 }

 class MyTimerTask extends TimerTask {

  @Override
  public void run() {
   Calendar calendar = Calendar.getInstance();
   SimpleDateFormat simpleDateFormat = 
     new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
   final String strDate = simpleDateFormat.format(calendar.getTime());

   runOnUiThread(new Runnable(){

    @Override
    public void run() {
     textCounter.setText(strDate);
    }});
  }

 }

}

.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:autoLink="web"
    android:text="http://android-er.blogspot.com/"
    android:textStyle="bold" />
<CheckBox 
    android:id="@+id/singleshot"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Single Shot"/>


Saya melihat bahwa Anda telah menambahkan ini beberapa tahun setelah pertanyaan & jawaban asli. Harap tambahkan penjelasan tentang bagaimana jawaban ini dibandingkan dengan jawaban lain yang sudah ada. Mengapa Anda menambahkan yang lain - manfaat apa / kapan berguna / kekurangan apa yang Anda lihat di jawaban lain?
ToolmakerSteve

Saya hanya membagikan kode yang melakukan pekerjaan yang sama dengan pendekatan yang berbeda. Tetapi setiap kali Anda ingin memperbarui data tampilan apa pun. Anda harus menggunakan handler untuk itu. karena banyak waktu saya perhatikan bahwa menggunakan timertask untuk memperbarui tampilan tidak berfungsi .. @ Dave.B metode lebih tepat untuk pengetahuan saya.
Zar E Ahmer

0

Jika Anda sudah punya waktu delta.

public class Timer {
    private float lastFrameChanged;
    private float frameDuration;
    private Runnable r;

    public Timer(float frameDuration, Runnable r) {
        this.frameDuration = frameDuration;
        this.lastFrameChanged = 0;
        this.r = r;
    }

    public void update(float dt) {
        lastFrameChanged += dt;

        if (lastFrameChanged > frameDuration) {
            lastFrameChanged = 0;
            r.run();
        }
    }
}

0

Saya abstrak Timer dan membuatnya menjadi kelas yang terpisah:

Timer.java

import android.os.Handler;

public class Timer {

    IAction action;
    Handler timerHandler = new Handler();
    int delayMS = 1000;

    public Timer(IAction action, int delayMS) {
        this.action = action;
        this.delayMS = delayMS;
    }

    public Timer(IAction action) {
        this(action, 1000);
    }

    public Timer() {
        this(null);
    }

    Runnable timerRunnable = new Runnable() {

        @Override
        public void run() {
            if (action != null)
                action.Task();
            timerHandler.postDelayed(this, delayMS);
        }
    };

    public void start() {
        timerHandler.postDelayed(timerRunnable, 0);
    }

    public void stop() {
        timerHandler.removeCallbacks(timerRunnable);
    }
}

Dan Ekstrak tindakan utama dari Timerkelas sebagai

IAction.java

public interface IAction {
    void Task();
}

Dan saya menggunakannya seperti ini:

MainActivity.java

public class MainActivity extends Activity implements IAction{
...
Timer timerClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
        ...
        timerClass = new Timer(this,1000);
        timerClass.start();
        ...
}
...
int i = 1;
@Override
public void Task() {
    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            timer.setText(i + "");
            i++;
        }
    });
}
...
}

Saya Berharap Ini Membantu 😊👌


0

Saya menggunakan cara ini:

String[] array={
       "man","for","think"
}; int j;

lalu di bawah onCreate

TextView t = findViewById(R.id.textView);

    new CountDownTimer(5000,1000) {

        @Override
        public void onTick(long millisUntilFinished) {}

        @Override
        public void onFinish() {
            t.setText("I "+array[j] +" You");
            j++;
            if(j== array.length-1) j=0;
            start();
        }
    }.start();

cara mudah untuk mengatasi masalah ini.


0

Bagi mereka yang tidak bisa mengandalkan Chronometer , saya membuat kelas utilitas dari salah satu saran:

public class TimerTextHelper implements Runnable {
   private final Handler handler = new Handler();
   private final TextView textView;
   private volatile long startTime;
   private volatile long elapsedTime;

   public TimerTextHelper(TextView textView) {
       this.textView = textView;
   }

   @Override
   public void run() {
       long millis = System.currentTimeMillis() - startTime;
       int seconds = (int) (millis / 1000);
       int minutes = seconds / 60;
       seconds = seconds % 60;

       textView.setText(String.format("%d:%02d", minutes, seconds));

       if (elapsedTime == -1) {
           handler.postDelayed(this, 500);
       }
   }

   public void start() {
       this.startTime = System.currentTimeMillis();
       this.elapsedTime = -1;
       handler.post(this);
   }

   public void stop() {
       this.elapsedTime = System.currentTimeMillis() - startTime;
       handler.removeCallbacks(this);
   }

   public long getElapsedTime() {
       return elapsedTime;
   }
 }

untuk digunakan..hanya lakukan:

 TimerTextHelper timerTextHelper = new TimerTextHelper(textView);
 timerTextHelper.start();

.....

 timerTextHelper.stop();
 long elapsedTime = timerTextHelper.getElapsedTime();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.