Как выполнить асинхронную задачу повторно через фиксированные промежутки времени - PullRequest
58 голосов
/ 30 июня 2011

Как заставить асинхронную задачу выполняться несколько раз через некоторый промежуток времени, как по таймеру ... На самом деле я разрабатываю приложение, которое будет автоматически загружать все последние непрочитанные приветствия с сервера, и для этой цели я должен проверять наличие обновлений с серверапосле некоторых фиксированных временных интервалов .... Я знаю, что это легко сделать с помощью таймера, но я хочу использовать асинхронную задачу, которая, на мой взгляд, более эффективна для приложений Android.

Ответы [ 5 ]

120 голосов
/ 30 июня 2011
public void callAsynchronousTask() {
    final Handler handler = new Handler();
    Timer timer = new Timer();
    TimerTask doAsynchronousTask = new TimerTask() {       
        @Override
        public void run() {
            handler.post(new Runnable() {
                public void run() {       
                    try {
                        PerformBackgroundTask performBackgroundTask = new PerformBackgroundTask();
                        // PerformBackgroundTask this class is the class that extends AsynchTask 
                        performBackgroundTask.execute();
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                    }
                }
            });
        }
    };
    timer.schedule(doAsynchronousTask, 0, 50000); //execute in every 50000 ms
}
6 голосов
/ 26 февраля 2014
  //Every 10000 ms   
       private void doSomethingRepeatedly() {
      Timer timer = new Timer();
      timer.scheduleAtFixedRate( new TimerTask() {
            public void run() {

                  try{

                     new SendToServer().execute(); 

                  }
                  catch (Exception e) {
                      // TODO: handle exception
                  }

             }
            }, 0, 10000);
                     }
2 голосов
/ 12 июля 2012

Не будет ли эффективнее создать службу и запланировать ее с помощью Alarm Manager?

2 голосов
/ 30 июня 2011

Вы можете просто обработчик:

private int m_interval = 5000; // 5 seconds by default, can be changed later
private Handle m_handler;

@Override
protected void onCreate(Bundle bundle)
{
  ...
  m_handler = new Handler();
}

Runnable m_statusChecker = new Runnable()
{
     @Override 
     public void run() {
          updateStatus(); //this function can change value of m_interval.
          m_handler.postDelayed(m_statusChecker, m_interval);
     }
}

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

void stopRepeatingTask()
{
    m_handler.removeCallback(m_statusChecker);
}

Но я бы порекомендовал вам проверить эту структуру: http://code.google.com/intl/de-DE/android/c2dm/ Это другой подход: сервер уведомит телефон, когда что-то будет готово (таким образом, сохраняя некоторую пропускную способность и производительность:))

0 голосов
/ 03 октября 2018

Принятый ответ проблематичен. Использование TimerTask () для активации асинхронной задачи через обработчик - плохая идея. при изменении ориентации вы должны помнить, чтобы отменить также таймер и вызов обработчика. в противном случае он будет вызывать асинхронную задачу снова и снова при каждом повороте. Это приведет к тому, что приложение взорвет сервер (если это запрос http http rest) вместо X time - в конце концов, вызовы будут повторять множество вызовов каждую секунду. (потому что будет много таймеров в зависимости от количества поворотов экрана). Это может сломать приложение, если активность и задача, выполняемая в фоновом потоке, тяжелые. если вы используете таймер, сделайте его классом memebr и отмените его onStop ():

            TimerTask mDoAsynchronousTask;


            @Override
            public void onStop(){
               super.onStop();                 
               mDoAsynchronousTask.cancel();
               mHandler.removeCallbacks(null);
               ... 
            }


          public void callAsynchronousTask(final boolean stopTimer) {
             Timer timer = new Timer();
             mDoAsynchronousTask = new TimerTask() {
                 @Override
                 public void run() {
                     mHandler.post(new Runnable() {
                 ...

Вместо этого попытайтесь избежать асинхронной задачи, и если вам необходимо использовать службу планировщика для запуска асинхронной задачи. или класс приложения, такой как в этой хорошей идее: https://fattybeagle.com/2011/02/15/android-asynctasks-during-a-screen-rotation-part-ii/

Или используйте простой обработчик (без таймера, просто используйте postDelayed), и также полезно вызывать отмену асинхронной задачи onStop (). этот код работает нормально, используя postDelayed:

           public class MainActivity extends AppCompatActivity {

                  MyAsync myAsync = new MyAsync();

                  private final Handler mSendSSLMessageHandler = new Handler();
                  private final Runnable mSendSSLRunnable = new Runnable(){

                  ..


                 @Override
                 protected void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                    setContentView(R.layout.activity_main);
                    ConnectivityManager connMgr = (ConnectivityManager)   
                    getSystemService(Context.CONNECTIVITY_SERVICE);
                    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
                    if (networkInfo != null && networkInfo.isConnected()) {
                            mSendSSLMessageHandler.post(mSendSSLRunnable);
                    }else
                    ..

                  @Override
                  public void onStop(){
                   super.onStop();
                      if ( progressDialog!=null && progressDialog.isShowing() ){
                           progressDialog.dismiss();
                      }
                    mSendSSLMessageHandler.removeCallbacks(mSendSSLRunnable);
                    myAsync.cancel(false);
                   }


              private final Runnable mSendSSLRunnable = new Runnable(){
              @Override
                public void run(){
                   try {
                    myAsync = new MyAsync();
                    myAsync.execute();
                   } catch (Exception e) {
                      // TODO Auto-generated catch block
                   }
                   mSendSSLMessageHandler.postDelayed(mSendSSLRunnable, 5000);
               }
          };


          class MyAsync extends AsyncTask<Void, Void, String> {
                boolean running = true;

                @Override
                protected void onPreExecute() {
                super.onPreExecute();
                  progressDialog = ProgressDialog.show               
                  (MainActivity.this, "downloading", "please wait");
                }

              @Override
              protected String doInBackground(Void... voids) {
                 if (!running) {
                       return null;
                  }
                 String result = null;
                 try{
                 URL url = new URL("http://192...");
                 HttpURLConnection urlConnection = (HttpURLConnection)            
                 url.openConnection();
                 InputStream in = new BufferedInputStream (urlConnection.getInputStream());
                 result = inputStreamToString(in);
                }catch(Exception e){
                   e.printStackTrace();
                }

               return result;
           }


    @Override
    protected void onCancelled() {
        boolean running = false;
    }
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        progressDialog.dismiss();
        try {

              ..


        } catch (JSONException e) {
            textView.append("json is invalid");
            e.printStackTrace();
        }

    }


}
...