Her X saniyede bir yöntem nasıl çalıştırılır


114

Bir Android 2.3.3 uygulaması geliştiriyorum ve her X saniyede bir yöntem çalıştırmam gerekiyor .

İOS, ben var NSTimer ama Android'de ı kullanmayı bilmiyorum.

Birisi bana Handler'ı tavsiye etti ; bir başkası bana AlarmManager'ı öneriyor ancak hangi yöntemin NSTimer ile daha iyi uyduğunu bilmiyorum .

Android'de uygulamak istediğim kod bu:

timer2 = [
    NSTimer scheduledTimerWithTimeInterval:(1.0f/20.0f)
    target:self
    selector:@selector(loopTask)
    userInfo:nil
    repeats:YES
];

timer1 = [
    NSTimer scheduledTimerWithTimeInterval:(1.0f/4.0f)
    target:self
    selector:@selector(isFree)
    userInfo:nil
    repeats:YES
];

NSTimer gibi çalışan bir şeye ihtiyacım var .

Bana ne önerirsin


1
"En iyi olanı" tanımlayın. Ne şekilde en iyisi olmasını istersiniz?
Simon Forsberg

NSTimer ile hangi yöntemin daha uygun olduğunu bilmiyorum.
VansFannel

@VansFannel Ne kadar uzun bir aralık istiyorsun?
FoamyGuy

Soruyu, yapmaya çalıştığım şeyle ilgili ayrıntılarla güncelledim.
VansFannel

Bu soru: stackoverflow.com/questions/6242268/… , buna benzer ve harika bir cevabı var.
VansFannel

Yanıtlar:


169

Bu, işlevi ne kadar ayrı çalıştırmanız gerektiğine bağlıdır.

=> 10 dakika ise → Alarm Yöneticisi ile giderim.

// Some time when you want to run
Date when = new Date(System.currentTimeMillis());    

try{
   Intent someIntent = new Intent(someContext,MyReceiver.class); // intent to be launched

   // note this could be getActivity if you want to launch an activity
   PendingIntent pendingIntent = PendingIntent.getBroadcast(
        context, 
        0, // id, optional
        someIntent, // intent to launch
        PendingIntent.FLAG_CANCEL_CURRENT); // PendintIntent flag

   AlarmManager alarms = (AlarmManager) context.getSystemService(
        Context.ALARM_SERVICE);

   alarms.setRepeating(AlarmManager.RTC_WAKEUP,
        when.getTime(),
        AlarmManager.INTERVAL_FIFTEEN_MINUTES,
        pendingIntent); 

}catch(Exception e){
   e.printStackTrace();
}

Ve sonra bu yayınları yayın alıcısı üzerinden alırsınız. Bunun, başvuru manifestinizde veya context.registerReceiver(receiver,filter);yöntem aracılığıyla eter olarak kaydedilmesi gerekeceğini unutmayın Yayın Alıcıları hakkında daha fazla bilgi için lütfen resmi Dokümanlar'a bakın. Yayın Alıcısı .

public class MyReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) 
    {
         //do stuffs
    }
}

Eğer = <10 dakika ise → İşleyici ile giderim.

Handler handler = new Handler();
int delay = 1000; //milliseconds

handler.postDelayed(new Runnable(){
    public void run(){
        //do something
        handler.postDelayed(this, delay);
    }
}, delay);

3
Zaman gecikmesine bağlı olarak neden farklı öneriler?
Simon Forsberg

7
Verimlilik, AlarmManager belgelerinde, herhangi bir küçük aralıklı tekrarlayan görev için kullanılmaması gerektiğini belirtir.
Jug6ernaut

9
@ SimonAndréForsberg, AlarmManager belgelerinde , İşleyicinin kısa tıklamalar için tercih edilen ve daha verimli bir yöntem olduğunu belirtir: "Not: Alarm Yöneticisi, uygulama kodunuzun belirli bir zamanda çalıştırılmasını istediğiniz durumlar için tasarlanmıştır. uygulama şu anda çalışmıyor. Normal zamanlama işlemleri için (işaretler, zaman aşımları vb.) İşleyiciyi kullanmak daha kolay ve çok daha etkilidir. "
FoamyGuy

Ancak, AlarmManager'ı başlatan aynı Aktivitede bir yöntem çalıştırmam gerekiyor. Bunu nasıl yapabilirim?
VansFannel

2
@ahmadalibaloch çalıştırılabilirin içinden yapabilirsiniz h.removeCallbacks(this);, aksi takdirde onu kaldırabilmek için çalıştırılabilir bir referans tutmanız gerekir. İkincisi istenirse, burada belirtilen yöntem en iyi rotanız olmayabilir.
Jug6ernaut


69

İşleyiciyi onResume () aracılığıyla her 15 saniyede bir çağırmak ve etkinlik görünmediğinde onPause () yoluyla durdurmak için lütfen bu kodu deneyebilirsiniz.

Handler handler = new Handler();
Runnable runnable;
int delay = 15*1000; //Delay for 15 seconds.  One second = 1000 milliseconds.


@Override
protected void onResume() {
   //start handler as activity become visible

    handler.postDelayed( runnable = new Runnable() {
        public void run() {
            //do something

            handler.postDelayed(runnable, delay);
        }
    }, delay);

    super.onResume();
}

// If onPause() is not included the threads will double up when you 
// reload the activity 

@Override
protected void onPause() {
    handler.removeCallbacks(runnable); //stop handler when activity not visible
    super.onPause();
}

5
Aradığım şey buydu. Mükemmel.
viper

3
bu mükemmel Cevap!
Riddhi

Yerde! MainActivitys'yi kontrol etmek için kullanmak TabLayout'ta mevcut seçili sekme bu parçayla eşleşir ve çalışmayı durdurmazsa - çünkü bu seçili sekmenin her iki tarafında herhangi bir TabLayout seçili sekme olduğunda onPause () başarısız olur
BENN1TH

mükemmel. İşte aradığım buydu :) 1 soru, bu yöntemi başka bir aktiviteden arayabilir miyim? Ya da bu faaliyeti bırakırsam bu nesne yok edilecek mi? Statik bir işleyici ve çalıştırılabilir oluşturursam ne olur? Mümkün mü?
hyperCoder

17

RxJava'ya aşina iseniz, oldukça düzgün olan Observable.interval () kullanabilirsiniz.

Observable.interval(60, TimeUnits.SECONDS)
          .flatMap(new Function<Long, ObservableSource<String>>() {
                @Override
                public ObservableSource<String> apply(@NonNull Long aLong) throws Exception {
                    return getDataObservable(); //Where you pull your data
                }
            });

Bunun dezavantajı, verilerinizi farklı bir şekilde sorgulamak zorunda olmanızdır. Bununla birlikte, Reaktif Programlama yönteminin birçok faydası vardır:

  1. Verilerinizi bir geri arama yoluyla kontrol etmek yerine, abone olduğunuz bir veri akışı oluşturursunuz. Bu, "veri sorgulama" mantığı ve "kullanıcı arayüzünü verilerinizle doldurma" mantığını ayırır, böylece "veri kaynağı" kodunuzu ve UI kodunuzu karıştırmazsınız.
  2. RxAndroid ile, konuları sadece 2 satır kodda işleyebilirsiniz.

    Observable.interval(60, TimeUnits.SECONDS)
          .flatMap(...) // polling data code
          .subscribeOn(Schedulers.newThread()) // poll data on a background thread
          .observeOn(AndroidSchedulers.mainThread()) // populate UI on main thread
          .subscribe(...); // your UI code

Lütfen RxJava'ya bakın. Yüksek bir öğrenme eğrisine sahiptir, ancak Android'de eşzamansız çağrıları çok daha kolay ve temiz hale getirecektir.


4

Kotlin ile artık bunun için genel bir fonksiyon yapabiliriz!

object RepeatHelper {
    fun repeatDelayed(delay: Long, todo: () -> Unit) {
        val handler = Handler()
        handler.postDelayed(object : Runnable {
            override fun run() {
                todo()
                handler.postDelayed(this, delay)
            }
        }, delay)
    }
}

Ve kullanmak için yapmanız gerekenler:

val delay = 1000L
RepeatHelper.repeatDelayed(delay) {
    myRepeatedFunction()
}

3
    new CountDownTimer(120000, 1000) {

        public void onTick(long millisUntilFinished) {
            txtcounter.setText(" " + millisUntilFinished / 1000);

        }

        public void onFinish() {

            txtcounter.setText(" TimeOut  ");
            Main2Activity.ShowPayment = false;
            EventBus.getDefault().post("go-main");

        }

    }.start();

4
Yalnızca yanıt kodu göndermeyin. Lütfen cevabınızı düzenleyin ve bir açıklama ekleyin.
Shashanth

2

Burada onCreate () bir Activity'de tekrar tekrar bir thread kullandım, timer bazı durumlarda her şeye izin vermiyor Thread çözümdür

     Thread t = new Thread() {
        @Override
        public void run() {
            while (!isInterrupted()) {
                try {
                    Thread.sleep(10000);  //1000ms = 1 sec
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            SharedPreferences mPrefs = getSharedPreferences("sam", MODE_PRIVATE);
                            Gson gson = new Gson();
                            String json = mPrefs.getString("chat_list", "");
                            GelenMesajlar model = gson.fromJson(json, GelenMesajlar.class);
                            String sam = "";

                            ChatAdapter adapter = new ChatAdapter(Chat.this, model.getData());
                            listview.setAdapter(adapter);
                           // listview.setStackFromBottom(true);
                          //  Util.showMessage(Chat.this,"Merhabalar");
                        }
                    });

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    t.start();

İhtiyaç duyulması halinde durdurulabilir

@Override
protected void onDestroy() {
    super.onDestroy();
    Thread.interrupted();
    //t.interrupted();
}

lütfen cevabımın işe yaramayacağı durumu açıklayın
Umar Ata

Merhaba Umar. Uygulamanın canlı olduğu süre boyunca bir çembere ihtiyacım vardı, Handler etkinlik canlıyken tekrarı canlı yaptı ancak diğer etkinlikleri de ziyaret ederken çembere ihtiyacım var. Öyleyse iplik bu şekilde çözümdür, elbette mücadelesi de vardır.
Sam

1

Burada , Rx Java & Rx Android kullanarak sorununuz için faydalı yanıt olabilir .

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.