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


325

Birisi bir saniyede bir metin alanını güncellemek için basit bir örnek verebilir mi?

Uçan bir top yapmak istiyorum ve her saniye top koordinatlarını hesaplamak / güncellemek istiyorum, bu yüzden bir çeşit zamanlayıcıya ihtiyacım var.

Buradan hiçbir şey alamıyorum .



Yanıtlar:


463

Tamam, çünkü bu henüz temizlenmedi, ancak bunu halletmek için 3 basit yol var. Aşağıda 3'ün tamamını gösteren bir örnek ve altta sadece tercih edildiğine inandığım yöntemi gösteren bir örnek var. Ayrıca, gerektiğinde durumdan tasarruf ederek onPause'da görevlerinizi temizlemeyi unutmayın.


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


hatırlanması gereken en önemli şey, UI'nin yalnızca ana ui iş parçacığından değiştirilebileceğidir, bu nedenle bir işleyici veya etkinlik kullanın. runOnUIThread (Runnable r);

İşte tercih edilen yöntem olarak düşündüğüm şey.


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, harika örnek için teşekkürler. Belirttiğiniz diğer yöntemlere göre bir yöntemi kullanmanın herhangi bir avantajı / dezavantajı var mı?
Gautam

2
@Gautam Yukarıdaki tüm yöntemlerin yaklaşık olarak aynı performansı gösterdiğine inanıyorum. Ben şahsen runnable ve h2 Handler ile yukarıda açıklanan işleyici yöntemini tercih ediyorum, çünkü android geliştirici sitesi tarafından reçete edilen ve bence en zarif.
Dave.B

6
Tercih ettiğiniz yöntemin kodun geri kalanından ayrılması iyi olur. Sanki bir tercih ettiğiniz yolu, bir diğeri de alternatifleri gösteren bir örneğiniz olabilir. Her üç yöntemin birlikte olması, neler olup bittiğini anlamayı zorlaştırır (özellikle benim gibi bir android acemi için). Muhtemelen çok fazla şey soruyorum :)
Jesse Aldridge

4
@JesseAldridge İyi fikir. Devam ettim ve sadece tercih edilen yöntemle kod ekledim.
Dave.B

1
@bluesm Dürüst olmak gerekirse sadece düşünmedim ama evet bu iyi çalışır.
Dave.B

84

Basit! Yeni bir zamanlayıcı oluşturursunuz.

Timer timer = new Timer();

Sonra zamanlayıcı görevini genişletirsiniz

class UpdateBallTask extends TimerTask {
   Ball myBall;

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

Ve sonra yeni görevi bazı güncelleme aralıklarıyla Zamanlayıcıya ekleyin

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

Feragatname: Bu ideal bir çözüm değildir. Bu, Timer sınıfını kullanan bir çözümdür (OP tarafından sorulduğu gibi). Android SDK'da, Handler sınıfının kullanılması önerilir (kabul edilen cevapta örnek vardır).


1
yukarıdaki
yazıyı okursanız

2
Elbette. OP, oyunda kullanılmasını tavsiye etmeyeceğim TimerTask ile yapmak istedi.
kurgu

3
Ha? OP nasıl yapılmasını istediklerini belirtmedi . TimerTask kullanılan bir makaleye bağlandılar, ancak bunun bu şekilde yapılmasını talep etmediler.
ToolmakerSteve

1
Çok yardımcı oldu, Teşekkürler @fiction
Naveed Ahmad

1
büyük cevap takip etmek basit.
JMASTER B

64

Kodunuzu UI iş parçacığında da çalıştırmanız gerekiyorsa (zamanlayıcı iş parçacığında değil), bloga bir göz atın: 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

    }
};
}

Tamlık uğruna, zamanlayıcıyı durdurmak ve belki de yeniden başlatmak için ne yapmanız gerektiğini söyleyebilirsiniz. (Gerekli bilgileri burada buldum: stackoverflow.com/questions/11550561/… )
RenniePet

3
RunOnUIThread'i doğrudan TimerTask run yönteminden çağıramamanızın bir nedeni var mı? İyi çalışıyor gibi görünüyor ve başka bir yuvalama düzeyini kaldırıyor.
RichieHH

Elbette, tüm adımları anlamak sadece didaktik bir yöntemdir. Bu standardın okunabilir bir kodu olmasını öneririm.
Meir Gerenstadt

41

Gelecekte belirli bir süre boyunca düzenli bildirimlerle geri sayım yapmak istiyorsanız, API seviye 1'den beri kullanılabilen CountDownTimer sınıfını kullanabilirsiniz .

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

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

2
CountDownTimer yalnızca birkaç yürütmeden sonra ortadan kalkmasını istediğinizi biliyorsanız mantıklıdır. Bu tipik, ama özellikle esnek bir yaklaşım değildir. Daha yaygın olanı, sonsuza kadar tekrarlayan (artık gerekli olmadığında iptal ettiğiniz) zamanlayıcı veya bir kez çalışan işleyicidir ve daha sonra tekrar gerekirse yeniden başlar. Diğer cevaplara bakın.
ToolmakerSteve

1
Tamamen haklısın. Sınıf adından bitişe kadar bir kez geri sayım sayacı işaretlemesi sağlar ve elbette uygulamasında Handler'ı kullanır.
Ahmed Hegazy

Milisaniye nasıl gösterilir? Formatında SS:MiMi? Teşekkürler
Ruchir Baronia

26

Bu bir zamanlayıcı için bazı basit kodlardır:

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

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

12

Ben Rx şekilde yapabilirsiniz düşünüyorum:

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

Ve şu şekilde iptal edin:

timerSubscribe.unsubscribe();

Rx Zamanlayıcı http://reactivex.io/documentation/operators/timer.html


10

Bu soru hala google aramadan (Android zamanlayıcı hakkında) birçok kullanıcıyı çektiğinden, iki paramı eklemek istiyorum.

Her şeyden önce, Timer sınıfı Java 9'da kullanımdan kaldırılacaktır (kabul edilen cevabı okuyun) .

Önerilen resmi yol, komutları belirli bir gecikmeden sonra çalışacak şekilde veya periyodik olarak çalışacak şekilde zamanlayabilen daha etkili ve zengin özelliklere sahip ScheduledThreadPoolExecutor kullanmaktır . Ayrıca, ThreadPoolExecutor ek esneklik ve yetenekleri sağlar.

İşte düz işlevlerin kullanımına bir örnek.

  1. Yürütücü hizmeti oluşturun:

    final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);
  2. Sadece koşabildiğini programla:

    final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit);
  3. Artık futuregörevi iptal etmek veya örneğin yapılıp yapılmadığını kontrol etmek için kullanabilirsiniz :

    future.isDone();

Umarım bunu Android'de bir görev oluşturmak için yararlı bulacaksınız.

Komple örnek:

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

8

RxJava2 ile çözümden bahsedecek bir cevap olmadığına şaşırdım . Gerçekten basittir ve Android'de zamanlayıcıyı kurmak için kolay bir yol sağlar.

Öncelikle, daha önce yapmadıysanız Gradle bağımlılığını ayarlamanız gerekir:

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

(yerine xve ybirlikte mevcut sürüm numarası )

Basit, tekrar etmeyen bir görevimiz olduğundan , Completablenesneyi kullanabiliriz :

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

İçin görev yinelenen , kullanabileceğiniz Observablebenzer bir şekilde:

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

Schedulers.computation() zamanlayıcının arka plan iş parçacığında çalışmasını sağlar ve .observeOn(AndroidSchedulers.mainThread()) zamanlayıcı tamamlandıktan sonra çalıştırdığımız kodun ana iş parçacığında gerçekleştirileceği anlamına gelir.

İstenmeyen bellek sızıntılarını önlemek için, Etkinlik / Parça yok edildiğinde abonelikten çıkmayı unutmayın.


4
Bu en temiz yaklaşım!
Constantin

bunlar nasıl iptal edilir? yani kullanıcı kullanıcı arayüzündeki [STOP] düğmesine bastığında ve Completable çalıştırılmadan önce iptal edilir.
Birisi bir yerde

@SomeoneSomewhere SubscriptionDöndürülen .subscribe()yöntemle değişkeni kaydedip subscription.unsubscribe()zamanlayıcıyı durdurmak istediğinizde arayın .
Micer

2

O daha basit bir çözüm, benim app iyi çalışıyor.

  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

UI güncellemelerinizin zaten var olan UI iş parçacığında olmasını istiyorsunuz.

En iyi yol, bir gecikmeden sonra bir Runnable çalıştırmak için postDelayed kullanan bir işleyici kullanmaktır (her çalışma bir sonraki programı zamanlar); removeCallbacks ile geri aramayı silin.

Zaten doğru yere bakıyorsunuz, bu yüzden tekrar bakın, belki de bu kod örneğinin neden istediğiniz şey olmadığını açıklayın. (Ayrıca UI'yi bir Zamanlayıcıdan Güncelleme konusundaki aynı makaleye bakın ).


Maalesef bağlantınız öldü. Doğru makaleyi hızlı bir şekilde bulamıyorum.
Lekensteyn


1

İşte basit ve güvenilir bir yol ...

Etkinliğinize aşağıdaki kodu koyun; etkinliğiniz "devam" durumundayken her saniye UI iş parçacığında tick () yöntemi çağrılır. Tabii ki, tick () yöntemini istediğinizi yapmak veya daha az veya daha sık çağırmak için değiştirebilirsiniz.

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

İlgilenenler için, faaliyetiniz bekleme süresi içinde duraklatılır ve devam ettirilirse, iki zamanlayıcının aynı anda çalışmasını önlemek için "_h0 = _handler" kodu gereklidir.


2
Neden bu garip yapmak _h0yerine, yaklaşım removeCallbacksiçinde onPauseherkes gibi?
ToolmakerSteve

1

Bunun için bir animatör de kullanabilirsiniz:

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

Güncelleme döngüsünü işlemek için bir iş parçacığı oluşturmanız ve bunu metin alanını güncellemek için kullanmanız gerekir. Zor kısmı olsa sadece ana iş parçacığı gerçekten ui değiştirebilir, böylece güncelleme döngü iş parçacığı güncelleme yapmak için ana iş parçacığı sinyal gerekir. Bu bir Handler kullanılarak yapılır.

Bu bağlantıya göz atın: http://developer.android.com/guide/topics/ui/dialogs.html# "İkinci bir iş parçacığına sahip Örnek ProgressDialog" başlıklı bölüme tıklayın. Metin alanı yerine ilerleme iletişim kutusu dışında, tam olarak ne yapmanız gerektiğine bir örnek.


Bunu yapma. Bunu sizin için yapan basit bir zamanlayıcı sınıfı var. Ve bu sorunun progressdialog veya diyaloglarla hiçbir ilgisi yok.
Falmarri

Gönderdiğim bağlantının bölümüne mi baktınız yoksa sadece diyalog penceresini gördünüz ve varsaydınız mı? Buradaki kod% 100 ilgili. Ayrıca FYI, zamanlayıcı kullanıyorsanız, güncelleme döngüsünü işlemek için bir iş parçacığı oluşturmaya devam edersiniz. İşleyiciyi, gönderdiğim bağlantıda açıklandığı gibi kullanmanız gerekir.
Nick

Maalesef, bağlantılı sayfa artık adı geçen bir bölüm içermiyor. Kod bağlanırken, anahtar snippet'i her zaman doğrudan cevabınıza dahil edilmelidir.
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
Belki bazı kod girintileri ve kod açıklamaları yararlı olabilir.
Raul Rene

0

Herkes ilgileniyorsa, bir etkinlikler UI iş parçacığı üzerinde çalıştırmak için standart bir nesne oluşturma ile oynamaya başladı. Tamam görünüyor. Yorumlarınızı bekliyoruz. Bunun, bir etkinliğe sürüklenecek bir bileşen olarak düzen tasarımcısında bulunmasını çok isterim. Böyle bir şeyin mevcut olmadığına inanamıyorum.

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

Faaliyette, ben bu onStart var:

@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
ahbap ActivityTimerListener ile sorun nedir? ADT Paketim böyle bir sınıfın olmadığını söyledi.
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"/>


Bunu orijinal soru ve cevaplardan birkaç yıl sonra eklediğinizi görüyorum. Lütfen bu cevabın zaten var olan diğer cevaplarla nasıl karşılaştırıldığına dair açıklama ekleyin. Neden bir tane daha eklediniz - diğer cevaplarda ne fayda / ne zaman yararlı / hangi eksiklik gördünüz?
ToolmakerSteve

Sadece aynı işi farklı bir yaklaşımla yapan bir kodu paylaşıyorum. Ancak herhangi bir görünümün verilerini güncellemek istediğinizde. Bunun için işleyici kullanmalısınız. çünkü çoğu zaman bir görünümü güncellemek için bir zamanlayıcı görevini kullanmak işe yaramaz olduğunu fark var .. @ Dave.B yöntemi benim bilgi için daha doğru.
Zar E Ahmer

0

Zaten delta zamanınız varsa.

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

I Timer'ı soyutlayıp ayrı bir sınıf haline getirdim:

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

Ve ana eylemi Timersınıftan dışarı çıkarın

IAction.java

public interface IAction {
    void Task();
}

Ben de aynen şöyle kullandım:

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

I Hope This Helps 😊👌 Instagram Hesabındaki Takipçileri


0

Bu şekilde kullanıyorum:

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

sonra onCreate'ın altında

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

bu sorunu çözmenin kolay yolu.


0

Kronometreye güvenemeyenler için , önerilerden birinden bir faydalı sınıf yaptım:

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

kullanmak için ...

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

.....

 timerTextHelper.stop();
 long elapsedTime = timerTextHelper.getElapsedTime();
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.