`

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:xdwangiflytek@gmail.com
	 * 
	 * @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:xdwangiflytek@gmail.com
	 * 
	 * @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 "文件已列出";
		}
	}
}
 

效果图:

 

 

 

  • 大小: 15.6 KB
  • 大小: 13.9 KB
  • 大小: 18.9 KB
分享到:
评论

相关推荐

    android支持包:android-support-v4

    `android-support-v4`库中的BroadcastReceiver和PendingIntent类提供了与原生API相匹配的功能,使得开发者能在低版本的Android上使用这些组件进行事件监听和跨组件通信。 **Preference支持** Preference类是用于...

    Android串口通信开发Google官方android-serialport-api源码

    在Android平台上进行串口通信开发是一项重要的技能,尤其是在嵌入式设备、物联网(IoT)应用或者需要与硬件设备交互的场景中。Google官方提供的`android-serialport-api`库就是为了方便开发者实现这一功能。这个库允许...

    asmack-android-16-source-beem.zip

    开发者可以通过研究这些源代码来学习如何在Android平台上实现XMPP协议,以及Beem是如何利用Asmack实现其复杂的通信功能的。这不仅对理解Asmack的工作原理有益,也有助于自定义或扩展Beem应用程序。

    Android-nRF-Toolbox-master 源码

    1. `app`目录:这是Android应用的主要代码库,包含Activity、Service、BroadcastReceiver等核心组件。 2. `libs`目录:存放了项目所需的第三方库,如蓝牙通信库、固件升级库等。 3. `res`目录:包含了应用的资源文件...

    spring-android-core-1.0.0.RELEASE-sources.jar

    4. **EventBus**:Spring for Android提供了一个事件总线,允许组件之间进行解耦的通信。这种设计模式可以帮助我们避免Activity和Fragment之间的直接调用,提升应用的结构清晰度。 5. **Android Context管理**:...

    android-sdk-macosx.zip

    2. **Android Platform Tools**:这是SDK中的一个重要组成部分,包括adb(Android Debug Bridge)、fastboot和其他用于设备通信的工具。adb是开发者与Android设备交互的主要手段,可用于安装应用、调试、传输文件等...

    android-sdk-windows-1.5_r3.zip-tools

    4. **Eclipse ADT Plugin**: 虽然在描述中未提及,但考虑到1.5_r3的年代,当时Android开发主要依赖Eclipse IDE,ADT(Android Developer Tools)插件是必不可少的,它允许开发者在Eclipse中创建、编辑、调试和发布...

    Android-nRF-Toolbox-master

    总结来说,"Android-nRF-Toolbox-master"不仅是一个实用的开发工具,更是学习和研究BLE通信、Android应用开发和Nordic芯片应用的宝贵资源。通过深入研究源代码,开发者可以掌握BLE通信的核心技术,为开发自己的BLE...

    android sdk android-34

    1. **平台工具**:这包括了如`adb`(Android Debug Bridge)用于与设备通信,`fastboot`用于固件更新,以及`zipalign`用于优化APK文件的工具。 2. **构建工具**:例如`build-tools`目录下的`gradle`插件,用于自动...

    android-sdk-NDK21.0.rar

    2. **Android SDK Platform Tools**:包括adb(Android Debug Bridge)、fastboot等,用于设备通信、安装应用、数据备份等。 3. **Android SDK Build-Tools**:用于构建APK,包含aapt(Android Asset Packaging Tool...

    android-sdk-windows.zip

    Android SDK(Software Development Kit)是开发Android应用必不可少的工具集,它包含了编写、调试和运行Android应用程序所需的各种组件。在Windows环境下,这个压缩包“android-sdk-windows.zip”提供了全面的SDK...

    Android-Tool-Log—Android轻量级简单易用的日志组件

    《Android-Tool-Log:Android轻量级日志组件详解》 在Android应用开发中,日志记录是一项不可或缺的功能,它能帮助开发者调试程序、排查问题。本文将深入探讨名为"Android-Tool-Log"的轻量级日志组件,其特点在于...

    Android-netty和socket通信的demo

    本示例“Android-netty和socket通信的demo”将展示如何在Android平台上利用Netty进行网络通信,与传统的Socket编程相结合,实现更加灵活和高效的通信机制。 首先,理解Netty的基本概念是非常重要的。Netty是一个...

    android-support-v4~v17

    在Android开发中,`android-support-v4`库是一个至关重要的组件,它提供了对早期Android版本的API兼容性支持。这个库包含了大量实用的功能,使得开发者能够编写与Android 2.1(API级别7)及更高版本兼容的应用程序,...

    Android学习笔记--Binder

    Binder是Android系统中的核心组件,它是Android系统实现进程间通信(IPC,Inter-Process Communication)的主要方式。Binder机制允许不同进程的组件之间进行数据交换和功能调用,就像它们在同一进程中一样,实现了...

    android-sdk-sources-android-21.rar

    - `system/core` 存放了 Android 系统的核心组件,如 init 进程、内核接口、JNI 头文件等。 3. **Android 源码学习路径**: - 首先,开发者应熟悉 Android 开发的基本概念,如 Activity 生命周期、Intent 机制等...

    Android-FTDI-UART-Sample-master1.zip_Android串口usb_android_usb_串口

    在Android平台上进行串口通信,尤其是在与USB设备如FT232芯片进行交互时,开发者通常需要编写特定的驱动程序和应用程序来实现数据传输。这个名为"Android-FTDI-UART-Sample-master1.zip"的压缩包提供了一个示例项目...

    android-support-v4源码

    在本文中,我们将深入探讨android-support-v4源码,了解其内部机制和关键组件,以期为开发者提供更全面的理解。 首先,我们来看一下`android-support-v4-master`这一压缩包中的主要内容。这通常是Android项目的一个...

    android-platform-tools-28.0.1

    "android-platform-tools-28.0.1"是Android开发者必备的一个组件,它属于Android Software Development Kit (SDK) 的一部分,主要包含了用于Android应用开发和设备管理的一系列命令行工具。这个版本对应的是Android ...

    android-nrf-toolbox

    《Android-nRF-Toolbox:探索蓝牙低功耗(BLE)在Android系统中的应用》 在移动设备领域,蓝牙低功耗(Bluetooth Low Energy,简称BLE或Bluetooth LE)技术已经广泛应用,尤其在物联网(IoT)场景下,其低功耗、高...

Global site tag (gtag.js) - Google Analytics