對於一個合格的安卓應用來講,流暢的界面操做是必不可少的。可是實際的應用會有很多的IO操做,例如更新數據庫,訪問本地文件或者網絡,這些都須要消耗很多時間。若是界面線程和這些IO混合在一塊兒,就會拖慢界面。這個時候,就須要將這些耗時的工做剝離,轉由其餘的異步線程來處理。java
java 程序是一步一步的執行的,好比有三個任務,task1, task2,task3,默認狀況下,這三個任務按順序執行。android
task1.run(); task2.run(); task3.run();
task2必須等待task1執行完畢後才能開始,task3同理。假設task1是一個IO類的任務,好比訪問遠端API,那麼在請求發出和收到回覆之間的時間, cpu是空閒的。這就形成了資源的浪費。git
有一種辦法,可讓這段空閒的時間作其餘的事情,這就是異步線程。其實也就是再啓動一個線程, java 中能夠用 thread類 或者 實現 runnable接口來實現一個線程。android 中沒必要這麼作,sdk 提供了更方便的實現。那就是 AsyncTask。github
AsyncTask,即異步任務。只須要繼承並重寫幾個生命週期方法,就能夠實現一個異步線程。數據庫
AsyncTask 的要點有兩部分apache
生命週期方法網絡
有三個重要的方法, 按照執行的時機前後,依次是 onPostExecute, doInBackground, onPostExecute,分別表異步任務執行前的工做,待執行任務,和執行結束後的工做異步
onProgressUpdate 和 publishProgress 支持自定義進度。在 doInBackground 中對具體業務進度進行分析後,得出一個進度值(類型自定),經過 publishProgress 發佈進度,onProgressUpdate
獲得執行(參數就是剛纔發佈的進度值)。async
更新UIide
大部分時候,task 進行中和結束後會更新UI,好比進度條,多是更新一個結果列表(listView)。那麼,如何更新呢? 在 activity 中天然是能夠findViewById,而後更新。可是 task 中沒有這樣的context。目前知道的辦法是,建立 task 的時候,將這個 listView 做爲構造方法的參數傳遞進去,而後就能夠將它存儲爲 task 的成員變量,進而在任務結束後操做。
下面的類用於遍歷獲取目錄中全部文件的數目
//定義類的時候指定了線程相關的3個參數的類型,分別是啓動參數,進度參數,返回值 //File 是執行execute方法時的參數類型, 第一個 Integer 是進度的參數類型,第二個 Integer 是後臺線程返回數據的類型,即 doInBackground 的返回值類型 public class FileCrawler extends AsyncTask<File, Integer, Integer> { @Override // params 就是下面執行execute的時候傳入的參數 directoryPath protected Long doInBackground(File ...params) { //這裏執行一些耗時的代碼 } @Override //categories 是 doInBackground 返回的結果 protected void onPostExecute(Integer sum){ //異步線程結束後,執行這裏。一般能夠在這裏更新UI } }
能夠直接在activity的onCreate中調用
new FileCrawler(getBaseContext()).execute(directoryPath);
文件遍歷是一個比較複雜的問題,尤爲對於大量的文件,直接用遞歸的話可能會出現內存溢出問題。apache 的 common io 是一個不錯的工具包,有不少io相關的工具類。這裏使用其中的 FileUtils來遍歷文件。
FileCrawler.java
/** * Created by wangpi on 6/30/2016. */ public class FileCrawler extends AsyncTask<File, Integer, Integer>{ private TextView view; public FileCrawler(TextView view ){ this.view = view; } @Override protected Integer doInBackground(File... folders) { Collection<File> files = null; for(File folder : folders){ if(folder.exists() && folder.isDirectory()){ if(files == null) { files = FileUtils.listFiles(folder, null, true); }else{ files.addAll(FileUtils.listFiles(folder, null, true)); } } } if(files != null){ return files.size(); }else{ return 0; } } @Override protected void onPostExecute(Integer sum){ view.setText("File amout : " + sum); } }
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); File[] folders = {Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)}; new FileCrawler((TextView)findViewById(R.id.info)).execute(folders); } }