以下为主界面上负责显示的代码:
1: public class MainActivity extends Activity {
2: private ImageService imageService;
3: private List<Blog> blogs;
4: //activity一创建执行的代码
5: public void onCreate(Bundle savedInstanceState) {
6: super.onCreate(savedInstanceState); 7: setContentView(R.layout.main);8: try {
9: //先拿到负责处理图像和封装微博对象的两个服务类对象
10: imageService = new ImageService(this);
11: BlogService blogService = new BlogService();
//通过blogService的get方法,从服务器中请求xml资源,并对xml进行解析,封装对象,得到一个微博对象集合 13: blogs = blogService.getBlogs();14: //获取ListView控件对象
15: ListView blogLV = (ListView) findViewById(R.id.blogLV);16: //设置ListView控件对象的适配器,用来向列表中添加包含了微博对象的各个item元素
17: blogLV.setAdapter(adapter);18: } catch (Exception e) {
19: e.printStackTrace();20: Toast.makeText(this, "服务器忙!", 0).show();
21: } 22: }23: private BaseAdapter adapter = new BaseAdapter() {
24: //listview中用来获取一个行信息的函数:
25: //getview方法作用,listview中显示一条item就调用一次该方法,创建一个条目视图
26: //需要传三个参数:当前条目位置,当前条目载体(是否重用),当前条目父级
27: public View getView(int position, View convertView, ViewGroup parent) {
28: //把每个item填充到listview中的行里,销毁的拿来重新利用,提高浏览的速度
29: View view = convertView == null ?
30: View.inflate(getApplicationContext(), R.layout.item, null) : convertView;
31: //生成一个完整的item,设置它里面的所有内容:
32: //获取头像控件对象
33: final ImageView portraitIV =(ImageView) view.findViewById(R.id.portraitIV); 34: //获取微博里的图片控件对象
35: final ImageView picIV =(ImageView) view.findViewById(R.id.picIV); 36: //获取名字文本控件对象
37: TextView nameTV = (TextView) view.findViewById(R.id.nameTV);38: //获取微博内容文本控件对象
39: TextView contentTV = (TextView) view.findViewById(R.id.contentTV);40: //获取微博来源内容文本控件对象
41: TextView fromTV = (TextView) view.findViewById(R.id.fromTV);42: //得到当前位置处的那个微博对象,position代表第几个条目,从0开始,正好和集合的下标一致
43: final Blog blog = blogs.get(position);44: // 把blog中的数据添加到TextView, ImageView中
45: nameTV.setText(blog.getName()); 46: contentTV.setText(blog.getContent()); 47: fromTV.setText(blog.getFrom()); 48: //获取解析到的图片的方法:
49: //原理:解析到的只是图片的地址,所以要得到图片,最好重新开一个线程,去访问服务器上的图片
50: try {
51: //把微博对象中的图片属性值(就是图片的地址),传给imageService的get方法,让它去访问,就可以得到一个图片
52: portraitIV.setImageBitmap(imageService.getImage(blog.getPortrait())); 53: } catch (Exception e) {
54: e.printStackTrace(); 55: }56: //设置微博对象中的微博图片同上
57: try {
58: picIV.setImageBitmap(imageService.getImage(blog.getPic())); 59: } catch (Exception e) {
60: e.printStackTrace(); 61: }62: return view;
63: }64: public long getItemId(int position) {
65: return position;
66: } 67: //从微博对象集合blogs中,找到当前位置处的那个微博对象,并返回,position代表第几个条目,从0开始,正好和集合的下标一致
68: public Object getItem(int position) {
69: return blogs.get(position);
70: } 71: public int getCount() {
72: return blogs.size();
73: } 74: };75: }
以下为负责处理请求图片逻辑的服务层代码
1: public class ImageService {
2: private Context context;
3: 4: public ImageService(Context context) {
5: this.context = context;
6: }7: //bitmap位图类,安卓中用来表示图片的类,自定义一个从服务器获得图片的方法,接受一个图片地址
8: public Bitmap getImage(String address) throws Exception {
9: if (address == null)
10: return null;
11: //创建连接对象
12: URL url = new URL(address);
13: //打开连接
14: HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 15: //设置连接超时
16: conn.setConnectTimeout(3000);17: //创建一个文件路径对象,目录是文件缓存地址,文件名是图片的网络地址
18: File cacheFile = new File(context.getCacheDir(), URLEncoder.encode(address));
19: if (cacheFile.exists()) {
//路径对象下的文件对象存在,说明之前访问过了,获取其最后修改时间, 设置请求头,再向服务器去请求这个图片21: //以便能让服务器判断这个图片最近有没有修改过
22: conn.setIfModifiedSince(cacheFile.lastModified()); 23: }24: //获取服务器响应
25: int code = conn.getResponseCode();
26: 27: //资源被修改了或者第一次访问该资源都是200
28: if (code == 200) {
29: //利用自定义的工具类,读取服务器响应回的输入流并转为字节数组型数据
30: byte[] data = Util.read(conn.getInputStream());
31: //创建一个位图对象的方法:利用工厂类把字节数据解码为图片
32: Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length); 33: // 存储图片到本地, 用作缓存. 建议新线程中处理
34: bm.compress(CompressFormat.JPEG, 100, new FileOutputStream(cacheFile));
35: return bm;
36: //304表示资源没有被修改过,只要不是304,资源要么被修改了,要么是第一次访问
37: } else if (code == 304) {
38: Bitmap bm = BitmapFactory.decodeFile(cacheFile.getAbsolutePath()); // 读取cacheFile, 生成Bitmap
39: return bm;
40: } 41: throw new NetworkErrorException("连接出错: " + code);
42: } 43: 44: }以下代码为负责从服务器请求微博数据的服务层代码:
1: public class BlogService {
2: 3: /**
4: * 请求服务端, 得到包含数据的XML, 解析XML, 得到List<Blog>
5: * @return 包含Blog对象的List集合
6: */
7: public List<Blog> getBlogs() throws Exception {
8: //如果服务器发过来的是blogs.js类型的数据,而不是blogs.xml,解析方式如下“
9: 10: //创建连接对象,如果服务器是以js的形式发回微博内容。则调用parseJSON方法
11: URL url = new URL("http://192.168.1.253:8080/15.Web/blogs.js");
12: 13: //创建连接对象,如果服务器是以xml的形式发回微博内容。则调用parseXML方法
14: //URL url = new URL("http://192.168.1.253:8080/15.Web/blogs.xml");
15: 16: //打开该连接
17: HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 18: conn.setConnectTimeout(3000); 19: 20: int code = conn.getResponseCode();
21: if (code == 200) {
22: //访问成功,执行解析方法
23: return parseJSON(conn.getInputStream());
24: }25: throw new NetworkErrorException("网络异常: " + code);
26: } 27: 28: //服务器以js的形式发回微博内容。调用parseJSON方法
29: private List<Blog> parseJSON(InputStream inputStream) throws Exception {
30: List<Blog> blogs = new ArrayList<Blog>();
31: // 读取服务端写回的js数据,将服务器发来的输入流封装到一个字节数组中
32: byte[] data = Util.read(inputStream);
33: //将返回的字节数组转为字符串,该字符串包含了很多表中单元,一个单元代表一个微博信息
34: String json = new String(data);
35: //将包含所有微博数据的字符串封装成一个JSON数组对象,数组中每个成员是一条微博信息
36: JSONArray arr = new JSONArray(json);
37: //遍历数组,解析每条微博
38: for (int i = 0; i < arr.length(); i++) { // 循环遍历数组
39: // 得到每一个JSON对象
40: JSONObject obj = arr.getJSONObject(i); 41: //准备封装成对象
42: Blog blog = new Blog();
43: //封装对象的过程:
44: blog.setPortrait(obj.getString("portrait")); // 获取JSON对象中的属性, 设置给Blog对象
45: blog.setName(obj.getString("name"));
46: blog.setContent(obj.getString("content"));
47: //将图片的路径作为图片属性放到微博对象中
48: String pic = obj.getString("pic");
49: //如果微博中本来就没有图片,则设置null即可
50: blog.setPic(pic.equals("null") ? null : pic);
51: blog.setFrom(obj.getString("from"));
52: blogs.add(blog); 53: } 54: 55: return blogs;
56: } 57: 58: //服务器以xml的形式发回微博内容。调用parseXML方法
59: private List<Blog> parseXML(InputStream inputStream) throws Exception {
60: List<Blog> blogs = new ArrayList<Blog>();
61: Blog blog = null;
62: 63: XmlPullParser parser = Xml.newPullParser();64: parser.setInput(inputStream, "UTF-8");
65: for (int type = parser.getEventType(); type != XmlPullParser.END_DOCUMENT; type = parser.next()) {
66: if (type == XmlPullParser.START_TAG) {
67: if ("blog".equals(parser.getName())) {
68: blog = new Blog();
69: blogs.add(blog);70: } else if ("portrait".equals(parser.getName())) {
71: blog.setPortrait(parser.nextText());72: } else if ("name".equals(parser.getName())) {
73: blog.setName(parser.nextText());74: } else if ("content".equals(parser.getName())) {
75: blog.setContent(parser.nextText());76: } else if ("pic".equals(parser.getName())) {
77: blog.setPic(parser.nextText());78: } else if ("from".equals(parser.getName())) {
79: blog.setFrom(parser.nextText()); 80: } 81: } 82: }83: return blogs;
84: } 85: }使用到的自定义工具类:读取服务器返回的输入流,转为字节数组
1: public class Util {
2: 3: /**
4: * 读取输入流中的数据, 返回
5: * @param in 要读取数据的输入流
6: * @return 输入流中的数据
7: */
8: public static byte[] read(InputStream in) throws IOException {
9: ByteArrayOutputStream baos = new ByteArrayOutputStream();
10: byte[] buffer = new byte[1024];
11: int len;
12: while ((len = in.read(buffer)) != -1)
13: //为了提高效率,砍掉数组中空白内容,写入字符数组的某一部分,而不是把字符数组整个写入
14: baos.write(buffer, 0, len);15: in.close();
16: baos.close();17: return baos.toByteArray();
18: } 19: }