Android'de bir zamanlayıcı nasıl ayarlanır


Yanıtlar:


143

Java.util.Timer ve java.util.TimerTask aracılığıyla zamanlayıcıları kullanmanın standart Java yolu Android'de iyi çalışıyor, ancak bu yöntemin yeni bir iş parçacığı oluşturduğunun farkında olmalısınız.

Çok uygun Handler sınıfını (android.os.Handler) kullanmayı ve sendMessageAtTime(android.os.Message, long)veya ile işleyiciye mesaj göndermeyi düşünebilirsiniz sendMessageDelayed(android.os.Message, long). Bir mesaj aldığınızda, istediğiniz görevleri çalıştırabilirsiniz. İkinci seçenek bir Runnable nesnesi oluşturmak ve bunu Handler's fonksiyonları postAtTime(java.lang.Runnable, long)veya postDelayed(java.lang.Runnable, long).


10
Bu android şeyler yapmak için yanlış bir yoldur. Android'de, görevleri çok ileride çalıştırmak için Alarm Manager'ı (developer.android.com/reference/android/app/AlarmManager.html) kullanmak istersiniz.
Kurtis Nusbaum

9
@Kurtis Nusbaum Soru gelecekte görevin ne kadar ileride olduğunu söylemiyor.
Christopher Perry

67
@KurtisNusbaum Bu mutlaka doğru değildir, bağlama bağlıdır. AlarmManager'daki dokümanlar "Not: Alarm Yöneticisi, uygulamanız şu anda çalışmıyor olsa bile uygulama kodunuzun belirli bir zamanda çalışmasını istediğiniz durumlar için tasarlanmıştır. Normal zamanlama işlemleri için (keneler, zaman aşımları, vb.) Handler'ı kullanmak daha kolay ve çok daha verimlidir. "
Christopher Perry

5
@Scienceprodigy Ah, anlıyorum. Yeterince adil.
Kurtis Nusbaum

10
bir görevi zamanlamak için Handler yöntemini kullanmak, ancak uygulama bir wakeLock almışsa ve dolayısıyla telefonun uyku durumuna geçmeyeceğinden eminseniz güvenilirdir. Telefon uyku durumuna geçerse, sendMessageDelayed ve sendMessageAtTime çalışmaz. Dolayısıyla bu senaryoda AlarmManager güvenilir bir seçim olacaktır.
crazyaboutliv

159

evet java'nın zamanlayıcısı kullanılabilir , ancak soru daha iyi bir yol istediğinden (mobil cihazlar için). Burada açıklanmaktadır .


StackOverflow uğruna:

Yana Zamanlayıcı ağır düşünülebilir yeni bir iş parçacığı oluşturur,

tek yapmanız gereken aktivite çalışırken geri çağrı yapmaksa , bir Handler bir

Çalıştırılabilir :

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

veya bir Mesaj

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

bir yan notta, UI iş parçacığında başka bir iş parçacığından bir parça kod çalıştırmak istiyorsanız bu yaklaşım kullanılabilir.

etkinliğiniz çalışmıyor olsa bile geri arama yapmanız gerekiyorsa, bir AlarmManager kullanabilirsiniz


1
Ah evet, tam olarak bu cevabı buldum. Yararlı bağlantı için benim oyumu al.
ulidtko

1
bağlantı güncellendi, google bağlantılarını korumakta sorun yaşıyorum.
Samuel

1
2007'den bu makale - bunun yanlış olduğunu söylemiyor, ancak 3 yıldan eski ise mobil bir makaleden her zaman şüpheleniyorum. Her şey çok hızlı değişiyor.
StackOverflowed

1
Cevabınızın ana noktalarını cevabınızda bulabilirseniz daha çok StackOverflow gibi olur.
n611x007

1
@naxa, bu cevabı daha çok StackOverflow gibi yapmak için iki sentim.
Samuel

131

Gördüğüm gibi, java.util.Timer bir zamanlayıcı uygulamak için en çok kullanılan.

Yinelenen bir görev için:

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

Bir görevin tek bir çalıştırılması için:

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


görev , ilk yürütme süresinden
sonra yürütülecek yöntemdir
( yürütmeyi tekrarlamak için zaman aralığı )


9
Sadece zamanın milisaniye cinsinden olduğunu ekleyeceğim
Uri


1
tasksınıfınızın java.util.TimerTask öğesinden devralınan ve geçersiz kılan bir örneği olabilir void run().
n611x007

2
Çok fazla oy. Bunu yapabilirsin. Ama @Samuel daha iyi yolu anlatıyor. Nedenine ilişkin "Burada açıklanmaktadır" bağlantısına bakın. Ayrıca, bir Zamanlayıcı iş parçacığından kullanıcı arayüzünü güncelleyemezsiniz! Ve diğer iş parçacıklarındaki diğer Handler tabanlı yanıtlara bakın: (basit) stackoverflow.com/a/6702767/199364 veya (çeşitli alternatifleri gösterir) stackoverflow.com/a/4598737/199364
ToolmakerSteve

@ quemeful çünkü her zaman kolaylık ile ilgili değil, kod kalitesi ve verimliliği ile ilgilidir. Bu şekilde Handler
inDepth

33

Umarım bu yardımcı olur ve uygulamak için daha az çaba harcayabilir , Android CountDownTimer sınıfı

Örneğin

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

      public void onFinish() {
          mTextField.setText("done!");
      }  
}.start();

1
Bu en kolay olanıdır ve bir video oynatma başlangıç ​​zamanı gibi basit geri sayım için sağa vurur
Vijay Kumar Kanta

17

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

veya

Yöntem 2 ::

Zamanlayıcıyı programlayın

Time isimli yeni bir int değişkeni ekleyin. MainActivity.java içinde onCreate işlevine aşağıdaki kodu ekleyin.

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

Run yöntemine gidin ve aşağıdaki kodu ekleyin.

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

});

11

Durumsaldır.

Android belgeleri, uygulamanız çalışmıyorsa belirtilen zamanda tetiklenecek bir Niyet kaydetmek için AlarmManager'ı kullanmanız gerektiğini önermektedir .

Aksi takdirde İşleyici kullanmalısınız.

Not: Alarm Yöneticisi, uygulamanız şu anda çalışmıyor olsa bile uygulama kodunuzun belirli bir zamanda çalışmasını istediğiniz durumlar için tasarlanmıştır. Normal zamanlama işlemleri için (keneler, zaman aşımları, vb.) İşleyiciyi kullanmak daha kolay ve çok daha verimlidir.


11

İşte başlıyoruz .. İki sınıfa ihtiyacımız olacak. Her 5 saniyeden sonra (5000 mili saniye) mobil ses profilini değiştiren bir kod gönderiyorum ...

1. Sınıfımız

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

}

2. Sınıfımız

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

    }

}

5

Ben bir Android acemi değilim ama yukarıdaki cevaplara dayanarak oluşturduğum zamanlayıcı sınıfı. Benim app için çalışır, ancak herhangi bir öneri hoş geldiniz.

Kullanım örneği:

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

3

Bir işleyici kullanıyorum ve bir zamanlayıcı oluşturmak için çalıştırılabilir. Bunu soyut bir sınıfa sarıyorum. Sadece türetin / uygulayın ve gitmeye hazırsınız:

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

handler.postDelayedKodun yürütülecek koddan önce çağrıldığına dikkat edin - bu, zamanlayıcının "beklenen" olarak daha fazla zamanlanmış olmasını sağlayacaktır. Ancak zamanlayıcının sık sık çalışması ve görev ( onTimer()) uzun olması durumunda - çakışmalar olabilir. intervalMSGörev tamamlandıktan sonra saymaya başlamak istiyorsanız , onTimer()çağrıyı yukarıdaki bir hatta taşıyın .


2

Android'de bunu yapmanın yolunun çalışmakta olan bir arka plan hizmetine ihtiyacınız olduğuna inanıyorum. Bu arka plan uygulamasında zamanlayıcıyı oluşturun. Zamanlayıcı "keneler" (ne kadar beklemek istediğinize ilişkin aralığı ayarlayın), başlatmak istediğiniz etkinliğinizi başlatın.

http://developer.android.com/guide/topics/fundamentals.html (<- bu makalede etkinlikler, hizmetler, niyetler ve Android geliştirmenin diğer temel temelleri arasındaki ilişki açıklanmaktadır)


1

Görevleri periyodik olarak başlatmanın yanı sıra ( Timer, TimerTask) kullanırdım Handler. Şimdi hepsini RxJava'ya çevirdim. RxJava Observable.timer, daha basit, daha az hataya açık, sorunsuz kullanım sağlar.

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

1

Zamanlama işlemi için Handler'ı kullanmalısınız .

Bir arka plan hizmeti çalıştırmanız gerekiyorsa, AlarmManager gitmenin yoludur.


0

Bu örnek Kotlin'de yok edilen zamanlayıcı birimini başlat

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

    }

OnDestroy () içindeki zamanlayıcı görevini iptal etme

timerTask.cancel()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.