Cara mengatur timer di android

Jawaban:

143

Cara Java standar untuk menggunakan timer melalui java.util.Timer dan java.util.TimerTask berfungsi dengan baik di Android, tetapi Anda harus menyadari bahwa metode ini membuat utas baru.

Anda dapat mempertimbangkan untuk menggunakan kelas Handler yang sangat nyaman (android.os.Handler) dan mengirim pesan ke handler melalui sendMessageAtTime(android.os.Message, long)atau sendMessageDelayed(android.os.Message, long). Setelah Anda menerima pesan, Anda dapat menjalankan tugas yang diinginkan. Opsi kedua adalah membuat objek Runnable dan menjadwalkannya melalui fungsi Handler postAtTime(java.lang.Runnable, long)atau postDelayed(java.lang.Runnable, long).

MannyNS
sumber
10
Ini adalah cara yang salah untuk melakukan hal-hal di android. Di android, Anda ingin menggunakan Pengelola Alarm (developer.android.com/reference/android/app/AlarmManager.html) untuk menjalankan tugas jauh di masa depan.
Kurtis Nusbaum
9
@Kurtis Nusbaum Pertanyaannya tidak mengatakan seberapa jauh di masa depan tugas itu.
Christopher Perry
67
@KurtisNusbaum Itu belum tentu benar, itu tergantung pada konteksnya. Dokumen di AlarmManager mengatakan, "Catatan: Manajer Alarm ditujukan untuk kasus-kasus di mana Anda ingin menjalankan kode aplikasi pada waktu tertentu, bahkan jika aplikasi Anda saat ini tidak berjalan. Untuk operasi pengaturan waktu normal (kutu, batas waktu, dll) lebih mudah dan jauh lebih efisien untuk menggunakan Handler. "
Christopher Perry
5
@ Sienceprodigy Ah, begitu. Cukup adil.
Kurtis Nusbaum
10
menggunakan metode Handler dalam menjadwalkan tugas hanya dapat diandalkan jika aplikasi telah memperoleh wakeLock dan karenanya Anda yakin bahwa ponsel tidak akan masuk ke kondisi tidur. Jika ponsel tidak masuk ke kondisi tidur maka sendMessageDelayed serta sendMessageAtTime tidak akan berfungsi. Karenanya dalam skenario itu AlarmManager akan menjadi pilihan yang andal.
crazyaboutliv
159

ya timer java dapat digunakan , tetapi sebagai pertanyaan meminta cara yang lebih baik (untuk ponsel). Yang dijelaskan di Sini .


Demi StackOverflow:

Karena Timer membuat utas baru, itu mungkin dianggap berat,

jika yang Anda butuhkan adalah mendapatkan panggilan kembali saat aktivitas berjalan, Handler dapat digunakan bersama dengan a

Runnable :

private final int interval = 1000; // 1 Second
private Handler handler = new Handler();
private Runnable runnable = new Runnable(){
    public void run() {
        Toast.makeText(MyActivity.this, "C'Mom no hands!", Toast.LENGTH_SHORT).show();
    }
};
...
handler.postAtTime(runnable, System.currentTimeMillis()+interval);
handler.postDelayed(runnable, interval);

atau Pesan

private final int EVENT1 = 1; 
private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {         
        case Event1:
            Toast.makeText(MyActivity.this, "Event 1", Toast.LENGTH_SHORT).show();
            break;

        default:
            Toast.makeText(MyActivity.this, "Unhandled", Toast.LENGTH_SHORT).show();
            break;
        }
    }
};

...

Message msg = handler.obtainMessage(EVENT1);
handler.sendMessageAtTime(msg, System.currentTimeMillis()+interval);
handler.sendMessageDelayed(msg, interval);

di samping catatan pendekatan ini dapat digunakan, jika Anda ingin menjalankan sepotong kode di utas UI dari utas lain.

jika Anda perlu mendapatkan panggilan kembali bahkan jika aktivitas Anda tidak berjalan, Anda dapat menggunakan AlarmManager

Samuel
sumber
1
Oh ya, saya mencari jawaban ini di Google. Ambil upvote saya untuk tautan yang bermanfaat.
ulidtko
1
memperbarui tautan, berbicara tentang google yang mengalami masalah dalam mempertahankan tautan.
Samuel
1
Artikel ini dari 2007 - tidak mengatakan itu salah, tapi saya selalu curiga dengan artikel seluler jika usianya lebih dari 3 tahun. Banyak hal berubah dengan cepat.
StackOverflowed
1
itu akan lebih seperti StackOverflow jika Anda bisa mengutip poin utama dari tautan Anda di sini dalam jawaban Anda.
n611x007
1
@naxa, dua sen saya untuk membuat respons ini lebih seperti StackOverflow.
Samuel
131

Seperti yang saya lihat, java.util.Timer adalah yang paling banyak digunakan untuk mengimplementasikan timer.

Untuk tugas yang berulang:

new Timer().scheduleAtFixedRate(task, after, interval);

Untuk satu kali tugas:

new Timer().schedule(task, after);


tugas menjadi metode yang akan dieksekusi
setelah waktu untuk eksekusi awal
( interval waktu untuk mengulangi eksekusi)

Thizzer
sumber
9
Saya hanya akan menambahkan bahwa waktu dalam milidetik
Uri
2
Android dev docs for scheduleAtFixedRate
n611x007
1
taskmungkin turunan dari kelas Anda yang mewarisi dari java.util.TimerTask dan menimpa void run().
n611x007
2
Begitu banyak upvotes. Anda bisa melakukannya. Tapi @Samuel menjelaskan cara yang lebih baik. Lihat tautan "Yang dijelaskan di Sini" untuk alasannya. Juga, tidak dapat memperbarui UI dari utas Timer! Dan lihat jawaban berbasis Handler lain ini di utas lain: (sederhana) stackoverflow.com/a/6702767/199364 , atau (
tampilkan
@quemeful karena ini bukan tentang selalu tentang kenyamanan, ini tentang kualitas kode dan efisiensi. Cara melakukannya menggunakan lebih banyak sumber daya daripada menggunakan Handler
inDepth
33

Saya harap yang satu ini bermanfaat dan mungkin membutuhkan sedikit upaya untuk mengimplementasikan, kelas Android CountDownTimer

misalnya

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

      public void onFinish() {
          mTextField.setText("done!");
      }  
}.start();
Gaurav Adurkar
sumber
1
Ini paling mudah dan tepat sasaran untuk hitung mundur sederhana seperti waktu mulai pemutaran video
Vijay Kumar Kanta
17

Mungkin Timerconcept

new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval

 public void onTick(long millisUntilFinished) {
  }
  public void onFinish() {
 }
}.start();

atau

Metode 2 ::

Program timer

Tambahkan variabel baru waktu bernama int. Atur ke 0. Tambahkan kode berikut ke fungsi onCreate di MainActivity.java.

//Declare the timer
Timer t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {

    @Override
    public void run() {
        //Called each time when 1000 milliseconds (1 second) (the period parameter)
    }

},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
1000);

Pergilah ke metode jalankan dan tambahkan kode berikut.

//We must use this function in order to change the text view text
runOnUiThread(new Runnable() {

    @Override
    public void run() {
        TextView tv = (TextView) findViewById(R.id.main_timer_text);
        tv.setText(String.valueOf(time));
        time += 1;
    }

});
vkulkarni
sumber
11

Itu situasional.

Dokumentasi Android menyarankan bahwa Anda harus menggunakan AlarmManager untuk mendaftarkan Intent yang akan diaktifkan pada waktu yang ditentukan jika aplikasi Anda mungkin tidak berjalan.

Jika tidak, Anda harus menggunakan Handler.

Catatan: Manajer Alarm ditujukan untuk kasus-kasus di mana Anda ingin menjalankan kode aplikasi pada waktu tertentu, bahkan jika aplikasi Anda saat ini tidak berjalan. Untuk operasi pengaturan waktu yang normal (tick, timeout, dll) lebih mudah dan jauh lebih efisien untuk menggunakan Handler.

Timothy Lee Russell
sumber
11

Ini dia .. Kita perlu dua kelas. Saya memposting kode yang mengubah profil audio seluler setelah setiap 5 detik (5.000 mili detik) ...

Kelas 1 kami

public class ChangeProfileActivityMain extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        Timer timer = new Timer();
        TimerTask updateProfile = new CustomTimerTask(ChangeProfileActivityMain.this);
        timer.scheduleAtFixedRate(updateProfile, 0, 5000);
    }

}

Kelas 2 kami

public class CustomTimerTask extends TimerTask {

    private AudioManager audioManager;
    private Context context;
    private Handler mHandler = new Handler();

    // Write Custom Constructor to pass Context
    public CustomTimerTask(Context con) {
        this.context = con;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

        // your code starts here.
        // I have used Thread and Handler as we can not show Toast without starting new thread when we are inside a thread.
        // As TimePicker has run() thread running., So We must show Toast through Handler.post in a new Thread. Thats how it works in Android..
        new Thread(new Runnable() {
            @Override
            public void run() {
                audioManager = (AudioManager) context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
                            audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
                            Toast.makeText(context, "Ringer Mode set to Normal", Toast.LENGTH_SHORT).show();
                        } else {
                            audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
                            Toast.makeText(context, "Ringer Mode set to Silent", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        }).start();

    }

}
Rizwan Sohaib
sumber
5

Saya seorang pemula Android tetapi ini adalah kelas timer yang saya buat berdasarkan jawaban di atas. Ini berfungsi untuk aplikasi saya, tetapi saya menerima saran.

Contoh penggunaan:

...{
public Handler uiHandler = new Handler();

  private Runnable runMethod = new Runnable()
    {
        public void run()
        {
              // do something
        }
    };

    timer = new UITimer(handler, runMethod, timeoutSeconds*1000);       
        timer.start();
}...

public class UITimer
{
    private Handler handler;
    private Runnable runMethod;
    private int intervalMs;
    private boolean enabled = false;
    private boolean oneTime = false;

    public UITimer(Handler handler, Runnable runMethod, int intervalMs)
    {
        this.handler = handler;
        this.runMethod = runMethod;
        this.intervalMs = intervalMs;
    }

    public UITimer(Handler handler, Runnable runMethod, int intervalMs, boolean oneTime)
    {
        this(handler, runMethod, intervalMs);
        this.oneTime = oneTime;
    }

    public void start()
    {
        if (enabled)
            return;

        if (intervalMs < 1)
        {
            Log.e("timer start", "Invalid interval:" + intervalMs);
            return;
        }

        enabled = true;
        handler.postDelayed(timer_tick, intervalMs);        
    }

    public void stop()
    {
        if (!enabled)
            return;

        enabled = false;
        handler.removeCallbacks(runMethod);
        handler.removeCallbacks(timer_tick);
    }

    public boolean isEnabled()
    {
        return enabled;
    }

    private Runnable timer_tick = new Runnable()
    {
        public void run()
        {
            if (!enabled)
                return;

            handler.post(runMethod);

            if (oneTime)
            {
                enabled = false;
                return;
            }

            handler.postDelayed(timer_tick, intervalMs);
        }
    }; 
}
pengguna868020
sumber
3

Saya menggunakan handler dan runnable untuk membuat timer. Saya membungkus ini dalam kelas abstrak. Turunkan / implementasikan saja dan Anda bisa melakukannya:

 public static abstract class SimpleTimer {
    abstract void onTimer();

    private Runnable runnableCode = null;
    private Handler handler = new Handler();

    void startDelayed(final int intervalMS, int delayMS) {
        runnableCode = new Runnable() {
            @Override
            public void run() {
                handler.postDelayed(runnableCode, intervalMS);
                onTimer();
            }
        };
        handler.postDelayed(runnableCode, delayMS);
    }

    void start(final int intervalMS) {
        startDelayed(intervalMS, 0);
    }

    void stop() {
        handler.removeCallbacks(runnableCode);
    }
}

Perhatikan bahwa handler.postDelayedkode dipanggil sebelum kode dieksekusi - ini akan membuat timer lebih tertutup waktunya seperti "yang diharapkan". Namun dalam kasus itu timer sering berjalan dan tugas ( onTimer()) panjang - mungkin ada tumpang tindih. Jika Anda ingin mulai menghitung intervalMSsetelah tugas selesai, pindahkan onTimer()panggilan ke baris di atas.

elcuco
sumber
2

Saya percaya cara untuk melakukan ini di android adalah bahwa Anda memerlukan layanan latar belakang untuk dapat berjalan. Di aplikasi latar belakang itu, buat pengatur waktu. Ketika penghitung waktu "berdetak" (mengatur interval berapa lama Anda ingin menunggu), luncurkan aktivitas yang ingin Anda mulai.

http://developer.android.com/guide/topics/fundamentals.html (<- artikel ini menjelaskan hubungan antara kegiatan, layanan, maksud, dan dasar-dasar inti lainnya dari pengembangan Android)

Crowe T. Robot
sumber
1

Saya biasa menggunakan ( Timer, TimerTask) dan juga Handleruntuk memulai (memakan waktu) tugas secara berkala. Sekarang saya sudah beralih keseluruhan ke RxJava. RxJava menyediakan Observable.timermana yang lebih sederhana, tidak rawan kesalahan, tidak mudah digunakan.

public class BetterTimerFragment extends Fragment {
  public static final String TAG = "BetterTimer";
  private TextView timeView;
  private Subscription timerSubscription;

  @Override
  public View onCreateView(LayoutInflater inflater,
                           @Nullable ViewGroup container,
                           @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_timer, container, false);
  }

  @Override
  public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    timeView = (TextView) view.findViewById(R.id.timeView);
  }

  @Override
  public void onResume() {
    super.onResume();

    // Right after the app is visible to users, delay 2 seconds
    // then kick off a (heavy) task every 10 seconds.
    timerSubscription = Observable.timer(2, 10, TimeUnit.SECONDS)
        .map(new Func1<Long, String>() {
          @Override
          public String call(Long unused) {
            // TODO: Probably do time-consuming work here.
            // This runs on a different thread than the main thread.
            return "Time: " + System.currentTimeMillis();
          }
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<String>() {
          @Override
          public void call(String timeText) {
            // The result will then be propagated back to the main thread.
            timeView.setText(timeText);
          }
        }, new Action1<Throwable>() {
          @Override
          public void call(Throwable throwable) {
            Log.e(TAG, throwable.getMessage(), throwable);
          }
        });
  }

  @Override
  public void onPause() {
    super.onPause();

    // Don't kick off tasks when the app gets invisible.
    timerSubscription.unsubscribe();
  }
}
Thuy Trinh
sumber
1

Untuk operasi pengaturan waktu Anda harus menggunakan Handler .

Jika Anda perlu menjalankan layanan latar belakang, AlarmManager adalah caranya.

robsf
sumber
0

contoh ini memulai timer unitl hancur di Kotlin

private lateinit var timerTask: TimerTask

 timerTask = object : TimerTask() {
        override fun run() {
            Log.d("KTZ", "$minutes:$seconds");
            timeRecordingLiveData.postValue("$minutes:$seconds")
            seconds += 1;
            if (seconds == 60) {
                Log.d("KTZ", "$minutes:$seconds");
                timeRecordingLiveData.postValue("$minutes:$seconds")
                seconds = 0;
                minutes += 1;
            }
        }

    }

Batalkan timertask di onDestroy ()

timerTask.cancel()
Kshitiz Mishra
sumber