Cách chạy một phương pháp sau mỗi X giây


114

Tôi đang phát triển một ứng dụng Android 2.3.3 và tôi cần chạy một phương pháp sau mỗi X giây .

Trong iOS, tôi có NSTimer , nhưng trong Android tôi không biết sử dụng cái gì.

Ai đó đã giới thiệu tôi Handler ; một người khác giới thiệu cho tôi AlarmManager nhưng tôi không biết phương pháp nào phù hợp hơn với NSTimer .

Đây là mã tôi muốn triển khai trong 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
];

Tôi cần một cái gì đó hoạt động như NSTimer .

Bạn khuyên tôi điều gì?


1
Xác định "cái tốt nhất". Bạn muốn nó là tốt nhất theo cách nào?
Simon Forsberg.

Tôi không biết phương pháp nào phù hợp hơn với NSTimer.
VansFannel

@VansFannel Bạn muốn khoảng thời gian bao lâu?
FoamyGuy

Tôi đã cập nhật câu hỏi với thông tin chi tiết về những gì tôi đang cố gắng làm.
VansFannel

Câu hỏi này: stackoverflow.com/questions/6242268/… , tương tự như câu hỏi này và có một câu trả lời tuyệt vời.
VansFannel

Câu trả lời:


168

Điều này thực sự phụ thuộc vào khoảng thời gian cách nhau bạn cần chạy chức năng.

Nếu là => 10 phút → Tôi sẽ sử dụng Trình quản lý báo thức.

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

Và sau đó bạn nhận các chương trình phát sóng này thông qua bộ thu phát sóng. Lưu ý rằng điều này sẽ cần được đăng ký ether trong bản kê khai ứng dụng của bạn hoặc thông qua context.registerReceiver(receiver,filter);phương thức Để biết thêm thông tin về Bộ thu phát sóng, vui lòng tham khảo Tài liệu chính thức. Máy thu phát sóng .

public class MyReceiver extends BroadcastReceiver{

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

Nếu nó = <10 phút → Tôi sẽ đi với một Xử lý.

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

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

3
Tại sao các đề xuất khác nhau tùy thuộc vào thời gian trễ?
Simon Forsberg

7
Hiệu quả, Trong tài liệu của AlarmManager, nó tuyên bố rằng nó không nên được sử dụng cho bất kỳ tác vụ lặp lại khoảng thời gian nhỏ nào.
Jug6ernaut, 11/12/12

9
@ SimonAndréForsberg trong tài liệu AlarmManager, nó nói rằng Handler là phương pháp được ưa chuộng và hiệu quả hơn để sử dụng cho các tick ngắn: "Lưu ý: Alarm Manager dành cho các trường hợp bạn muốn chạy mã ứng dụng của mình tại một thời điểm cụ thể, ngay cả khi ứng dụng hiện không chạy. Đối với các hoạt động định thời bình thường (tích tắc, hết giờ, v.v.), sử dụng Trình xử lý sẽ dễ dàng và hiệu quả hơn nhiều. "
FoamyGuy

Tuy nhiên, tôi cần chạy một phương thức trong cùng Hoạt động đã khởi chạy AlarmManager. Làm thế nào tôi có thể làm điều đó?
VansFannel

2
@ahmadalibaloch từ bên trong có thể chạy mà bạn có thể làm h.removeCallbacks(this);, nếu không, bạn cần duy trì tham chiếu đến có thể chạy để có thể xóa nó. Nếu bạn muốn thứ hai, phương pháp được đăng ở đây có thể không phải là con đường tốt nhất của bạn.
Jug6ernaut 19/08/2016

101

Sử dụng Hẹn giờ cho mỗi giây ...

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

Tôi đã cập nhật câu hỏi với thông tin chi tiết về những gì tôi đang cố gắng làm.
VansFannel

4
Không sử dụng Timer ( mopri.de/2010/timertask-bad-do-it-the-android-way-use-a-handler ), hãy sử dụng Handler hoặc SchedisedThreadPoolExecutor .
AppiDevo

69

Bạn có thể thử mã này để gọi trình xử lý 15 giây một lần qua onResume () và dừng nó khi hoạt động không hiển thị, qua 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
Đây là những gì tôi đang tìm kiếm. Hoàn hảo.
viper

3
đó là câu trả lời hoàn hảo!
Riddhi

Tại chỗ trên! Sử dụng để kiểm tra MainActivitys tab chọn hiện tại trong TabLayout phù hợp với đoạn này và làm việc nếu không dừng lại - như onPause () không thành công khi bất kỳ TabLayout chọn tab ở hai bên của tab chọn này
BENN1TH

hoàn hảo. Đây là những gì tôi đang tìm kiếm :) 1 câu hỏi, tôi có thể gọi phương pháp này từ một hoạt động khác không. Hoặc nếu tôi từ bỏ hoạt động này, đối tượng này sẽ bị phá hủy? Điều gì sẽ xảy ra nếu tôi tạo một trình xử lý tĩnh và có thể chạy được. Điều đó có thể không?
hyperCoder

17

Nếu bạn đã quen với RxJava, bạn có thể sử dụng Observable.interval (), khá gọn gàng.

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

Nhược điểm của điều này là bạn phải kiến ​​trúc thăm dò dữ liệu của mình theo một cách khác. Tuy nhiên, có rất nhiều lợi ích đối với cách Lập trình phản ứng:

  1. Thay vì kiểm soát dữ liệu của bạn thông qua lệnh gọi lại, bạn tạo một luồng dữ liệu mà bạn đăng ký. Điều này tách mối quan tâm của logic "dữ liệu thăm dò" và logic "điền giao diện người dùng với dữ liệu của bạn" để bạn không trộn lẫn mã "nguồn dữ liệu" và mã giao diện người dùng của mình.
  2. Với RxAndroid, bạn có thể xử lý các luồng chỉ trong 2 dòng mã.

    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

Vui lòng kiểm tra RxJava. Nó có một đường cong học tập cao nhưng nó sẽ giúp việc xử lý các cuộc gọi không đồng bộ trong Android trở nên dễ dàng và sạch sẽ hơn nhiều.


4

Với Kotlin, bây giờ chúng ta có thể tạo một hàm chung cho việc này!

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

Và để sử dụng, chỉ cần làm:

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
Không đăng mã chỉ trả lời. Vui lòng chỉnh sửa câu trả lời của bạn và thêm một số giải thích.
Shashanth

2

Ở đây tôi đã sử dụng một luồng trong onCreate () một Activity lặp lại, bộ đếm thời gian không cho phép mọi thứ trong một số trường hợp Thread là giải pháp

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

Trong trường hợp cần thiết, có thể dừng lại bằng

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

vui lòng mô tả tình huống khi câu trả lời của tôi sẽ không hoạt động
Umar Ata

Xin chào Umar. Tôi cần một vòng kết nối trong suốt thời gian ứng dụng đó tồn tại, Handler thực hiện lặp đi lặp lại trong khi hoạt động vẫn tồn tại nhưng tôi cần vòng kết nối trong khi tôi cũng có thể truy cập các hoạt động khác. Vì vậy, chủ đề là giải pháp theo cách này chắc chắn nó cũng có cuộc đấu tranh của nó.
Sam

1

Đây có thể là câu trả lời hữu ích cho vấn đề của bạn khi sử dụng Rx Java & Rx Android .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.