web-dev-qa-db-fra.com

Comment exécuter une tâche async à plusieurs reprises après des intervalles de temps fixes

Comment faire en sorte que la tâche Async s'exécute de manière répétée après un certain intervalle, exactement comme pour Timer ... intervalles de temps .... Je sais que cela peut être facilement fait par minuterie, mais je veux utiliser une tâche asynchrone qui, je pense, est plus efficace pour les applications Android 

57
Waseem
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
}
118
Rasel
  //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);
                     }
6
ritesh4326

ne serait-il pas plus efficace de créer un service et de le programmer via Alarm Manager?

2
Richie

Vous pouvez juste un gestionnaire:

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

Mais je vous recommande de vérifier ce cadre: http://code.google.com/intl/de-DE/Android/c2dm/ est une approche différente: le serveur avertira le téléphone lorsque quelque chose est prêt donc, économiser de la bande passante et des performances :))

2
kikoso

La réponse acceptée est problématique . Utiliser TimerTask () pour activer une tâche async via un gestionnaire est une mauvaise idée. lors du changement d’orientation, vous devez également vous rappeler d’annuler les appels de la minuterie et du gestionnaire. sinon, il appellera la tâche asynchrone à chaque rotation . Cela fera sauter le serveur par l'application (s'il s'agit d'une requête http rest restante) au lieu de l'heure X. Finalement, les appels seront des appels nombreux par exemple. à chaque seconde. (car il y aura beaucoup de minuteries en fonction du nombre de rotations d'écran). Cela pourrait écraser l'application si l'activité et la tâche s'exécutant dans le fil d'arrière-plan sont lourdes. si vous utilisez le timer, faites-en une classe memebr et annulez-la 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() {
                 ...

Au lieu de cela, essayez d'éviter la tâche async, et si vous devez ensuite utiliser le service de planificateur pour exécuter la tâche async. ou la classe d'application telle que dans cette idée intéressante: https://fattybeagle.com/2011/02/15/Android-asynctasks-during-a-screen-rotation-part-ii/

Ou utilisez un gestionnaire simple (sans le minuteur, utilisez simplement postDelayed) et il est également bon d’appeler pour annuler la tâche async sur onStop (). Ce code fonctionne bien avec 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();
        }

    }


}
0
Udi Reshef