青蛙9
![](http://192.192.8.233:8080/Test/images/9.gif)
青蛙10
![](http://192.192.8.233:8080/Test/images/10.gif)
青蛙11
![](http://192.192.8.233:8080/Test/images/11.gif)
青蛙12
![](http://192.192.8.233:8080/Test/images/12.gif)
青蛙13
![](http://192.192.8.233:8080/Test/images/13.gif)
青蛙14
![](http://192.192.8.233:8080/Test/images/14.gif)
青蛙15
![](http://192.192.8.233:8080/Test/images/15.gif)
青蛙16
![](http://192.192.8.233:8080/Test/images/16.gif)
青蛙17
![](http://192.192.8.233:8080/Test/images/17.gif)
青蛙18
![](http://192.192.8.233:8080/Test/images/18.gif)
我们可以看到list.xml最外层是一个contacts标签,里面有多个子contact标签,每个子标签包含id、name和image内容,这就是我们下面要解析的内容对应每一个Contact对象。
这里要提一下,我们看到image标签,src是图片url地址,这个地址是我PC的IP地址,读者在测试的时候需要将这个IP地址改为你的PC的IP地址,如何得到?运行->cmd->ipconfig /all查看ipv4地址,就是你电脑的ip地址了。
创建好Web项目之后,我们在电脑上测试一下,在浏览器输入地址:
http://192.192.8.233:8080/Test/list.xml
看到以上内容,说明我们已经可以访问到我们的服务端了,下面我们就可以开发我们的客户端:
我这里创建了一个07_DataAsyncLoad的项目:
目录结构如下:
因为需要联网,在AndroidManifest.xml设置权限:
根据服务端list.xml,我们需要定义一个实体类:
/07_DataAsyncLoad/src/com/wwj/domain/Contact.java
package com.wwj.domain;
/**
-
联系人实体类
-
@author wwj
*/
public class Contact {
public int id;
public String name;
public String image;
public Contact(int id, String name, String image) {
this.id = id;
this.name = name;
this.image = image;
}
public Contact() {
}
}
需要访问服务端并且解析xml文件,我们定义一个服务类:
/07_DataAsyncLoad/src/com/wwj/service/ContactService.java
package com.wwj.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 com.wwj.domain.Contact;
import com.wwj.utils.MD5;
import android.net.Uri;
import android.util.Xml;
public class ContactService {
/**
-
获取联系人
-
@return
*/
public static List getContacts() throws Exception{
// 服务器文件路径
String path = “http://192.192.8.233:8080/Test/list.xml”;
HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(5000); //设置超时5秒
conn.setRequestMethod(“GET”); //设置请求方式
if(conn.getResponseCode() == 200){ //连接成功返回码200
return parseXML(conn.getInputStream());
}
return null;
}
/**
-
利用pull解析器对xml文件进行解析
-
@param xml
-
@return
-
@throws Exception
*/
private static List parseXML(InputStream xml) throws Exception{
List contacts = new ArrayList();
Contact contact = null;
XmlPullParser pullParser = Xml.newPullParser();
pullParser.setInput(xml, “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.id = new Integer(pullParser.getAttributeValue(0));
}else if(“name”.equals(pullParser.getName())){
contact.name = pullParser.nextText(); //取得后面节点的文本值
}else if(“image”.equals(pullParser.getName())){
contact.image = pullParser.getAttributeValue(0); //取得第一个属性的值
}
break;
case XmlPullParser.END_TAG: //结束标签
if(“contact”.equals(pullParser.getName())){
contacts.add(contact); //将contact对象添加到集合中
contact = null;
}
break;
}
event = pullParser.next(); //去下一个标签
}
return contacts;
}
/**
-
获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来
-
@param path 图片路径
-
@return
*/
public static Uri getImage(String path, File cacheDir) throws Exception{// path -> MD5 ->32字符串.jpg
File localFile = new File(cacheDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf(".")));
if(localFile.exists()){
return Uri.fromFile(localFile);
}else{
HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod(“GET”);
if(conn.getResponseCode() == 200){
FileOutputStream outStream = new FileOutputStream(localFile);
InputStream inputStream = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len = inputStream.read(buffer)) != -1){
outStream.write(buffer, 0, len);
}
inputStream.close();
outStream.close();
return Uri.fromFile(localFile);
}
}
return null;
}
}
上面代码已经很清楚的定义了获取服务端数据的方法,大致流程是这样的:传递一个网络路径path,通过URL打开连接,通过HttpURLConnection连接服务端,得到输入流,解析xml文件再获得数据。
上面代码获取网络图片,需要进行MD5加密计算,具体方法如下:
/07_DataAsyncLoad/src/com/wwj/utils/MD5.java
package com.wwj.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
/**
-
MD5加密算法
-
@param content
-
@return
*/
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;
}
/**
-
获得哈希字符串
-
@param digest
-
@return
*/
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();
}
}
好,这样我们的服务类就已经写完了,这时我们在MainActivity进行异步加载数据:
/07_DataAsyncLoad/src/com/wwj/asyntask/MainActivity.java
package com.wwj.asyntask;
import java.io.File;
import java.util.List;
import com.wwj.adapter.ContactAdapter;
import com.wwj.asyntask.R;
import com.wwj.domain.Contact;
import com.wwj.service.ContactService;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.widget.ListView;
public class MainActivity extends Activity {
ListView listView;
File cache; // 缓存文件
Handler handler = new Handler() {
public void handleMessage(Message msg) {
listView.setAdapter(new ContactAdapter(MainActivity.this,
(List) msg.obj, R.layout.listview_item, cache));
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) this.findViewById(R.id.listView);
cache = new File(Environment.getExternalStorageDirectory(), “cache”); // 实例化缓存文件
if (!cache.exists())
cache.mkdirs(); // 如果文件不存在,创建
// 开一个线程来加载数据
new Thread(new Runnable() {
public void run() {
try {
List data = ContactService.getContacts();
// 通过handler来发送消息
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();
}
}
这里我们开了一个线程来加载数据,是因为网络操作不能在UI线程中进行,加载完数据后通过Hanlder发送消息,显示列表。
一般情况下,我们获取图片需要另外处理,我们有很多种方法,最常用的就是Handler+Thread和AsyncTask两种,具体实现来看:
/07_DataAsyncLoad/src/com/wwj/adapter/ContactAdapter.java
我们定义了一个列表适配器,用来填充我们的数据,我们的图片异步加载也在这里实现了:
package com.wwj.adapter;
import java.io.File;
import java.util.List;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.wwj.asyntask.R;
import com.wwj.domain.Contact;
import com.wwj.service.ContactService;
/**
-
自定义适配器
-
@author wwj
*/
public class ContactAdapter extends BaseAdapter {
private List data; // 缓存数据
private int listviewItem; // 条目id
private File cache; // 缓存文件
LayoutInflater layoutInflater;
public ContactAdapter(Context context, List data,
int listviewItem, File cache) {
this.data = data;
this.listviewItem = listviewItem;
this.cache = cache;
layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INF
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
LATER_SERVICE);// 获取布局填充服务
}
/**
- 得到数据的总数
*/
public int getCount() {
return data.size();
}
/**