2015-10-04 75 views
0

場景:Asynctask和隊列OR延遲執行

用戶有一個項目列表,比方說10個項目。每個項目都有一個操作按鈕,它調用一個可以進行Web通話的AsyncTask。當調用時,該項目任務的執行過程中會顯示一個微調

問題:

一些用戶的濫用這一點,並快速按下多個操作按鈕,quicklt此起彼伏,執行網絡電話太頻繁。所以我希望能夠以某種方式,在執行之間延遲2秒執行每個AsyncTasks。如果可能的話,我不想從AsyncTask切換到別的東西。因此,基本上,如果有按下3的操作按鈕時,執行應該是:

- >操作1 - > 2秒延時 - >操作2 - > 2秒延時 - >操作3 - > .. ..

在Android中這樣做的最好方法是什麼?

LE:

我剛剛意識到的東西,用於執行我的任務我跑到下面的代碼:

myTask = new MyTask(); 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    myTask.execute(); 
} 

嗯,我已經使用了很多的時間這個代碼現在,知道在蜂窩之後,如果不使用Executor,任務不會並行執行。所以看起來只需要做一個簡單的myTask.execute()並添加一個Thread.sleep()就可以讓我的AsyncTasks按照預期一個接一個地執行。

回答

1

您需要維護一個需要執行的操作列表。 單擊按鈕添加列表中的任務,調用一個方法,檢查任務列表並執行它,如果沒有其他任務正在運行..

在onPostExecute方法調用相同的方法來檢查是否有其他任務/操作需要執行..

它可能不是你所需要的完整代碼...但可以給你一些想法..

public class TestActivity extends AppCompatActivity { 

    private static boolean isTaskRunning =false; 
    static ArrayList<CustomTask> customTaskList = new ArrayList(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_test); 
    } 

    public void onBtnClick(View view) 
    { 
     // create custom task with required values and actions 
     CustomTask customTask = new CustomTask(); 
     customTaskList.add(customTask);   

     checkAndExecuteTask(); 
    } 


    private static void checkAndExecuteTask() 
    { 
     //checks if there is any task in the list and is there any other   running task 
     if(customTaskList.size()>0 && !isTaskRunning) { 
      new MyAsync(customTaskList.get(0)).execute(); 
     } 
    } 

    static class MyAsync extends AsyncTask<Void,Void,Void> 
    { 
     CustomTask currentCustomTask; 

     public MyAsync(CustomTask customTask) 
     { 
      currentCustomTask = customTask; 
     } 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
      isTaskRunning= true; 
     } 

     @Override 
     protected Void doInBackground(Void... voids) { 

      // do your stuff 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void aVoid) { 
      super.onPostExecute(aVoid); 
      customTaskList.remove(currentCustomTask); 
      isTaskRunning =false; 
      checkAndExecuteTask(); // task is completed so check for another  task and execute (if any). 
     } 
    } 

    class CustomTask 
    { 
     // create class with required fields and method 
    } 
} 
+0

也許我失去了一些東西,但如果我按接連3個的操作按鍵之一,在過去2個項目將在幾乎同時進行,因爲有將是最後2個線程的睡眠時間爲2秒,幾毫秒讓我按下按鈕... – Alin

+0

如何使用進度對話框?當任務正在運行時顯示它..當進度對話框在屏幕上可見時..用戶將無法觸及其他操作按鈕...當任務完成時..關閉onPostExecute方法中的對話..這樣將只有一個任務將運行.. – Tarun

+0

另一種選擇是維護需要執行的操作的列表....在點擊按鈕上添加動作到列表..並調用一個方法來檢查是否已經有一個正在運行的任務。它沒有任何運行..它執行數組列表中的操作.....在後執行方法從數組列表中刪除操作..並調用相同的方法來檢查是否有任何其他操作需要被執行.... – Tarun

1

有許多的你可以在android中做到這一點。 一種方法是使用handler

你需要做的是,創建一個單獨的線程並在其中運行handler.postDelayed。

private void startWebCall() { 

    Thread thread = new Thread() { 
     public void run() { 
      Looper.prepare(); 

      final Handler handler = new Handler(); 
      handler.postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        // Do your web calls here 
        handler.removeCallbacks(this); 
        Looper.myLooper().quit(); 
       } 
      }, 2000); 

      Looper.loop(); 
     } 
    }; 
    thread.start(); 
} 

無論何時用戶單擊某個項目,都應該調用上述方法。

,我能想到的另一種方法是使用IntentService

的IntentService是用於在後臺執行異步任務的服務。它維護着它需要做的任務的隊列。與上述方法不同的是,它按順序執行這些任務。因此,當您向網絡電話發出請求時,它會將它們排隊,進行第一個呼叫,然後在完成後它將進行第二個呼叫。所以不同的網絡電話將不會並行執行。它們將按順序執行,但執行的是另一個線程。它也是一種服務,所以它可以在後臺運行,即用戶關閉應用程序。

This是一個很好的教程,以開始使用IntentService。

應該避免使用AsyncTaks,除非需要做的工作非常簡單。 This博客解釋了它的陷阱。

+0

謝謝你的回答,它確實看起來像它做我需要的東西,但我想使用現有的AsyncTask實現。目前不需要IntentService,因爲操作很簡單,並且需要不斷更新接口。 – Alin

0

該算法將做按您的要求:

ButtonA.onclick() { 
    final Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() { 
     @Override public void run() { 
      MytaskA.execute(); 
     } 
    }, 2000); 
} 

ButtonB.onclick() { 
    final Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() { 
     @Override public void run() { 
      MytaskB.execute(); 
     } 
    }, 2000); 

} 
ButtonC.onclick() { 
    final Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() { 
     @Override public void run() { 
      MytaskC.execute(); 
     } 
    }, 2000); 

}