Android学习10-----Android组件通信 (4) 消息机制
在 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 "文件已列出";
}
}
}
效果图: