在 Android 操作系统中存在着消息队列的操作,用消息队列可以完成主线程和子线程之间的消息传递,要想完成这些线程的消息操作,则需要使用 Looper 、 Message 和 Handler 类,其关系如下:
所以,我们可以发现, Looper 本身提供的是一个消息队列的集合,而每个消息都可以通过 Handler 增加和取出,而操作 Handler 的对象就是主线程( UI Thread )和子线程(利用 Runable 实现的线程操作类)。
说明:
如果把 Looper 比喻成一个正在排队卖票的队伍,那么每个排队的人就是一个 Message ,而一个维护队伍的管理员就相当于是一个 Handler ,管理员负责通知对外的人进到队列之中等待,也负责通知队列中的人离开队伍。
1 、 Android.os.Message 的主要功能是进行消息的封装,同事可以指定消息的操作形式。
No. |
变量或方法 |
类型 |
描述 |
1 |
Public int what |
变量 |
用于定义此 Message 属性何种操作 |
2 |
Public Object obj |
变量 |
用于定义此 Message 传递的信息数据 |
3 |
Public int arg1 |
变量 |
传递一些整型数据时使用,一般很少用 |
4 |
Public int arg2 |
变量 |
传递一些整型数据时使用,一般很少用 |
5 |
Public Handler getTarget() |
普通 |
取得操作此消息的 Handler 对象 |
在 Message 类中,使用最多的是 what 和 obj 两个变量,通过 what 变量指明一个 Message 所携带的是何种信息,而通过 obj 传递信息
2 、 Message 对象封装了所有的消息,而这些消息的操作需要 android.os.Handler 类完成
No. |
方法 |
类型 |
描述 |
1 |
Public Handler() |
构造 |
创建一个新的 Handler 实例 |
2 |
Public Handler(Looper looper) |
构造 |
使用指定的队列创建一个新的 Handler 实例 |
3 |
Public final Message obtainMessage(int what,Object obj) |
普通 |
获得一个 Messge 对象 |
4 |
Public final Message obtainMessage(int what,Int arg1, int arg2,Object obj) |
普通 |
获得一个 Messge 对象 |
5 |
Public void handleMessage(Message msg) |
普通 |
处理消息的方法,子类要覆写此方法 |
6 |
Public final Boolean hasMessages(int what) |
普通 |
判断是否有指定的 Message |
7 |
Public final boolwan hasMessages(int what,Object obj) |
普通 |
判断是否有指定的 Message |
8 |
Public final void removeMessages(int what) |
普通 |
删除指定的 Message |
9 |
Public final void removeMessages(int what,Object obj) |
普通 |
删除指定的 Message |
10 |
Public final Boolean sendEmptyMessage(int what) |
普通 |
发送一个空消息 |
11 |
Public final Boolean sendEmptyAtTime(Int what, long uptimeMills) |
普通 |
在指定的日期时间发送消息 |
12 |
Public final boolean senEmptyMessageDelayed(int what, long delayMills) |
普通 |
等待指定的时间之后发送消息 |
13 |
Public final boolean sendMessage(Message msg) |
普通 |
发送消息 |
可以发现 Handler 所有的相关操作都是在操作 Message 的,可以向队列中添加 Message ,也可以从队列中删除指定的 Message 。
下面我们来通过一个定时更新文本来做一个范例:
Message01_Activity.java
package com.iflytek.demo; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.TextView; public class Message01_Activity extends Activity { private TextView info = null; private static int count = 0; // 表示更新后的记录 private static final int SET = 1; // 操作的what状态 private Handler myHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { // 判断操作的消息类型 case SET: // 更新组件 Message01_Activity.this.info.setText("XDWANG - " + count++); } } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.info = (TextView) super.findViewById(R.id.info); // 取得组件 // 通过任务管理器进行任务调度 Timer timer = new Timer(); //每一秒调度一次 timer.schedule(new MyTask(), 0, 1000); } /** * * @author xdwang * * @create 2012-10-27下午08:11:25 * * @email:[email protected] * * @description 定时调度类 * */ private class MyTask extends TimerTask { @Override public void run() { Message msg = new Message(); // 设置更新 msg.what = SET; // 操作的标记 Message01_Activity.this.myHandler.sendMessage(msg); // 发送消息 } } }
从上面代码我们可以发现是在 Handler 中处理组件内容的,那么为什么不在任务调度器里完成呢?因为子线程不能更新主线程中各个组件的状态。即子线程无法更新组件,那么现在只能采用与之前一样的方式,在子线程之中返回要要操作的消息,而后在主线程之中利用 Handler 处理这些消息,从而实现线程的操作 。
3 、在使用 Handler 处理 Message 时,都需要依靠一个 Looper 通道完成,当用户取得一个 Handler 对象时,实际上都是通过 Looper 完成的,在一个 Activity 类中,会自动帮助用户启动 Looper 对象,而若是在一个用户自定义的类中,则需要手动调用 Looper 类的若干方法,之后才可以正常的启动 Looper 对象,其方法如下:
No. |
方法名称 |
描述 |
1 |
Public static final synchronized Looper getMainLooper() |
取得主线程 |
2 |
Public static final myLooper() |
返回当前的线程 |
3 |
Public static final void prepare() |
初始化 Looper 对象 |
4 |
Public static final void prepareMainLooper() |
初始化主线程 Looper 对象 |
5 |
Public void quit() |
消息队列结束时调用 |
6 |
Public static final void loop() |
启动消息队列 |
下面我们来利用 Looper 做一个范例
Message02_Activity.java:
package com.iflytek.demo; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class Message02_Activity extends Activity { private TextView info = null; private static final int SET = 1; // 操作的what状态 private Button but = null; // 操作按钮 /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.info = (TextView) super.findViewById(R.id.info); // 取得组件 this.but = (Button) super.findViewById(R.id.but); // 取得组件 this.but.setOnClickListener(new OnClickListenerImpl()); // 单击事件 } private class OnClickListenerImpl implements OnClickListener { @Override public void onClick(View v) { Looper looper = Looper.myLooper(); MyHandler myHandler = new MyHandler(looper); myHandler.removeMessages(0); // 表示清空所有的消息 String data = "xdwangiflytek.iteye.com"; // 要传递的消息 Message msg = myHandler.obtainMessage(SET, 1, 1, data); // 创建消息 myHandler.sendMessage(msg); // 发送消息 } } private class MyHandler extends Handler { public MyHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch (msg.what) { // 判断操作的消息类型 case SET: // 更新组件 Message02_Activity.this.info.setText(msg.obj.toString()); // 设置文本组件 } } } }
这里如果我们不设置Looper,如下:
private class OnClickListenerImpl implements OnClickListener { @Override public void onClick(View v) { MyHandler myHandler = new MyHandler(); myHandler.removeMessages(0); // 表示清空所有的消息 String data = "xdwangiflytek.iteye.com"; // 要传递的消息 Message msg = myHandler.obtainMessage(SET, 1, 1, data); // 创建消息 myHandler.sendMessage(msg); // 发送消息 } } private class MyHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { // 判断操作的消息类型 case SET: // 更新组件 Message03_Activity.this.info.setText(msg.obj.toString()); // 设置文本组件 } } }
其效果是一样的。
下面我们来完成一个主线程与子线程之间的数据交换
主线程向子线程发送数据,然后子线程再向主线程发送数据:
Thread01_Activity.java
package com.iflytek.demo; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class Thread02_Activity extends Activity { public static final int SETMAIN = 1; // 设置一个what标记 public static final int SETCHILD = 2; // 设置what的标记] private Handler mainHandler, childHandler; private TextView msg = null; private Button but; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.msg = (TextView) super.findViewById(R.id.msg); this.but = (Button) super.findViewById(R.id.but); this.mainHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case SETMAIN: Thread02_Activity.this.msg.setText("主线程接收数据:" + msg.obj.toString()); break; } } }; new Thread(new ChildThread(), "Child Thread").start(); this.but.setOnClickListener(new OnClickListenerImpl()); } private class OnClickListenerImpl implements OnClickListener { @Override public void onClick(View v) { // 是将信息发送到子线程之中 //因为线程的状态不固定,所以这里需要一个判断 if (Thread02_Activity.this.childHandler != null) { Message childMsg = Thread02_Activity.this.childHandler .obtainMessage(); // 创建消息 childMsg.obj = Thread02_Activity.this.mainHandler.getLooper() .getThread().getName() + " --> Hello XDWANG ."; childMsg.what = SETCHILD; Thread02_Activity.this.childHandler.sendMessage(childMsg); } } } /** * * @author xdwang * * @create 2012-10-27下午08:31:25 * * @email:[email protected] * * @description 子线程的线程类 * */ class ChildThread implements Runnable { @Override public void run() { Looper.prepare();//准备好一个Looper对象 Thread02_Activity.this.childHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case SETCHILD: // 子线程接收主线程发送来的消息 System.out.println("*** Main Child Message : " + msg.obj); // 输出数据 Message toMain = Thread02_Activity.this.mainHandler .obtainMessage(); toMain.obj = "\n\n[B]这是子线程发送给主线程的信息:" + super.getLooper().getThread().getName(); toMain.what = SETMAIN; Thread02_Activity.this.mainHandler.sendMessage(toMain); break; } } }; Looper.loop(); // 创建消息队列 } } @Override protected void onDestroy() { super.onDestroy(); //结束子线程的操作队列 Thread02_Activity.this.childHandler.getLooper().quit(); } }
打印:
10-27 21:04:07.165: I/System.out(4449): *** Main Child Message : main --> Hello XDWANG .
下面我们再以一个时钟显示来看看
前面我们说过时钟的组件,但是当时没有时间的说明,下面我们来写一个这样的时钟
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <AnalogClock android:id="@+id/myAnalogClock" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/info" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </LinearLayout>
AnalogClockThread_Activity.java
package com.iflytek.demo; import java.text.SimpleDateFormat; import java.util.Date; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.TextView; public class AnalogClockThread_Activity extends Activity { private TextView info = null; private static final int SET = 1; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case SET: AnalogClockThread_Activity.this.info.setText("当前时间为:" + msg.obj.toString()); break; } } }; private class ClockThread implements Runnable { @Override public void run() { while (true) { // 一直更新 Message msg = AnalogClockThread_Activity.this.handler .obtainMessage(AnalogClockThread_Activity.SET, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(new Date())); AnalogClockThread_Activity.this.handler.sendMessage(msg); try { Thread.sleep(1000); } catch (InterruptedException e) { } } } } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.info = (TextView) super.findViewById(R.id.info); new Thread(new ClockThread()).start(); } }
进度条组件:ProgressBar
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ProgressBar android:id="@+id/myprobarA" android:visibility="gone" style="?android:attr/progressBarStyle" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/myprobarB" android:visibility="gone" style="?android:attr/progressBarStyleHorizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/myprobarC" android:visibility="gone" style="?android:attr/progressBarStyleHorizontal" android:max="120" android:progress="0" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/myprobarD" android:visibility="gone" style="?android:attr/progressBarStyleLarge" android:max="120" android:progress="50" android:secondaryProgress="70" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/myprobarE" android:visibility="gone" style="?android:attr/progressBarStyleSmall" android:max="120" android:progress="50" android:secondaryProgress="70" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/mybut" android:text="显示进度条" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
属性说明:
android:visibility="gone":隐藏进度条 android:max="120":设置最大进度 android:progress="50":设置当前进度 android:secondaryProgress="70":设置第二进度条当前值
ProgressBar_Activity.java:
package com.iflytek.demo; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; public class ProgressBar_Activity extends Activity { private static final int STOP = 1; private static final int CONTINUE = 2; private ProgressBar myprobarA, myprobarB, myprobarC, myprobarD, myprobarE; private Button mybut; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.myprobarA = (ProgressBar) super.findViewById(R.id.myprobarA); this.myprobarB = (ProgressBar) super.findViewById(R.id.myprobarB); this.myprobarC = (ProgressBar) super.findViewById(R.id.myprobarC); this.myprobarD = (ProgressBar) super.findViewById(R.id.myprobarD); this.myprobarE = (ProgressBar) super.findViewById(R.id.myprobarE); this.mybut = (Button) super.findViewById(R.id.mybut); this.myprobarA.setIndeterminate(false); // 不确定模式 this.myprobarB.setIndeterminate(false); // 不确定模式 this.myprobarC.setIndeterminate(true); // 确定模式 this.myprobarD.setIndeterminate(false); // 不确定模式 this.myprobarE.setIndeterminate(false); // 不确定模式 this.mybut.setOnClickListener(new OnClickListenerImpl()); // 单击事件 } private class OnClickListenerImpl implements OnClickListener { @Override public void onClick(View v) { ProgressBar_Activity.this.myprobarB.setSecondaryProgress(50); ProgressBar_Activity.this.myprobarA.setVisibility(View.VISIBLE); ProgressBar_Activity.this.myprobarB.setVisibility(View.VISIBLE); ProgressBar_Activity.this.myprobarC.setVisibility(View.VISIBLE); ProgressBar_Activity.this.myprobarD.setVisibility(View.VISIBLE); ProgressBar_Activity.this.myprobarE.setVisibility(View.VISIBLE); ProgressBar_Activity.this.myprobarA.setMax(120); ProgressBar_Activity.this.myprobarB.setMax(120); ProgressBar_Activity.this.myprobarA.setProgress(0); ProgressBar_Activity.this.myprobarB.setProgress(0); new Thread(new Runnable() { @Override public void run() { int count = 0; // 保存当前进度的值 for (int i = 0; i < 10; i++) { count = (i + 1) * 20; // 进度的增长快一些 try {// 每次操作延迟500MS Thread.sleep(500); } catch (InterruptedException e) { } if (i == 6) { // 正好增长到120 Message m = new Message(); m.what = ProgressBar_Activity.STOP; // 停止 ProgressBar_Activity.this.myMessageHandler .sendMessage(m);// 停止 } else { Message m = new Message(); m.what = ProgressBar_Activity.CONTINUE; m.arg1 = count; ProgressBar_Activity.this.myMessageHandler .sendMessage(m); } } } }).start(); } } private Handler myMessageHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case ProgressBar_Activity.STOP: ProgressBar_Activity.this.myprobarA.setVisibility(View.GONE); ProgressBar_Activity.this.myprobarB.setVisibility(View.GONE); ProgressBar_Activity.this.myprobarC.setVisibility(View.GONE); ProgressBar_Activity.this.myprobarD.setVisibility(View.GONE); ProgressBar_Activity.this.myprobarE.setVisibility(View.GONE); Thread.currentThread().interrupt(); break; case ProgressBar_Activity.CONTINUE: if (!Thread.currentThread().isInterrupted()) { // 线程没有中断 ProgressBar_Activity.this.myprobarA.setProgress(msg.arg1); ProgressBar_Activity.this.myprobarB.setProgress(msg.arg1); ProgressBar_Activity.this.myprobarC.setProgress(msg.arg1); ProgressBar_Activity.this.myprobarD.setProgress(msg.arg1); ProgressBar_Activity.this.myprobarE.setProgress(msg.arg1); } break; } } }; }
效果图:
异步处理工具类: AsyncTask
上面我们了解了主线程与子线程之间的通信主要依靠 Handler 完成,但子线程无法直接对主线程的组件进行更新,而如果所有的开发都分别定义若干个子线程的操作对象,则这多个对象同时对主线程操作就会非常满分,为了解决这个问题,在 Android1.5 之后专门提供了一个 andorid.os.AsyncTask (非同步任务)类,可以通过此类完成非阻塞的操作类,该类的功能与 Handler 类似,可以在后台进行操作之后更新主线程的 UI ,但其使用比 Handler 要容易的多。
通过此类的定义可以发现,在 AsyncTask 类中要通过泛型指定 3 个参数,作用分别是:
Params :启动时需要的参数类型,如每次操作的休眠时间为 Integer ;
Progress :后台执行任务的百分比,如进度条需要传递的是 Integer ;
Result :后台执行完毕之后返回的信息,如完成数据信息显示传递的是 String ;
常用方法:
No. |
方法 |
描述 |
1 |
Public final Boolean cancel(Boolean mayInterruptIfRunning)) |
指定是否取消当前线程操作 |
2 |
Public final AsyncTask<Params,Progress,Result> execute(Params… params) |
执行 AsyncTask 操作 |
3 |
Public final Boolean isCancelled() |
判断子线程是否被取消 |
4 |
Protected final void publishProgress( Progress… values) |
更新线程进度 |
5 |
Protected abstract Result doInBackground( Params… params) |
在后台完成任务执行,可以调用 publishProgress() 方法更新线程进度 |
6 |
Protectes void onProgressUpdate( Progress… values) |
在主线程中执行,用于显示任务的进度 |
7 |
Protectes void onPreExecute() |
在主线程中执行,在 doInBackground() 之前执行 |
8 |
Protectes void onPostExecute(Result result) |
在主线程中执行,方法参数为任务执行结果 |
9 |
Protectes void onCancelled() |
主线程中执行,在 cancel() 方法之后执行 |
下面我们通过 AsyncTask 来实现进度条
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ProgressBar android:id="@+id/bar" android:layout_width="fill_parent" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal"/> <TextView android:id="@+id/info" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </LinearLayout>
AsyncTask_Activity.java
package com.iflytek.demo; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.widget.ProgressBar; import android.widget.TextView; public class AsyncTask_Activity extends Activity { private ProgressBar progressBar = null; private TextView info = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.progressBar = (ProgressBar) super.findViewById(R.id.bar); this.info = (TextView) super.findViewById(R.id.info); ChildUpdate child = new ChildUpdate(); //每次休眠100毫秒 child.execute(100); } // 每次处理后台进度的类型是Integer、更新之后的数值Integer,最后的结果返回的是字符串 private class ChildUpdate extends AsyncTask<Integer, Integer, String> { @Override protected void onPostExecute(String result) { AsyncTask_Activity.this.info.setText(result); } @Override protected void onProgressUpdate(Integer... values) { // 每次更新之后的内容 AsyncTask_Activity.this.info.setText("当前的进度值是:" + String.valueOf(values[0])); } @Override protected String doInBackground(Integer... params) { // 每次的进度处理,可以更新UI组件 for (int x = 0; x < 100; x++) { AsyncTask_Activity.this.progressBar.setProgress(x); // 设置进度 this.publishProgress(x); // 更新,调用更新操作 try {// 延迟的操作由外部决定 Thread.sleep(params[0]); } catch (InterruptedException e) { } } return "执行完毕"; } } }
从上我们可以发现这个组件完全融合了Handler和Message的功能所完成。
下面我们再做一个简单的文件管理器
main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
file_list.xml:
<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TableRow> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> </TableLayout>
AsyncTaskListFile_Activity.java
package com.iflytek.demo; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.SimpleAdapter; public class AsyncTaskListFile_Activity extends Activity { private List<Map<String, Object>> allFileItems = new ArrayList<Map<String, Object>>(); private SimpleAdapter simpleAdapter = null; private ListView listView = null; private ListFileThread listFileThread = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.listView = (ListView) super.findViewById(R.id.list); File filePath = new File(java.io.File.separator); // 从根目录下开始列出 this.listView.setOnItemClickListener(new OnItemClickListenerImpl()); this.listFileThread = new ListFileThread(); this.listFileThread.execute(filePath); } private class OnItemClickListenerImpl implements OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { File currFile = (File) AsyncTaskListFile_Activity.this.allFileItems .get(position).get("name"); if (currFile.isDirectory()) { // 当前是一个目录 AsyncTaskListFile_Activity.this.allFileItems = new ArrayList<Map<String, Object>>(); AsyncTaskListFile_Activity.this.listFileThread = new ListFileThread(); AsyncTaskListFile_Activity.this.listFileThread.execute(currFile); } } } private class ListFileThread extends AsyncTask<File, File, String> { @Override protected void onProgressUpdate(File... values) { Map<String, Object> fileItem = new HashMap<String, Object>(); // 表示可以返回 if (values[0].isDirectory()) { fileItem.put("img", R.drawable.folder_close); // 文件夹 } else { // 是文件 fileItem.put("img", R.drawable.file); } fileItem.put("name", values[0]); AsyncTaskListFile_Activity.this.allFileItems.add(fileItem); AsyncTaskListFile_Activity.this.simpleAdapter = new SimpleAdapter( AsyncTaskListFile_Activity.this, AsyncTaskListFile_Activity.this.allFileItems, R.layout.file_list, new String[] { "img", "name" }, new int[] { R.id.img, R.id.name }); AsyncTaskListFile_Activity.this.listView .setAdapter(AsyncTaskListFile_Activity.this.simpleAdapter); } @Override protected String doInBackground(File... params) { if (!params[0].getPath().equals(java.io.File.separator)) { // 不是根目录 Map<String, Object> fileItem = new HashMap<String, Object>(); // 表示可以返回 fileItem.put("img", R.drawable.folder_open); // 可以返回 fileItem.put("name", params[0].getParentFile()); AsyncTaskListFile_Activity.this.allFileItems.add(fileItem); } if (params[0].isDirectory()) { // 是文件夹 File tempFile[] = params[0].listFiles(); if (tempFile != null) { for (int x = 0; x < tempFile.length; x++) { this.publishProgress(tempFile[x]); } } } return "文件已列出"; } } }
效果图: