对于一个合格的安卓应用来讲,流畅的界面操做是必不可少的。可是实际的应用会有很多的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); } }