【问题标题】:How to execute Async task repeatedly after fixed time intervals如何在固定时间间隔后重复执行异步任务
【发布时间】:2011-09-25 19:02:33
【问题描述】:

如何让异步任务像定时器一样在一段时间间隔后重复执行...实际上我正在开发一个应用程序,它将自动从服务器下载所有最新的未读问候语,为此我必须检查来自服务器的更新经过一些固定的时间间隔......我知道这可以通过计时器轻松完成,但我想使用我认为对 android 应用程序更有效的异步任务。

【问题讨论】:

    标签: android android-asynctask android-service timertask


    【解决方案1】:
    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
    }
    

    【讨论】:

    • Async Task 无论如何都在它自己的线程中运行。为什么要在处理程序上运行它?
    • 是的,异步任务确实在单独的线程上运行,但不能从 UI 线程以外的其他线程启动。我猜,处理程序是为了允许这样做。
    • 如果启动这些 AsyncTask 的 Activity 被终止(通过方向更改或操作系统中断,如电话呼叫),此技术会留下悬空引用。因此,如果您对自己的程序在这些时候崩溃感到满意,那么请务必使用此方法。
    • @ScottBiggs 哪种技术会更好/不会崩溃?
    • @colti:还没有找到好的解决方案。除了非常简单的东西外,我已经放弃了 ASyncTasks。对于更复杂的操作,我使用服务(是的,我知道,开销是一个痛苦的$$,但至少它不会崩溃那么多。小心清理,不要留下悬空的服务) .
    【解决方案2】:
      //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);
                         }
    

    【讨论】:

    【解决方案3】:

    你可以只是一个处理程序:

    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/ 是一种不同的方法:服务器会在准备就绪时通知手机(从而节省一些带宽和性能:))

    【讨论】:

    • 非常感谢。实际上我只是在开发应用程序的客户端。服务器端已经在为 iphone 开发的相同应用程序工作,我必须为 android 使用相同的服务器
    • 我是 android 线程的新手。你在哪里将 runnable 传递给处理程序?
    • 回答@DheeB,回答者在这里没有提到,虽然它应该在像这样的实例化过程中 m_handler = new Handler(m_statusChecker);该解决方案可能不起作用的另一个原因,因为问题清楚地表明将有网络操作“自动从服务器下载所有最新的未读问候语”。但是,尽管您使用的是处理程序,但此处理程序/可运行文件仍在运行在仍然阻塞的 UI 线程中。您需要手动在单独的线程中启动它。
    【解决方案4】:

    通过警报管理器创建服务并安排它不是更有效吗?

    【讨论】:

    • 创建一个服务是一件很痛苦的事,所以要在一个服务上处理很多事情。我宁愿只使用计时器。
    • 服务易于启动和停止。另外,它们不依赖于 UI 线程。所以是的,我会使用服务。
    • @IgorGanapolsky 是的。但是它们也很麻烦,如果它们没有意义并且一切都将通过服务完成,为什么还要为较小的操作创建异步任务、计时器和这些模块?
    • @tony9099 AsyncTask 用于在完成后更新 UI 线程。服务不是。至于 Timer - 它既不存在也不存在 - 它与 AsyncTask 和 Service 之间的比较无关......
    • 我同意伊戈尔的观点。由于在设备旋转时(以及其他时间)如何杀死活动的问题,除非非常仔细地处理(在这些示例中没有),否则 AsyncTask 肯定会崩溃。真正的解决方案是咬紧牙关(是的,我知道,这很痛苦)并提供服务。
    【解决方案5】:

    接受的答案有问题。 使用 TimerTask() 通过处理程序激活异步任务是一个坏主意。在方向更改时,您必须记住取消计时器和处理程序调用。如果不是,它将在每次轮换时一次又一次地调用异步任务。 这将导致应用程序炸毁服务器(如果这是休息 http get 请求)而不是 X 时间 - 最终调用将是每秒实例多次调用。 (因为根据屏幕旋转的次数会有很多定时器)。如果在后台线程中运行的活动和任务很重,它可能会破坏应用程序。 如果您使用计时器,则将其设为类 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();
            }
    
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 1970-01-01
      • 2014-07-24
      • 1970-01-01
      • 1970-01-01
      • 2017-09-06
      • 1970-01-01
      相关资源
      最近更新 更多