233

コードに「ステータス」という変数があります。

この変数値に応じて、アプリケーションにテキストを表示したいと思います。これは、特定の時間遅延で実行する必要があります。

それは、

  • ステータス変数値を確認してください

  • テキストを表示する

  • 10秒待ちます

  • ステータス変数値を確認してください

  • テキストを表示する

  • 15秒待ちます

等々。時間遅延は異なる場合があり、テキストが表示されると設定されます。

試しThread.sleep(time delay)ましたが失敗しました。これを行うためのより良い方法はありますか?

4

12 に答える 12

469

この目的には、Handlerの関数を使用する必要があります。postDelayedメインUIスレッドで指定された遅延でコードが実行されるため、UIコントロールを更新できます。

private int mInterval = 5000; // 5 seconds by default, can be changed later
private Handler mHandler;

@Override
protected void onCreate(Bundle bundle) {

    // your code here

    mHandler = new Handler();
    startRepeatingTask();
}

@Override
public void onDestroy() {
    super.onDestroy();
    stopRepeatingTask();
}

Runnable mStatusChecker = new Runnable() {
    @Override 
    public void run() {
          try {
               updateStatus(); //this function can change value of mInterval.
          } finally {
               // 100% guarantee that this always happens, even if
               // your update method throws an exception
               mHandler.postDelayed(mStatusChecker, mInterval);
          }
    }
};

void startRepeatingTask() {
    mStatusChecker.run(); 
}

void stopRepeatingTask() {
    mHandler.removeCallbacks(mStatusChecker);
}
于 2011-06-05T10:17:34.137 に答える
40

興味のある人には、必要なものすべてを作成する inazaruk のコードを使用して作成したクラスを次に示します (定期的に UI を更新するために使用するため、UIUpdater と呼びましたが、好きなように呼び出すことができます)。

import android.os.Handler;
/**
 * A class used to perform periodical updates,
 * specified inside a runnable object. An update interval
 * may be specified (otherwise, the class will perform the 
 * update every 2 seconds).
 * 
 * @author Carlos Simões
 */
public class UIUpdater {
        // Create a Handler that uses the Main Looper to run in
        private Handler mHandler = new Handler(Looper.getMainLooper());

        private Runnable mStatusChecker;
        private int UPDATE_INTERVAL = 2000;

        /**
         * Creates an UIUpdater object, that can be used to
         * perform UIUpdates on a specified time interval.
         * 
         * @param uiUpdater A runnable containing the update routine.
         */
        public UIUpdater(final Runnable uiUpdater) {
            mStatusChecker = new Runnable() {
                @Override
                public void run() {
                    // Run the passed runnable
                    uiUpdater.run();
                    // Re-run it after the update interval
                    mHandler.postDelayed(this, UPDATE_INTERVAL);
                }
            };
        }

        /**
         * The same as the default constructor, but specifying the
         * intended update interval.
         * 
         * @param uiUpdater A runnable containing the update routine.
         * @param interval  The interval over which the routine
         *                  should run (milliseconds).
         */
        public UIUpdater(Runnable uiUpdater, int interval){
            UPDATE_INTERVAL = interval;
            this(uiUpdater);
        }

        /**
         * Starts the periodical update routine (mStatusChecker 
         * adds the callback to the handler).
         */
        public synchronized void startUpdates(){
            mStatusChecker.run();
        }

        /**
         * Stops the periodical update routine from running,
         * by removing the callback.
         */
        public synchronized void stopUpdates(){
            mHandler.removeCallbacks(mStatusChecker);
        }
}

次に、クラス内に UIUpdater オブジェクトを作成し、次のように使用できます。

...
mUIUpdater = new UIUpdater(new Runnable() {
         @Override 
         public void run() {
            // do stuff ...
         }
    });

// Start updates
mUIUpdater.startUpdates();

// Stop updates
mUIUpdater.stopUpdates();
...

これをアクティビティ アップデーターとして使用する場合は、開始呼び出しを onResume() メソッド内に配置し、停止呼び出しを onPause() メソッド内に配置して、アクティビティの可視性に応じて更新が開始および停止するようにします。

于 2013-01-09T12:14:52.227 に答える
19

それには 3 つの方法があります。

ScheduledThreadPoolExecutor を使用する

スレッドのプールが必要ないため、少しやり過ぎです

   //----------------------SCHEDULER-------------------------
    private final ScheduledThreadPoolExecutor executor_ =
            new ScheduledThreadPoolExecutor(1);
     ScheduledFuture<?> schedulerFuture;
   public void  startScheduler() {
       schedulerFuture=  executor_.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                //DO YOUR THINGS
                pageIndexSwitcher.setVisibility(View.GONE);
            }
        }, 0L, 5*MILLI_SEC,  TimeUnit.MILLISECONDS);
    }


    public void  stopScheduler() {
        pageIndexSwitcher.setVisibility(View.VISIBLE);
        schedulerFuture.cancel(false);
        startScheduler();
    }

タイマー タスクを使用する

古い Android スタイル

    //----------------------TIMER  TASK-------------------------

    private Timer carousalTimer;
    private void startTimer() {
        carousalTimer = new Timer(); // At this line a new Thread will be created
        carousalTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                //DO YOUR THINGS
                pageIndexSwitcher.setVisibility(INVISIBLE);
            }
        }, 0, 5 * MILLI_SEC); // delay
    }

    void stopTimer() {
        carousalTimer.cancel();
    }

Handler と Runnable を使用する

モダン Android スタイル

    //----------------------HANDLER-------------------------

    private Handler taskHandler = new android.os.Handler();

    private Runnable repeatativeTaskRunnable = new Runnable() {
        public void run() {
            //DO YOUR THINGS
        }
    };

   void startHandler() {
        taskHandler.postDelayed(repeatativeTaskRunnable, 5 * MILLI_SEC);
    }

    void stopHandler() {
        taskHandler.removeCallbacks(repeatativeTaskRunnable);
    }

アクティビティ / コンテキストを使用した漏れのないハンドラー

Activity/Fragment クラスでメモリをリークしない内部 Handler クラスを宣言します

/**
     * Instances of static inner classes do not hold an implicit
     * reference to their outer class.
     */
    private static class NonLeakyHandler extends Handler {
        private final WeakReference<FlashActivity> mActivity;

        public NonLeakyHandler(FlashActivity activity) {
            mActivity = new WeakReference<FlashActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            FlashActivity activity = mActivity.get();
            if (activity != null) {
                // ...
            }
        }
    }

Activity/Fragment クラスで反復タスクを実行する runnable を宣言します

   private Runnable repeatativeTaskRunnable = new Runnable() {
        public void run() {
            new Handler(getMainLooper()).post(new Runnable() {
                @Override
                public void run() {

         //DO YOUR THINGS
        }
    };

Activity/Fragment で Handler オブジェクトを初期化します (ここで FlashActivity は私のアクティビティ クラスです)

//Task Handler
private Handler taskHandler = new NonLeakyHandler(FlashActivity.this);

固定時間間隔の後にタスクを繰り返すには

taskHandler.postDelayed(repeatativeTaskRunnable , DELAY_MILLIS);

タスクの繰り返しを止めるには

taskHandler .removeCallbacks(repeatativeTaskRunnable);

更新: コトリン:

    //update interval for widget
    override val UPDATE_INTERVAL = 1000L

    //Handler to repeat update
    private val updateWidgetHandler = Handler()

    //runnable to update widget
    private var updateWidgetRunnable: Runnable = Runnable {
        run {
            //Update UI
            updateWidget()
            // Re-run it after the update interval
            updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
        }

    }

 // SATART updating in foreground
 override fun onResume() {
        super.onResume()
        updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
    }


    // REMOVE callback if app in background
    override fun onPause() {
        super.onPause()
        updateWidgetHandler.removeCallbacks(updateWidgetRunnable);
    }
于 2017-08-10T04:25:25.200 に答える
15

タイマーは正常に動作します。ここでは、Timer を使用して 1.5 秒後にテキストを検索し、UI を更新します。それが役立つことを願っています。

private Timer _timer = new Timer();

_timer.schedule(new TimerTask() {
    @Override
    public void run() {
        // use runOnUiThread(Runnable action)
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                search();
            }
        });
    }
}, timeInterval);
于 2016-02-04T14:57:04.897 に答える
4

次の例を試してみてください!!!

onCreate() メソッドで [Handler] を使用します。これは postDelayed() メソッドを使用して Runnable をメッセージ キューに追加し、特定の例では 0 である指定された時間が経過した後に実行されます。1

このコードを参照してください:

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
    //------------------
    //------------------
    android.os.Handler customHandler = new android.os.Handler();
            customHandler.postDelayed(updateTimerThread, 0);
}

private Runnable updateTimerThread = new Runnable()
{
        public void run()
        {
            //write here whaterver you want to repeat
            customHandler.postDelayed(this, 1000);
        }
};

于 2014-04-05T09:46:19.120 に答える
4

私の場合、これらの条件のいずれかが真である場合にプロセスを実行する必要がありました: 前のプロセスが完了した場合、または 5 秒が既に経過した場合。それで、私は次のことを行い、かなりうまくいきました:

private Runnable mStatusChecker;
private Handler mHandler;

class {
method() {
  mStatusChecker = new Runnable() {
            int times = 0;
            @Override
            public void run() {
                if (times < 5) {
                    if (process1.isRead()) {
                        executeProcess2();
                    } else {
                        times++;
                        mHandler.postDelayed(mStatusChecker, 1000);
                    }
                } else {
                    executeProcess2();
                }
            }
        };

        mHandler = new Handler();
        startRepeatingTask();
}

    void startRepeatingTask() {
       mStatusChecker.run();
    }

    void stopRepeatingTask() {
        mHandler.removeCallbacks(mStatusChecker);
    }


}

process1 が読み込まれると、process2 が実行されます。そうでない場合は、変数の時間をインクリメントし、1 秒後に Handler が実行されるようにします。process1 が読み込まれるか、times が 5 になるまでループを維持します。times が 5 の場合は、5 秒が経過したことを意味し、1 秒ごとに process1.isRead() の if 句が実行されます。

于 2016-04-27T19:25:35.840 に答える
4

ScheduledThreadPoolExecutorに関する上記の投稿に基づいて、自分のニーズに合ったユーティリティを思いつきました (3 秒ごとにメソッドを起動したい)。

class MyActivity {
    private ScheduledThreadPoolExecutor mDialogDaemon;

    private void initDebugButtons() {
        Button btnSpawnDialogs = (Button)findViewById(R.id.btn_spawn_dialogs);
        btnSpawnDialogs.setVisibility(View.VISIBLE);
        btnSpawnDialogs.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                spawnDialogs();
            }
        });
    }

    private void spawnDialogs() {
        if (mDialogDaemon != null) {
            mDialogDaemon.shutdown();
            mDialogDaemon = null;
        }
        mDialogDaemon = new ScheduledThreadPoolExecutor(1);
        // This process will execute immediately, then execute every 3 seconds.
        mDialogDaemon.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // Do something worthwhile
                    }
                });
            }
        }, 0L, 3000L, TimeUnit.MILLISECONDS);
    }
}
于 2016-04-21T22:40:09.780 に答える
4

Handler を使用して、実行可能なコードを投稿できます。この手法は、https ://guides.codepath.com/android/Repeating-Periodic-Tasks で非常にうまく概説されています。

于 2015-09-28T22:01:40.447 に答える
1

Kotlin を使用している場合、inazaruk の回答は機能しません。IDE では変数を初期化する必要があるため、postDelayed内で を使用する代わりRunnableに、別のメソッドで使用します。

  • このように初期化しますRunnable

    private var myRunnable = Runnable {
        //Do some work
        //Magic happens here ↓
        runDelayedHandler(1000)   }
    
  • runDelayedHandler次のようにメソッドを初期化します。

     private fun runDelayedHandler(timeToWait : Long) {
        if (!keepRunning) {
            //Stop your handler
            handler.removeCallbacksAndMessages(null)
            //Do something here, this acts like onHandlerStop
        }
        else {
            //Keep it running
            handler.postDelayed(myRunnable, timeToWait)
        }
    }
    
  • keepRunningご覧のとおり、このアプローチにより、タスクの存続期間を制御できるようになり、アプリケーションの存続期間中にタスクを追跡および変更することができます。

于 2019-04-14T17:08:27.003 に答える