X秒ごとにメソッドを実行する方法


114

Android 2.3.3アプリケーションを開発しています。X秒ごとにメソッドを実行する必要があります。

iOSではNSTimerを使用していますが、Androidでは何を使用すればよいかわかりません。

誰かが私にハンドラを勧めています。もう1つは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、2012

どのメソッドがNSTimerに適しているのかわかりません。
VansFannel 2012

@VansFannelどれくらいの間隔が必要ですか?
FoamyGuy

私がやろうとしていることの詳細で質問を更新しました。
VansFannel 2012

この質問:stackoverflow.com/questions/6242268/…は、この質問に似ており、すばらしい答えがあります。
VansFannel 2012

回答:


168

これは、関数を実行するために必要な間隔に本当に依存します。

10分以上の場合→アラームマネージャーを使用します。

// 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);メソッドを介して登録する必要があることに注意してください。ブロードキャストレシーバーの詳細については、公式ドキュメントを参照してください。放送レシーバー

public class MyReceiver extends BroadcastReceiver{

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

それが= <10分である場合→ハンドラーを使用します。

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、2012

7
効率性、AlarmManager docsには、小さな間隔の反復タスクには使用しないように記載されています。
Jug6ernaut

9
AlarmManagerドキュメントの @SimonAndréForsbergは、ハンドラーが短いティックに使用することが優先され、より効率的な方法であると述べています:「注:アラームマネージャーは、アプリケーションは現在実行されていません。通常のタイミング操作(ティック、タイムアウトなど)では、ハンドラーを使用する方が簡単で効率的です。」
FoamyGuy

しかし、AlarmManagerを起動したのと同じアクティビティでメソッドを実行する必要があります。どうやってやるの?
VansFannel 2012

2
@ahmadalibalochは、実行可能なランナブル内から実行できますh.removeCallbacks(this);。それ以外の場合は、ランナブルへの参照を維持して削除できます。2番目が望ましい場合は、ここに投稿された方法が最適なルートではない可能性があります。
Jug6ernaut 2016

101

毎秒タイマーを使用...

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

私がやろうとしていることの詳細で質問を更新しました。
VansFannel 2012

4
タイマー(mopri.de/2010/timertask-bad-do-it-the-android-way-use-a-handler)を使用せず、HandlerまたはScheduledThreadPoolExecutorを使用してください。
AppiDevo 2017年

69

このコードを試して、onResume()経由で15秒ごとにハンドラーを呼び出し、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
これは私が探していたものです。完璧です。
バイパー、

3
それは完璧な答えです!
Riddhi

スポット!TabLayoutでMainActivitysの現在選択されているタブをチェックするために使用すると、このフラグメントに一致し、作業が停止しない場合-この選択されたタブのいずれかの側でTabLayoutで選択されたタブがあるとonPause()が失敗する
BENN1TH

完璧。これは私が探していたものでした:) 1つの質問、別のアクティビティからこのメソッドを呼び出すことができますか?または、このアクティビティを傍受した場合、このオブジェクトは破棄されますか?静的ハンドラを作成して実行可能にするとどうなるでしょうか。それは可能ですか?
hyperCoder 2018年

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 2018

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

ウマルこんにちは。アプリが動作している間は常にサークルが必要でした。アクティビティが動作している間、ハンドラは繰り返し動作を実行しましたが、他のアクティビティにアクセスできている間もサークルが必要です。したがって、スレッドはこのように解決策であり、確実に問題が発生します。
サム

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.