วิธีเรียกใช้เมธอดทุกๆ X วินาที


114

ฉันกำลังพัฒนาระบบปฏิบัติการ Android 2.3.3 แอพลิเคชันและผมจำเป็นต้องใช้วิธีการทุกวินาที X

ใน iOS ฉันมีNSTimerแต่ใน Android ฉันไม่รู้ว่าจะใช้อะไร

มีคนแนะนำฉันHandler ; อีกคนแนะนำฉันAlarmManagerแต่ฉันไม่รู้ว่าวิธีไหนเหมาะกับNSTimer

นี่คือรหัสที่ฉันต้องการติดตั้งใน Android:

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

มีอะไรแนะนำฉัน


1
กำหนด "สิ่งที่ดีที่สุด" คุณต้องการให้มันดีที่สุดในทางใด?
Simon Forsberg

ฉันไม่รู้ว่าวิธีไหนเข้ากับ NSTimer ได้ดีกว่ากัน
VansFannel

@VansFannel คุณต้องการช่วงเวลานานแค่ไหน?
FoamyGuy

ฉันได้อัปเดตคำถามพร้อมรายละเอียดเกี่ยวกับสิ่งที่ฉันกำลังพยายามทำ
VansFannel

คำถามนี้: stackoverflow.com/questions/6242268/…คล้ายกับคำถามนี้และมีคำตอบที่ดี
VansFannel

คำตอบ:


169

สิ่งนี้ขึ้นอยู่กับระยะเวลาที่คุณต้องเรียกใช้ฟังก์ชัน

ถ้าเป็น => 10 นาที→ฉันจะใช้ Alarm Manager

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

จากนั้นคุณจะรับการออกอากาศเหล่านี้ผ่านเครื่องรับสัญญาณออกอากาศ โปรดทราบว่าสิ่งนี้จะต้องลงทะเบียนอีเธอร์ในรายการแอปพลิเคชันของคุณหรือผ่านcontext.registerReceiver(receiver,filter);วิธีการสำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Broadcast Receivers โปรดดูเอกสารอย่างเป็นทางการ รับสัญญาณออกอากาศ

public class MyReceiver extends BroadcastReceiver{

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

ถ้าเป็น = <10 นาที→ฉันจะไปกับ Handler

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

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

3
ทำไมคำแนะนำที่แตกต่างกันขึ้นอยู่กับเวลาล่าช้า?
Simon Forsberg

7
ประสิทธิภาพในเอกสาร AlarmManager ระบุว่าไม่ควรใช้สำหรับงานที่ทำซ้ำในช่วงเวลาเล็ก ๆ
Jug6ernaut

9
@ SimonAndréForsbergในเอกสาร AlarmManagerระบุว่า Handler เป็นวิธีที่มีประสิทธิภาพและมีประสิทธิภาพมากขึ้นในการใช้สำหรับเห็บสั้น: "หมายเหตุ: Alarm Manager มีไว้สำหรับกรณีที่คุณต้องการให้รหัสแอปพลิเคชันของคุณทำงานในช่วงเวลาที่กำหนดแม้ว่าคุณจะ แอปพลิเคชันไม่ได้ทำงานอยู่ในขณะนี้สำหรับการใช้งานการจับเวลาตามปกติ (เครื่องหมายการหมดเวลา ฯลฯ ) การใช้ Handler จะง่ายและมีประสิทธิภาพมากขึ้น "
FoamyGuy

แต่ฉันต้องเรียกใช้เมธอดในกิจกรรมเดียวกับที่เปิด AlarmManager ฉันจะทำเช่นนั้นได้อย่างไร?
VansFannel

2
@ahmadalibaloch จากภายใน runnable ที่คุณสามารถทำได้h.removeCallbacks(this);มิฉะนั้นคุณต้องรักษาการอ้างอิงถึง runnable เพื่อให้สามารถลบออกได้ หากต้องการวิธีที่สองวิธีที่โพสต์ไว้ที่นี่อาจไม่ใช่เส้นทางที่ดีที่สุดของคุณ
Jug6ernaut

101

ใช้ Timer ทุกวินาที ...

new Timer().scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        //your method
    }
}, 0, 1000);//put here time 1000 milliseconds=1 second

ฉันได้อัปเดตคำถามพร้อมรายละเอียดเกี่ยวกับสิ่งที่ฉันกำลังพยายามทำ
VansFannel

4
อย่าใช้ตัวจับเวลา ( mopri.de/2010/timertask-bad-do-it-the-android-way-use-a-handler ) ให้ใช้ Handler หรือ ScheduledThreadPoolExecutor
AppiDevo

69

คุณสามารถลองใช้รหัสนี้เพื่อโทรหาตัวจัดการทุกๆ 15 วินาทีผ่าน onResume () และหยุดการทำงานเมื่อมองไม่เห็นกิจกรรมผ่านทาง onPause ()

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
นี่คือสิ่งที่ฉันกำลังมองหา สมบูรณ์แบบ.
viper

3
นั่นคือคำตอบที่สมบูรณ์แบบ!
Riddhi

จับได้เห็นชัดตรงเผง! การใช้สำหรับการตรวจสอบแท็บ MainActivitys ที่เลือกในปัจจุบันใน TabLayout ตรงกับส่วนนี้และหากไม่หยุดทำงาน - เนื่องจาก onPause () ล้มเหลวเมื่อแท็บที่เลือก TabLayout ใด ๆ ที่ด้านใดด้านหนึ่งของแท็บที่เลือกนี้
BENN1TH

สมบูรณ์แบบ นี่คือสิ่งที่ฉันกำลังมองหา :) 1 คำถามฉันสามารถเรียกวิธีนี้จากกิจกรรมอื่นได้ไหม หรือถ้าฉันหลีกเลี่ยงกิจกรรมนี้วัตถุนี้จะถูกทำลาย? จะเกิดอะไรขึ้นถ้าฉันสร้างตัวจัดการแบบคงที่และรันได้ เป็นไปได้หรือไม่
hyperCoder

17

หากคุณคุ้นเคยกับ RxJava คุณสามารถใช้ Observable.interval () ซึ่งค่อนข้างเรียบร้อย

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

ข้อเสียคือคุณต้องออกแบบการสำรวจข้อมูลของคุณด้วยวิธีอื่น อย่างไรก็ตามมีประโยชน์มากมายสำหรับวิธีการเขียนโปรแกรมแบบโต้ตอบ:

  1. แทนที่จะควบคุมข้อมูลของคุณผ่านการโทรกลับคุณจะสร้างสตรีมข้อมูลที่คุณสมัครรับข้อมูล สิ่งนี้จะแยกความกังวลของตรรกะ "ข้อมูลการสำรวจ" และตรรกะ "การเติม UI ด้วยข้อมูลของคุณ" เพื่อที่คุณจะได้ไม่ผสมรหัส "แหล่งข้อมูล" กับรหัส UI ของคุณ
  2. ด้วย RxAndroid คุณสามารถจัดการเธรดได้ด้วยโค้ดเพียง 2 บรรทัด

    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
    

โปรดตรวจสอบ RxJava มีช่วงการเรียนรู้ที่สูง แต่จะทำให้การจัดการการโทรแบบอะซิงโครนัสใน Android ง่ายขึ้นและสะอาดขึ้นมาก


4

ด้วย Kotlin ตอนนี้เราสามารถสร้างฟังก์ชันทั่วไปสำหรับสิ่งนี้ได้แล้ว!

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

และในการใช้งานเพียงทำ:

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
อย่าโพสต์โค้ดตอบอย่างเดียว โปรดแก้ไขคำตอบของคุณและเพิ่มคำอธิบาย
Shashanth

2

ที่นี่ฉันใช้เธรดใน onCreate () กิจกรรมซ้ำ ๆ ตัวจับเวลาไม่อนุญาตให้ทุกอย่างในบางกรณีเธรดเป็นวิธีแก้ปัญหา

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

ในกรณีที่จำเป็นสามารถแวะได้

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

โปรดอธิบายสถานการณ์ที่คำตอบของฉันใช้ไม่ได้
Umar Ata

สวัสดีท่านอุมัร ฉันต้องการวงกลมตลอดเวลาที่แอปมีชีวิต Handler ทำให้การทำซ้ำมีชีวิตในขณะที่กิจกรรมยังมีชีวิตอยู่ แต่ฉันต้องการวงกลมในขณะที่ฉันสามารถเยี่ยมชมกิจกรรมอื่น ๆ ได้ด้วย เธรดจึงเป็นวิธีแก้ปัญหาในลักษณะนี้เพื่อให้แน่ใจว่ามันมีปัญหาเช่นกัน
แซม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.