step1:新建项目DataAsyncLoad,如下图所示
step2:设置应用的UI界面
a.应用的主界面 main.xml
[html]
<?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:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/listView"
/>
</LinearLayout>
<?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:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/listView"
/>
</LinearLayout>
b.每个ListView的界面 listview_item.xml
[html]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:layout_width="42dp"
android:layout_height="42dp"
android:id="@+id/imageView"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#FFFFFF"
android:id="@+id/textView"
/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:layout_width="42dp"
android:layout_height="42dp"
android:id="@+id/imageView"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#FFFFFF"
android:id="@+id/textView"
/>
</LinearLayout>
step3:写一些辅助类 cn.roco.data.utilsMD5.java
[java]
package cn.roco.data.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
public static String getMD5(String content) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(content.getBytes());
return getHashString(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
private static String getHashString(MessageDigest digest) {
StringBuilder builder = new StringBuilder();
for (byte b : digest.digest()) {
builder.append(Integer.toHexString((b >> 4) & 0xf));
builder.append(Integer.toHexString(b & 0xf));
}
return builder.toString();
}
}
package cn.roco.data.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
public static String getMD5(String content) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(content.getBytes());
return getHashString(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
private static String getHashString(MessageDigest digest) {
StringBuilder builder = new StringBuilder();
for (byte b : digest.digest()) {
builder.append(Integer.toHexString((b >> 4) & 0xf));
builder.append(Integer.toHexString(b & 0xf));
}
return builder.toString();
}
}
step4:写应用使用的JavaBean cn.roco.data.domain.Contact.java
[java]
package cn.roco.data.domain;
public class Contact {
private int id;
private String name;
private String image;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Contact(int id, String name, String image) {
this.id = id;
this.name = name;
this.image = image;
}
public Contact(){
}
}
package cn.roco.data.domain;
public class Contact {
private int id;
private String name;
private String image;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Contact(int id, String name, String image) {
this.id = id;
this.name = name;
this.image = image;
}
public Contact(){
}
}
step5:写一个应用的service层,用于对javabean进行操作 cn.roco.data.service.ContactService.java
[java]
package cn.roco.data.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import android.net.Uri;
import android.util.Xml;
import cn.roco.data.domain.Contact;
import cn.roco.data.utils.MD5;
public class ContactService {
/**
* 获取联系人数据
*
* @return
* @throws Exception
*/
public static List<Contact> getContacts() throws Exception {
String path = "http://192.168.1.100:8080/Hello/contact.xml";
HttpURLConnection connection = (HttpURLConnection) new URL(path)
.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
if (connection.getResponseCode() == 200) {
return parseXML(connection.getInputStream());
}
return null;
}
/**转化XML获取数据
* 服务器端的xml文件如下。。。。。。
* <?xml version="1.0" encoding="UTF-8"?>
<contacts>
<contact id="1">
<name>Roco_1</name>
<image src=http://up.2cto.com/2013/0417/20130417032102399.png" />
</contact>
.......
</contacts>*/
private static List<Contact> parseXML(InputStream inputStream)
throws Exception {
List<Contact> contacts = new ArrayList<Contact>();
Contact contact = null;
XmlPullParser pullParser = Xml.newPullParser();
pullParser.setInput(inputStream, "UTF-8");
int event = pullParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
switch (event) {
case XmlPullParser.START_TAG:
if ("contact".equals(pullParser.getName())) {
contact = new Contact();
contact.setId(new Integer(pullParser.getAttributeValue(0)));
} else if ("name".equals(pullParser.getName())) {
contact.setName(pullParser.nextText());
} else if ("image".equals(pullParser.getName())) {
contact.setImage(pullParser.getAttributeValue(0));
}
break;
case XmlPullParser.END_TAG:
if ("contact".equals(pullParser.getName())) {
contacts.add(contact);
contact = null;
}
}
event = pullParser.next();
}
return contacts;
}
/**
* 获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来
*
* @param path
* 图片路径
* @return
*/
public static Uri getImage(String imagePath, File cacheDir)
throws Exception {
//缓存文件的文件名用MD5进行加密
File localFile = new File(cacheDir, MD5.getMD5(imagePath)
+ imagePath.substring(imagePath.lastIndexOf(".")));
if (localFile.exists()) {
return Uri.fromFile(localFile);
} else {
HttpURLConnection connection = (HttpURLConnection) new URL(
imagePath).openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
//将文件缓存起来
if (connection.getResponseCode() == 200) {
FileOutputStream outputStream = new FileOutputStream(localFile);
InputStream inputStream = connection.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
inputStream.close();
outputStream.close();
return Uri.fromFile(localFile);
}
}
return null;
}
}
package cn.roco.data.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import android.net.Uri;
import android.util.Xml;
import cn.roco.data.domain.Contact;
import cn.roco.data.utils.MD5;
public class ContactService {
/**
* 获取联系人数据
*
* @return
* @throws Exception
*/
public static List<Contact> getContacts() throws Exception {
String path = "http://192.168.1.100:8080/Hello/contact.xml";
HttpURLConnection connection = (HttpURLConnection) new URL(path)
.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
if (connection.getResponseCode() == 200) {
return parseXML(connection.getInputStream());
}
return null;
}
/**转化XML获取数据
* 服务器端的xml文件如下。。。。。。
* <?xml version="1.0" encoding="UTF-8"?>
<contacts>
<contact id="1">
<name>Roco_1</name>
<image src=http://up.2cto.com/2013/0417/20130417032102399.png" />
</contact>
.......
</contacts>*/
private static List<Contact> parseXML(InputStream inputStream)
throws Exception {
List<Contact> contacts = new ArrayList<Contact>();
Contact contact = null;
XmlPullParser pullParser = Xml.newPullParser();
pullParser.setInput(inputStream, "UTF-8");
int event = pullParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
switch (event) {
case XmlPullParser.START_TAG:
if ("contact".equals(pullParser.getName())) {
contact = new Contact();
contact.setId(new Integer(pullParser.getAttributeValue(0)));
} else if ("name".equals(pullParser.getName())) {
contact.setName(pullParser.nextText());
} else if ("image".equals(pullParser.getName())) {
contact.setImage(pullParser.getAttributeValue(0));
}
break;
case XmlPullParser.END_TAG:
if ("contact".equals(pullParser.getName())) {
contacts.add(contact);
contact = null;
}
}
event = pullParser.next();
}
return contacts;
}
/**
* 获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来
*
* @param path
* 图片路径
* @return
*/
public static Uri getImage(String imagePath, File cacheDir)
throws Exception {
//缓存文件的文件名用MD5进行加密
File localFile = new File(cacheDir, MD5.getMD5(imagePath)
+ imagePath.substring(imagePath.lastIndexOf(".")));
if (localFile.exists()) {
return Uri.fromFile(localFile);
} else {
HttpURLConnection connection = (HttpURLConnection) new URL(
imagePath).openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
//将文件缓存起来
if (connection.getResponseCode() == 200) {
FileOutputStream outputStream = new FileOutputStream(localFile);
InputStream inputStream = connection.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
inputStream.close();
outputStream.close();
return Uri.fromFile(localFile);
}
}
return null;
}
}
step6:写一个Adapter用于对ListView进行数据更新 cn.roco.data.adapter.ContactAdapter.java
[java]
package cn.roco.data.adapter;
import java.io.File;
import java.util.List;
import cn.roco.data.R;
import cn.roco.data.domain.Contact;
import cn.roco.data.service.ContactService;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
/**适配器,用于更新View*/
public class ContactAdapter extends BaseAdapter {
private List<Contact> data;
private int listviewItem;
private File cache;
/**
* LayoutInflater的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout文件夹下的xml布局文件,并且实例化!
* 而 findViewById()是找具体某一个xml下的具体 widget控件(如:Button,TextView等)。
*/
private LayoutInflater layoutInflater;
public ContactAdapter(Context context, List<Contact> data,
int listviewItem, File cache) {
this.data = data;
this.listviewItem = listviewItem;
this.cache = cache;
this.layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);//取得xml里定义的view
/***
* getSystemService()是Android很重要的一个API,它是Activity的一个方法,
* 根据传入的NAME来取得对应的Object,然后转换成相应的服务对象。以下介绍系统相应的服务。
* 传入的Name 返回的对象 说明
WINDOW_SERVICE WindowManager 管理打开的窗口程序
LAYOUT_INFLATER_SERVICE LayoutInflater 取得xml里定义的view
ACTIVITY_SERVICE ActivityManager 管理应用程序的系统状态
POWER_SERVICE PowerManger 电源的服务
ALARM_SERVICE AlarmManager 闹钟的服务
NOTIFICATION_SERVICE NotificationManager 状态栏的服务
KEYGUARD_SERVICE KeyguardManager 键盘锁的服务
LOCATION_SERVICE LocationManager 位置的服务,如GPS
SEARCH_SERVICE SearchManager 搜索的服务
VEBRATOR_SERVICE Vebrator 手机震动的服务
CONNECTIVITY_SERVICE Connectivity 网络连接的服务
WIFI_SERVICE WifiManager Wi-Fi服务
TELEPHONY_SERVICE TeleponyManager 电话服务
*/
}
/** 得到数据的总数 */
@Override
public int getCount() {
return data.size();
}
/** 根据数据索引,得到集合中所对应的数据 */
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = null;
TextView textView = null;
if (convertView == null) {
convertView = layoutInflater.inflate(listviewItem, null);
imageView = (ImageView) convertView.findViewById(R.id.imageView);
textView = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(new DataWrapper(imageView, textView));//将内容包装起来以备以后使用
} else {
DataWrapper dataWrapper=(DataWrapper) convertView.getTag();//将包装类取出来
//从包装类中取数据
imageView=dataWrapper.getImageView();
textView=dataWrapper.getTextView();
}
Contact contact=data.get(position);
textView.setText(contact.getName());
/**异步加载图片文件*/
asynchImageLoad(imageView,contact.getImage());
return convertView;
}
/*
//该方法会创建很多的线程,也会很耗资源
private void asynchImageLoad(final ImageView imageView, final String imagePath) {
final Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {//运行在主线程中
Uri uri=(Uri) msg.obj;
if (uri!=null&&imageView!=null) {
imageView.setImageURI(uri);
}
}
};
Runnable runnable=new Runnable() {
@Override
public void run() {
try {
Uri uri=ContactService.getImage(imagePath, cache);
handler.sendMessage(handler.obtainMessage(10,uri));
} catch (Exception e) {
e.printStackTrace();
}
}
};
new Thread(runnable).start();
}
*/
/**异步加载图片文件*/
private void asynchImageLoad(ImageView imageView, String imagePath) {
AsycImageTask asycImageTask=new AsycImageTask(imageView);
asycImageTask.execute(imagePath);
}
/**
* 使用AsyncTask提高性能
* 可选方法:
1, onprogressupdate(progress…) 可以使用进度条增加用户体验度。此方法在主线程执行,用户显示任务执行的进度。
2, onpreExecute() 这里是最新用户调用excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
3, onCancelled() 用户调用取消时,要做的操作。
AsyncTask<Params, Progress, Result>
AsyscTask定义了三种泛型类型params,progress和result.
1, params启动任务执行的输入参数,比如http请求的URL
2, progress后台任务执行的百分比
3, result后台执行任务最终返回的结果,比如String,比如我需要得到的list。
使用AsyncTask类,遵守的准则:1, Task的实例必须在UI thread中创建;2, Execute方法必须在UI thread中调用
3, 不要手动的调用onPfreexecute(),onPostExecute(result)Doinbackground(params…),onProgressupdate(progress…)这几个方法;
4, 该task只能被执行一次,否则多次调用时将会出现异常;
AsyncTask的整个调用过程都是从execute方法开始的,一旦在主线程中调用execute方法,就可以通过onpreExecute方法,
这是一个预处理方法,比如可以在这里开始一个进度框,同样也可以通过onprogressupdate方法给用户一个进度条的显示,增加用户体验;
最后通过onpostexecute方法,相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果处理操作UI。
此方法在主线程执行,任务执行的结果作为此方法的参数返回
*/
private final class AsycImageTask extends AsyncTask<String, Integer, Uri>{
private ImageView imageView;
public AsycImageTask(ImageView imageView) {
this.imageView=imageView;
}
/**
* 后台执行,比较耗时的操作都可以放在这里。
注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作
,通常需要较长的时间。在执行过程中可以调用
Public progress(progress…)来更新任务的进度。
*/
@Override
protected Uri doInBackground(String... params) {//子线程中执行
try {
return ContactService.getImage(params[0], cache);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果
* 处理操作UI。此方法在主线程执行,任务执行的结果作为此方法的参数返回。
*/
@Override
protected void onPostExecute(Uri result) {//运行在主线程
if (result!=null&&imageView!=null) {
imageView.setImageURI(result);
}
}
}
/**数据包装类*/
private final class DataWrapper {
private ImageView imageView;
private TextView textView;
public ImageView getImageView() {
return imageView;
}
public TextView getTextView() {
return textView;
}
public DataWrapper(ImageView imageView, TextView textView) {
this.imageView = imageView;
this.textView = textView;
}
}
}
package cn.roco.data.adapter;
import java.io.File;
import java.util.List;
import cn.roco.data.R;
import cn.roco.data.domain.Contact;
import cn.roco.data.service.ContactService;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
/**适配器,用于更新View*/
public class ContactAdapter extends BaseAdapter {
private List<Contact> data;
private int listviewItem;
private File cache;
/**
* LayoutInflater的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout文件夹下的xml布局文件,并且实例化!
* 而 findViewById()是找具体某一个xml下的具体 widget控件(如:Button,TextView等)。
*/
private LayoutInflater layoutInflater;
public ContactAdapter(Context context, List<Contact> data,
int listviewItem, File cache) {
this.data = data;
this.listviewItem = listviewItem;
this.cache = cache;
this.layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);//取得xml里定义的view
/***
* getSystemService()是Android很重要的一个API,它是Activity的一个方法,
* 根据传入的NAME来取得对应的Object,然后转换成相应的服务对象。以下介绍系统相应的服务。
* 传入的Name 返回的对象 说明
WINDOW_SERVICE WindowManager 管理打开的窗口程序
LAYOUT_INFLATER_SERVICE LayoutInflater 取得xml里定义的view
ACTIVITY_SERVICE ActivityManager 管理应用程序的系统状态
POWER_SERVICE PowerManger 电源的服务
ALARM_SERVICE AlarmManager 闹钟的服务
NOTIFICATION_SERVICE NotificationManager 状态栏的服务
KEYGUARD_SERVICE KeyguardManager 键盘锁的服务
LOCATION_SERVICE LocationManager 位置的服务,如GPS
SEARCH_SERVICE SearchManager 搜索的服务
VEBRATOR_SERVICE Vebrator 手机震动的服务
CONNECTIVITY_SERVICE Connectivity 网络连接的服务
WIFI_SERVICE WifiManager Wi-Fi服务
TELEPHONY_SERVICE TeleponyManager 电话服务
*/
}
/** 得到数据的总数 */
@Override
public int getCount() {
return data.size();
}
/** 根据数据索引,得到集合中所对应的数据 */
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = null;
TextView textView = null;
if (convertView == null) {
convertView = layoutInflater.inflate(listviewItem, null);
imageView = (ImageView) convertView.findViewById(R.id.imageView);
textView = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(new DataWrapper(imageView, textView));//将内容包装起来以备以后使用
} else {
DataWrapper dataWrapper=(DataWrapper) convertView.getTag();//将包装类取出来
//从包装类中取数据
imageView=dataWrapper.getImageView();
textView=dataWrapper.getTextView();
}
Contact contact=data.get(position);
textView.setText(contact.getName());
/**异步加载图片文件*/
asynchImageLoad(imageView,contact.getImage());
return convertView;
}
/*
//该方法会创建很多的线程,也会很耗资源
private void asynchImageLoad(final ImageView imageView, final String imagePath) {
final Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {//运行在主线程中
Uri uri=(Uri) msg.obj;
if (uri!=null&&imageView!=null) {
imageView.setImageURI(uri);
}
}
};
Runnable runnable=new Runnable() {
@Override
public void run() {
try {
Uri uri=ContactService.getImage(imagePath, cache);
handler.sendMessage(handler.obtainMessage(10,uri));
} catch (Exception e) {
e.printStackTrace();
}
}
};
new Thread(runnable).start();
}
*/
/**异步加载图片文件*/
private void asynchImageLoad(ImageView imageView, String imagePath) {
AsycImageTask asycImageTask=new AsycImageTask(imageView);
asycImageTask.execute(imagePath);
}
/**
* 使用AsyncTask提高性能
* 可选方法:
1, onprogressupdate(progress…) 可以使用进度条增加用户体验度。此方法在主线程执行,用户显示任务执行的进度。
2, onpreExecute() 这里是最新用户调用excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
3, onCancelled() 用户调用取消时,要做的操作。
AsyncTask<Params, Progress, Result>
AsyscTask定义了三种泛型类型params,progress和result.
1, params启动任务执行的输入参数,比如http请求的URL
2, progress后台任务执行的百分比
3, result后台执行任务最终返回的结果,比如String,比如我需要得到的list。
使用AsyncTask类,遵守的准则:1, Task的实例必须在UI thread中创建;2, Execute方法必须在UI thread中调用
3, 不要手动的调用onPfreexecute(),onPostExecute(result)Doinbackground(params…),onProgressupdate(progress…)这几个方法;
4, 该task只能被执行一次,否则多次调用时将会出现异常;
AsyncTask的整个调用过程都是从execute方法开始的,一旦在主线程中调用execute方法,就可以通过onpreExecute方法,
这是一个预处理方法,比如可以在这里开始一个进度框,同样也可以通过onprogressupdate方法给用户一个进度条的显示,增加用户体验;
最后通过onpostexecute方法,相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果处理操作UI。
此方法在主线程执行,任务执行的结果作为此方法的参数返回
*/
private final class AsycImageTask extends AsyncTask<String, Integer, Uri>{
private ImageView imageView;
public AsycImageTask(ImageView imageView) {
this.imageView=imageView;
}
/**
* 后台执行,比较耗时的操作都可以放在这里。
注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作
,通常需要较长的时间。在执行过程中可以调用
Public progress(progress…)来更新任务的进度。
*/
@Override
protected Uri doInBackground(String... params) {//子线程中执行
try {
return ContactService.getImage(params[0], cache);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果
* 处理操作UI。此方法在主线程执行,任务执行的结果作为此方法的参数返回。
*/
@Override
protected void onPostExecute(Uri result) {//运行在主线程
if (result!=null&&imageView!=null) {
imageView.setImageURI(result);
}
}
}
/**数据包装类*/
private final class DataWrapper {
private ImageView imageView;
private TextView textView;
public ImageView getImageView() {
return imageView;
}
public TextView getTextView() {
return textView;
}
public DataWrapper(ImageView imageView, TextView textView) {
this.imageView = imageView;
this.textView = textView;
}
}
}
step7:应用的主程序 cn.roco.data.MainActivity.java
[java]
package cn.roco.data;
import java.io.File;
import java.util.List;
import cn.roco.data.adapter.ContactAdapter;
import cn.roco.data.domain.Contact;
import cn.roco.data.service.ContactService;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView listView;
/**缓存文件*/
private File cache;
/**接受消息,处理消息 ,此Handler会与当前主线程一块运行
* 使用匿名内部类来复写Handler当中的handlerMessage()方法 */
Handler handler = new Handler() {
// 接受数据
public void handleMessage(android.os.Message msg) {
//设置适配器,将获取的数据使用适配器更新View
listView.setAdapter(new ContactAdapter(MainActivity.this,
(List<Contact>) msg.obj, R.layout.listview_item, cache));
};
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
listView = (ListView) this.findViewById(R.id.listView);
/**在SD卡中生成缓存目录*/
cache = new File(Environment.getExternalStorageDirectory(), "cache");
/**如果目录不存在就新建一个*/
if (!cache.exists()) cache.mkdir();
new Thread(new Runnable() {
@Override
public void run() {
try {
//获取联系人数据
List<Contact> data= ContactService.getContacts();
// 向Handler发送消息,更新UI
handler.sendMessage(handler.obtainMessage(22, data));
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
@Override
protected void onDestroy() {
/**清除缓存文件*/
for (File file:cache.listFiles()) {
file.delete();
}
cache.delete();
super.onDestroy();
}
}
package cn.roco.data;
import java.io.File;
import java.util.List;
import cn.roco.data.adapter.ContactAdapter;
import cn.roco.data.domain.Contact;
import cn.roco.data.service.ContactService;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView listView;
/**缓存文件*/
private File cache;
/**接受消息,处理消息 ,此Handler会与当前主线程一块运行
* 使用匿名内部类来复写Handler当中的handlerMessage()方法 */
Handler handler = new Handler() {
// 接受数据
public void handleMessage(android.os.Message msg) {
//设置适配器,将获取的数据使用适配器更新View
listView.setAdapter(new ContactAdapter(MainActivity.this,
(List<Contact>) msg.obj, R.layout.listview_item, cache));
};
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
listView = (ListView) this.findViewById(R.id.listView);
/**在SD卡中生成缓存目录*/
cache = new File(Environment.getExternalStorageDirectory(), "cache");
/**如果目录不存在就新建一个*/
if (!cache.exists()) cache.mkdir();
new Thread(new Runnable() {
@Override
public void run() {
try {
//获取联系人数据
List<Contact> data= ContactService.getContacts();
// 向Handler发送消息,更新UI
handler.sendMessage(handler.obtainMessage(22, data));
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
@Override
protected void onDestroy() {
/**清除缓存文件*/
for (File file:cache.listFiles()) {
file.delete();
}
cache.delete();
super.onDestroy();
}
}
step8:AndroidManifest.xml
[html]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.roco.data" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<!-- 访问Internet权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 在SD卡中创建和删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SD卡中写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.roco.data" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<!-- 访问Internet权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 在SD卡中创建和删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SD卡中写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
step9:编写服务器端的代码,主要是一个contact.xml文件
[html]
<?xml version="1.0" encoding="UTF-8"?>
<contacts>
<contact id="1">
<name>Roco_1</name>
<image src=http://up.2cto.com/2013/0417/20130417032102399.png" />
</contact>
<contact id="2">
<name>Roco_2</name>
<image src=http://up.2cto.com/2013/0417/20130417032103840.png" />
</contact>
<contact id="3">
<name>Roco_3</name>
<image src=http://up.2cto.com/2013/0417/20130417032103320.png" />
</contact>
<contact id="4">
<name>Roco_4</name>
<image src=http://up.2cto.com/2013/0417/20130417032103459.png" />
</contact>
<contact id="5">
<name>Roco_5</name>
<image src=http://up.2cto.com/2013/0417/20130417032104874.png" />
</contact>
<contact id="6">
<name>Roco_6</name>
<image src=http://up.2cto.com/2013/0417/20130417032104668.png" />
</contact>
<contact id="7">
<name>Roco_7</name>
<image src=http://up.2cto.com/2013/0417/20130417032104615.png" />
</contact>
<contact id="8">
<name>Roco_8</name>
<image src=http://up.2cto.com/2013/0417/20130417032105398.png" />
</contact>
<contact id="9">
<name>Roco_9</name>
<image src=http://up.2cto.com/2013/0417/20130417032106799.png" />
</contact>
<contact id="10">
<name>Roco_10</name>
<image src=http://up.2cto.com/2013/0417/20130417032106442.png" />
</contact>
<contact id="11">
<name>Roco_11</name>
<image src=http://up.2cto.com/2013/0417/20130417032108933.png" />
</contact>
<contact id="12">
<name>Roco_12</name>
<image src=http://up.2cto.com/2013/0417/20130417032108268.png" />
</contact>
<contact id="13">
<name>Roco_13</name>
<image src=http://up.2cto.com/2013/0417/20130417032108395.png" />
</contact>
<contact id="14">
<name>Roco_14</name>
<image src=http://up.2cto.com/2013/0417/20130417032110808.png" />
</contact>
<contact id="15">
<name>Roco_15</name>
<image src=http://up.2cto.com/2013/0417/20130417032110349.png" />
</contact>
<contact id="16">
<name>Roco_16</name>
<image src=http://up.2cto.com/2013/0417/20130417032111248.png" />
</contact>
<contact id="17">
<name>Roco_17</name>
<image src=http://up.2cto.com/2013/0417/20130417032112162.png" />
</contact>
<contact id="18">
<name>Roco_18</name>
<image src=http://up.2cto.com/2013/0417/20130417032112322.png" />
</contact>
<contact id="19">
<name>Roco_19</name>
<image src=http://up.2cto.com/2013/0417/20130417032112787.png" />
</contact>
<contact id="20">
<name>Roco_20</name>
<image src=http://up.2cto.com/2013/0417/20130417032112445.png" />
</contact>
</contacts>
<?xml version="1.0" encoding="UTF-8"?>
<contacts>
<contact id="1">
<name>Roco_1</name>
<image src=http://up.2cto.com/2013/0417/20130417032102399.png" />
</contact>
<contact id="2">
<name>Roco_2</name>
<image src=http://up.2cto.com/2013/0417/20130417032103840.png" />
</contact>
<contact id="3">
<name>Roco_3</name>
<image src=http://up.2cto.com/2013/0417/20130417032103320.png" />
</contact>
<contact id="4">
<name>Roco_4</name>
<image src=http://up.2cto.com/2013/0417/20130417032103459.png" />
</contact>
<contact id="5">
<name>Roco_5</name>
<image src=http://up.2cto.com/2013/0417/20130417032104874.png" />
</contact>
<contact id="6">
<name>Roco_6</name>
<image src=http://up.2cto.com/2013/0417/20130417032104668.png" />
</contact>
<contact id="7">
<name>Roco_7</name>
<image src=http://up.2cto.com/2013/0417/20130417032104615.png" />
</contact>
<contact id="8">
<name>Roco_8</name>
<image src=http://up.2cto.com/2013/0417/20130417032105398.png" />
</contact>
<contact id="9">
<name>Roco_9</name>
<image src=http://up.2cto.com/2013/0417/20130417032106799.png" />
</contact>
<contact id="10">
<name>Roco_10</name>
<image src=http://up.2cto.com/2013/0417/20130417032106442.png" />
</contact>
<contact id="11">
<name>Roco_11</name>
<image src=http://up.2cto.com/2013/0417/20130417032108933.png" />
</contact>
<contact id="12">
<name>Roco_12</name>
<image src=http://up.2cto.com/2013/0417/20130417032108268.png" />
</contact>
<contact id="13">
<name>Roco_13</name>
<image src=http://up.2cto.com/2013/0417/20130417032108395.png" />
</contact>
<contact id="14">
<name>Roco_14</name>
<image src=http://up.2cto.com/2013/0417/20130417032110808.png" />
</contact>
<contact id="15">
<name>Roco_15</name>
<image src=http://up.2cto.com/2013/0417/20130417032110349.png" />
</contact>
<contact id="16">
<name>Roco_16</name>
<image src=http://up.2cto.com/2013/0417/20130417032111248.png" />
</contact>
<contact id="17">
<name>Roco_17</name>
<image src=http://up.2cto.com/2013/0417/20130417032112162.png" />
</contact>
<contact id="18">
<name>Roco_18</name>
<image src=http://up.2cto.com/2013/0417/20130417032112322.png" />
</contact>
<contact id="19">
<name>Roco_19</name>
<image src=http://up.2cto.com/2013/0417/20130417032112787.png" />
</contact>
<contact id="20">
<name>Roco_20</name>
<image src=http://up.2cto.com/2013/0417/20130417032112445.png" />
</contact>
</contacts>
以及在images目录下放置了一些图片
step10:将项目部署到模拟器上运行效果如下图:
在SD卡中会生成缓存文件
当应用退出的时候,会将缓存文件删除
有了缓存文件,只要应用没有退出,即使联网不成功,也可以读取缓存中的图片文件