11_Android中HttpClient的应用,读取网络xml及xml解析流,Handler的应用,LayoutInflater的使用,SmartImageView的使用



1 所需的web项目结构如下:

11_Android中HttpClient的应用,读取网络xml及xml解析流,Handler的应用,LayoutInflater的使用,SmartImageView的使用

11_Android中HttpClient的应用,读取网络xml及xml解析流,Handler的应用,LayoutInflater的使用,SmartImageView的使用

2 new.xml的文件内容如下:

<?xml version="1.0" encoding="UTF-8" ?>

<news>

<new>

<title>3Q大战宣判: 腾讯获赔500万</title>

<detail>最高法驳回360上诉, 维持一审宣判.</detail>

<comment>6427</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/1.jpg</image>

</new>

<new>

<title>今日之声:北大雕塑被戴口罩</title>

<detail>市民: 因雾霾起诉环保局; 公务员谈"紧日子": 坚决不出去.</detail>

<comment>681</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/2.jpg</image>

</new>

<new>

<title>奥巴马见***是装蒜</title>

<detail>外文局: 国际民众认可中国大国地位;法院: "流量清零"未侵权.</detail>

<comment>1359</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/3.jpg</image>

</new>

<new>

<title>轻松一刻: 我要沉迷学习不自拔</title>

<detail>放假时我醒了不代表我起床了, 如今我起床了不代表我醒了!</detail>

<comment>10116</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/4.jpg</image>

</new>

<new>

<title>男女那些事儿</title>

<detail>"妈, 我在东莞被抓, 要2万保释金, 快汇钱到xxx!"</detail>

<comment>10339</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/5.jpg</image>

</new>

<new>

<title>3Q大战宣判: 腾讯获赔500万</title>

<detail>最高法驳回360上诉, 维持一审宣判.</detail>

<comment>6427</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/1.jpg</image>

</new>

<new>

<title>今日之声:北大雕塑被戴口罩</title>

<detail>市民: 因雾霾起诉环保局; 公务员谈"紧日子": 坚决不出去.</detail>

<comment>681</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/2.jpg</image>

</new>

<new>

<title>奥巴马见***是装蒜</title>

<detail>外文局: 国际民众认可中国大国地位;法院: "流量清零"未侵权.</detail>

<comment>1359</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/3.jpg</image>

</new>

<new>

<title>轻松一刻: 我要沉迷学习不自拔</title>

<detail>放假时我醒了不代表我起床了, 如今我起床了不代表我醒了!</detail>

<comment>10116</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/4.jpg</image>

</new>

<new>

<title>男女那些事儿</title>

<detail>"妈, 我在东莞被抓, 要2万保释金, 快汇钱到xxx!"</detail>

<comment>10339</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/5.jpg</image>

</new>

<new>

<title>3Q大战宣判: 腾讯获赔500万</title>

<detail>最高法驳回360上诉, 维持一审宣判.</detail>

<comment>6427</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/1.jpg</image>

</new>

<new>

<title>今日之声:北大雕塑被戴口罩</title>

<detail>市民: 因雾霾起诉环保局; 公务员谈"紧日子": 坚决不出去.</detail>

<comment>681</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/2.jpg</image>

</new>

<new>

<title>奥巴马见***是装蒜</title>

<detail>外文局: 国际民众认可中国大国地位;法院: "流量清零"未侵权.</detail>

<comment>1359</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/3.jpg</image>

</new>

<new>

<title>轻松一刻: 我要沉迷学习不自拔</title>

<detail>放假时我醒了不代表我起床了, 如今我起床了不代表我醒了!</detail>

<comment>10116</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/4.jpg</image>

</new>

<new>

<title>男女那些事儿</title>

<detail>"妈, 我在东莞被抓, 要2万保释金, 快汇钱到xxx!"</detail>

<comment>10339</comment>

<image>http://10.0.2.2:8080/NetEaseServer/images/5.jpg</image>

</new>

</news>

3 将上面这个web项目部署在云服务器上(这里为安全起见,我略去部分地址),访问地址为:http://XXX:8080/NetEaseServer/new.xml

11_Android中HttpClient的应用,读取网络xml及xml解析流,Handler的应用,LayoutInflater的使用,SmartImageView的使用

4 下面开始编写android app项目,最终的项目截图如下:

11_Android中HttpClient的应用,读取网络xml及xml解析流,Handler的应用,LayoutInflater的使用,SmartImageView的使用

5 编写Android的清单文件,如下:

<?xml "

android:textColor="@android:color/black"

android:textSize="17sp" />

<TextView

android:id="@+id/tv_listview_item_detail"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignLeft="@id/tv_listview_item_title"

android:layout_below="@id/tv_listview_item_title"

android:layout_marginTop="3dip"

android:text="啊发送旅客登机挥发速度发送旅客登机"

android:textColor="@android:color/darker_gray"

android:textSize="14sp" />

<TextView

android:id="@+id/tv_listview_item_comment"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:layout_alignParentRight="true"

android:text="668跟帖"

android:textColor="#FF0000"

android:textSize="12sp" />

</RelativeLayout>

8 用到的github上的SmartView,代码如下:

package com.loopj.android.image;

import android.content.Context;

import android.graphics.Bitmap;

public class BitmapImage implements SmartImage {

private Bitmap bitmap;

public BitmapImage(Bitmap bitmap) {

this.bitmap = bitmap;

}

public Bitmap getBitmap(Context context) {

return bitmap;

}

}

package com.loopj.android.image;

import java.io.InputStream;

import android.content.ContentUris;

import android.content.ContentResolver;

import android.content.Context;

import android.provider.ContactsContract;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.net.Uri;

public class ContactImage implements SmartImage {

private long contactId;

public ContactImage(long contactId) {

this.contactId = contactId;

}

public Bitmap getBitmap(Context context) {

Bitmap bitmap = null;

ContentResolver contentResolver = context.getContentResolver();

try {

Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);

InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, uri);

if(input != null) {

bitmap = BitmapFactory.decodeStream(input);

}

} catch(Exception e) {

e.printStackTrace();

}

return bitmap;

}

}

package com.loopj.android.image;

import android.content.Context;

import android.graphics.Bitmap;

public interface SmartImage {

public Bitmap getBitmap(Context context);

}

package com.loopj.android.image;

import android.content.Context;

import android.graphics.Bitmap;

import android.os.Handler;

import android.os.Message;

public class SmartImageTask implements Runnable {

private static final int BITMAP_READY = 0;

private boolean cancelled = false;

private OnCompleteHandler onCompleteHandler;

private SmartImage image;

private Context context;

public static class OnCompleteHandler extends Handler {

@Override

public void handleMessage(Message msg) {

Bitmap bitmap = (Bitmap)msg.obj;

onComplete(bitmap);

}

public void onComplete(Bitmap bitmap){};

}

public abstract static class OnCompleteListener {

public abstract void onComplete();

}

public SmartImageTask(Context context, SmartImage image) {

this.image = image;

this.context = context;

}

@Override

public void run() {

if(image != null) {

complete(image.getBitmap(context));

context = null;

}

}

public void setOnCompleteHandler(OnCompleteHandler handler){

this.onCompleteHandler = handler;

}

public void cancel() {

cancelled = true;

}

public void complete(Bitmap bitmap){

if(onCompleteHandler != null && !cancelled) {

onCompleteHandler.sendMessage(onCompleteHandler.obtainMessage(BITMAP_READY, bitmap));

}

}

}

package com.loopj.android.image;

import android.content.Context;

import android.graphics.Bitmap;

import android.util.AttributeSet;

import android.widget.ImageView;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class SmartImageView extends ImageView {

private static final int LOADING_THREADS = 4;

private static ExecutorService threadPool = Executors.newFixedThreadPool(LOADING_THREADS);

private SmartImageTask currentTask;

public SmartImageView(Context context) {

super(context);

}

public SmartImageView(Context context, AttributeSet attrs) {

super(context, attrs);

}

public SmartImageView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

}

// Helpers to set image by URL

public void setImageUrl(String url) {

setImage(new WebImage(url));

}

public void setImageUrl(String url, SmartImageTask.OnCompleteListener completeListener) {

setImage(new WebImage(url), completeListener);

}

public void setImageUrl(String url, final Integer fallbackResource) {

setImage(new WebImage(url), fallbackResource);

}

public void setImageUrl(String url, final Integer fallbackResource, SmartImageTask.OnCompleteListener completeListener) {

setImage(new WebImage(url), fallbackResource, completeListener);

}

public void setImageUrl(String url, final Integer fallbackResource, final Integer loadingResource) {

setImage(new WebImage(url), fallbackResource, loadingResource);

}

public void setImageUrl(String url, final Integer fallbackResource, final Integer loadingResource, SmartImageTask.OnCompleteListener completeListener) {

setImage(new WebImage(url), fallbackResource, loadingResource, completeListener);

}

// Helpers to set image by contact address book id

public void setImageContact(long contactId) {

setImage(new ContactImage(contactId));

}

public void setImageContact(long contactId, final Integer fallbackResource) {

setImage(new ContactImage(contactId), fallbackResource);

}

public void setImageContact(long contactId, final Integer fallbackResource, final Integer loadingResource) {

setImage(new ContactImage(contactId), fallbackResource, fallbackResource);

}

// Set image using SmartImage object

public void setImage(final SmartImage image) {

setImage(image, null, null, null);

}

public void setImage(final SmartImage image, final SmartImageTask.OnCompleteListener completeListener) {

setImage(image, null, null, completeListener);

}

public void setImage(final SmartImage image, final Integer fallbackResource) {

setImage(image, fallbackResource, fallbackResource, null);

}

public void setImage(final SmartImage image, final Integer fallbackResource, SmartImageTask.OnCompleteListener completeListener) {

setImage(image, fallbackResource, fallbackResource, completeListener);

}

public void setImage(final SmartImage image, final Integer fallbackResource, final Integer loadingResource) {

setImage(image, fallbackResource, loadingResource, null);

}

public void setImage(final SmartImage image, final Integer fallbackResource, final Integer loadingResource, final SmartImageTask.OnCompleteListener completeListener) {

// Set a loading resource

if(loadingResource != null){

setImageResource(loadingResource);

}

// Cancel any existing tasks for this image view

if(currentTask != null) {

currentTask.cancel();

currentTask = null;

}

// Set up the new task

currentTask = new SmartImageTask(getContext(), image);

currentTask.setOnCompleteHandler(new SmartImageTask.OnCompleteHandler() {

@Override

public void onComplete(Bitmap bitmap) {

if(bitmap != null) {

setImageBitmap(bitmap);

} else {

// Set fallback resource

if(fallbackResource != null) {

setImageResource(fallbackResource);

}

}

if(completeListener != null){

completeListener.onComplete();

}

}

});

// Run the task in a threadpool

threadPool.execute(currentTask);

}

public static void cancelAllTasks() {

threadPool.shutdownNow();

threadPool = Executors.newFixedThreadPool(LOADING_THREADS);

}

}

package com.loopj.android.image;

import java.io.InputStream;

import java.net.URL;

import java.net.URLConnection;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

public class WebImage implements SmartImage {

private static final int CONNECT_TIMEOUT = 5000;

private static final int READ_TIMEOUT = 10000;

private static WebImageCache webImageCache;

private String url;

public WebImage(String url) {

this.url = url;

}

public Bitmap getBitmap(Context context) {

// Don't leak context

if(webImageCache == null) {

webImageCache = new WebImageCache(context);

}

// Try getting bitmap from cache first

Bitmap bitmap = null;

if(url != null) {

bitmap = webImageCache.get(url);

if(bitmap == null) {

bitmap = getBitmapFromUrl(url);

if(bitmap != null){

webImageCache.put(url, bitmap);

}

}

}

return bitmap;

}

private Bitmap getBitmapFromUrl(String url) {

Bitmap bitmap = null;

try {

URLConnection conn = new URL(url).openConnection();

conn.setConnectTimeout(CONNECT_TIMEOUT);

conn.setReadTimeout(READ_TIMEOUT);

bitmap = BitmapFactory.decodeStream((InputStream) conn.getContent());

} catch(Exception e) {

e.printStackTrace();

}

return bitmap;

}

public static void removeFromCache(String url) {

if(webImageCache != null) {

webImageCache.remove(url);

}

}

}

package com.loopj.android.image;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.lang.ref.SoftReference;

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Bitmap.CompressFormat;

import android.graphics.BitmapFactory;

public class WebImageCache {

private static final String DISK_CACHE_PATH = "/web_image_cache/";

private ConcurrentHashMap<String, SoftReference<Bitmap>> memoryCache;

private String diskCachePath;

private boolean diskCacheEnabled = false;

private ExecutorService writeThread;

public WebImageCache(Context context) {

// Set up in-memory cache store

memoryCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>();

// Set up disk cache store

Context appContext = context.getApplicationContext();

diskCachePath = appContext.getCacheDir().getAbsolutePath() + DISK_CACHE_PATH;

File outFile = new File(diskCachePath);

outFile.mkdirs();

diskCacheEnabled = outFile.exists();

// Set up threadpool for image fetching tasks

writeThread = Executors.newSingleThreadExecutor();

}

public Bitmap get(final String url) {

Bitmap bitmap = null;

// Check for image in memory

bitmap = getBitmapFromMemory(url);

// Check for image on disk cache

if(bitmap == null) {

bitmap = getBitmapFromDisk(url);

// Write bitmap back into memory cache

if(bitmap != null) {

cacheBitmapToMemory(url, bitmap);

}

}

return bitmap;

}

public void put(String url, Bitmap bitmap) {

cacheBitmapToMemory(url, bitmap);

cacheBitmapToDisk(url, bitmap);

}

public void remove(String url) {

if(url == null){

return;

}

// Remove from memory cache

memoryCache.remove(getCacheKey(url));

// Remove from file cache

File f = new File(diskCachePath, getCacheKey(url));

if(f.exists() && f.isFile()) {

f.delete();

}

}

public void clear() {

// Remove everything from memory cache

memoryCache.clear();

// Remove everything from file cache

File cachedFileDir = new File(diskCachePath);

if(cachedFileDir.exists() && cachedFileDir.isDirectory()) {

File[] cachedFiles = cachedFileDir.listFiles();

for(File f : cachedFiles) {

if(f.exists() && f.isFile()) {

f.delete();

}

}

}

}

private void cacheBitmapToMemory(final String url, final Bitmap bitmap) {

memoryCache.put(getCacheKey(url), new SoftReference<Bitmap>(bitmap));

}

private void cacheBitmapToDisk(final String url, final Bitmap bitmap) {

writeThread.execute(new Runnable() {

@Override

public void run() {

if(diskCacheEnabled) {

BufferedOutputStream ostream = null;

try {

ostream = new BufferedOutputStream(new FileOutputStream(new File(diskCachePath, getCacheKey(url))), 2*1024);

bitmap.compress(CompressFormat.PNG, 100, ostream);

} catch (FileNotFoundException e) {

e.printStackTrace();

} finally {

try {

if(ostream != null) {

ostream.flush();

ostream.close();

}

} catch (IOException e) {}

}

}

}

});

}

private Bitmap getBitmapFromMemory(String url) {

Bitmap bitmap = null;

SoftReference<Bitmap> softRef = memoryCache.get(getCacheKey(url));

if(softRef != null){

bitmap = softRef.get();

}

return bitmap;

}

private Bitmap getBitmapFromDisk(String url) {

Bitmap bitmap = null;

if(diskCacheEnabled){

String filePath = getFilePath(url);

File file = new File(filePath);

if(file.exists()) {

bitmap = BitmapFactory.decodeFile(filePath);

}

}

return bitmap;

}

private String getFilePath(String url) {

return diskCachePath + getCacheKey(url);

}

private String getCacheKey(String url) {

if(url == null){

throw new RuntimeException("Null url passed in");

} else {

return url.replaceAll("[.:/,%?&=]", "+").replaceAll("[+]+", "+");

}

}

}

9 需要的实体NewInfo.java

package com.itheima28.neteasedemo.domain;

/**

* @author andong

* 新闻信息实体类

*/

public class NewInfo {

private String title; // 标题

private String detail; // 详细

private Integer comment; // 跟帖数量

private String imageUrl; // 图片连接

@Override

public String toString() {

return "NewInfo [title=" + title + ", detail=" + detail + ", comment="

+ comment + ", imageUrl=" + imageUrl + "]";

}

public NewInfo(String title, String detail, Integer comment, String imageUrl) {

super();

this.title = title;

this.detail = detail;

this.comment = comment;

this.imageUrl = imageUrl;

}

public NewInfo() {

super();

// TODO Auto-generated constructor stub

}

public String getTitle() {

return title;

}

public void setTitle(String title) {

this.title = title;

}

public String getDetail() {

return detail;

}

public void setDetail(String detail) {

this.detail = detail;

}

public Integer getComment() {

return comment;

}

public void setComment(Integer comment) {

this.comment = comment;

}

public String getImageUrl() {

return imageUrl;

}

public void setImageUrl(String imageUrl) {

this.imageUrl = imageUrl;

}

}

10 Activity中的代码如下:

package com.itheima28.neteasedemo;

import java.io.InputStream;

import java.util.ArrayList;

import java.util.List;

import org.apache.http.HttpResponse;

import org.apache.http.client.HttpClient;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.DefaultHttpClient;

import org.xmlpull.v1.XmlPullParser;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

import android.util.Xml;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.ListView;

import android.widget.TextView;

import android.widget.Toast;

import com.itheima28.neteasedemo.domain.NewInfo;

import com.loopj.android.image.SmartImageView;

public class MainActivity extends Activity {

private static final String TAG = "MainActivity";

private final int SUCCESS = 0;

private final int FAILED = 1;

private ListView lvNews;

private List<NewInfo> newInfoList;

private Handler handler = new Handler() {

/**

* 接收消息

*/

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case SUCCESS:// 访问成功, 有数据

// 给Listview列表绑定数据

newInfoList = (List<NewInfo>) msg.obj;

MyAdapter adapter = new MyAdapter();

lvNews.setAdapter(adapter);

break;

case FAILED:  // 无数据

Toast.makeText(MainActivity.this, "当前网络崩溃了.", 0).show();

break;

default:

break;

}

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

init();

}

private void init() {

lvNews = (ListView) findViewById(R.id.lv_news);

// 抓取新闻数据

new Thread(new Runnable() {

@Override

public void run() {

// 获得新闻集合

List<NewInfo> newInfoList = getNewsFromInternet();

Message msg = new Message();

if(newInfoList != null) {

msg.what = SUCCESS;

msg.obj = newInfoList;

} else {

msg.what = FAILED;

}

handler.sendMessage(msg);

}

}).start();

}

/**

* 返回新闻信息

*/

private List<NewInfo> getNewsFromInternet() {

HttpClient client = null;

try {

// 定义一个客户端

client = new DefaultHttpClient();

// 定义get方法

HttpGet get = new HttpGet("http://114.215.142.191:8080/NetEaseServer/new.xml");

// 执行请求

HttpResponse response = client.execute(get);

int statusCode = response.getStatusLine().getStatusCode();

if(statusCode == 200) {

InputStream is = response.getEntity().getContent();

List<NewInfo> newInfoList = getNewListFromInputStream(is);

return newInfoList;

} else {

Log.i(TAG, "访问失败: " + statusCode);

}

} catch (Exception e) {

e.printStackTrace();

} finally {

if(client != null) {

client.getConnectionManager().shutdown();     // 关闭和释放资源

}

}

return null;

}

/**

* 从流中解析新闻集合

* @param is

* @return

*/

private List<NewInfo> getNewListFromInputStream(InputStream is) throws Exception {

XmlPullParser parser = Xml.newPullParser();   // 创建一个pull解析器

parser.setInput(is, "utf-8");   // 指定解析流, 和编码

int eventType = parser.getEventType();

List<NewInfo> newInfoList = null;

NewInfo newInfo = null;

while(eventType != XmlPullParser.END_DOCUMENT) { // 如果没有到结尾处, 继续循环

String tagName = parser.getName(); // 节点名称

switch (eventType) {

case XmlPullParser.START_TAG: // <news>

if("news".equals(tagName)) {

newInfoList = new ArrayList<NewInfo>();

} else if("new".equals(tagName)) {

newInfo = new NewInfo();

} else if("title".equals(tagName)) {

newInfo.setTitle(parser.nextText());

} else if("detail".equals(tagName)) {

newInfo.setDetail(parser.nextText());

} else if("comment".equals(tagName)) {

newInfo.setComment(Integer.valueOf(parser.nextText()));

} else if("image".equals(tagName)) {

newInfo.setImageUrl(parser.nextText());

}

break;

case XmlPullParser.END_TAG: // </news>

if("new".equals(tagName)) {

newInfoList.add(newInfo);

}

break;

default:

break;

}

eventType = parser.next();      // 取下一个事件类型

}

return newInfoList;

}

class MyAdapter extends BaseAdapter {

/**

* 返回列表的总长度

*/

@Override

public int getCount() {

return newInfoList.size();

}

/**

* 返回一个列表的子条目的布局

*/

@Override

public View getView(int position, View convertView, ViewGroup parent) {

View view = null;

if(convertView == null) {

LayoutInflater inflater = getLayoutInflater();

view = inflater.inflate(R.layout.listview_item, null);

} else {

view = convertView;

}

// 重新赋值, 不会产生缓存对象中原有数据保留的现象

SmartImageView sivIcon = (SmartImageView) view.findViewById(R.id.siv_listview_item_icon);

TextView tvTitle = (TextView) view.findViewById(R.id.tv_listview_item_title);

TextView tvDetail = (TextView) view.findViewById(R.id.tv_listview_item_detail);

TextView tvComment = (TextView) view.findViewById(R.id.tv_listview_item_comment);

NewInfo newInfo = newInfoList.get(position);

sivIcon.setImageUrl(newInfo.getImageUrl());      // 设置图片

tvTitle.setText(newInfo.getTitle());

tvDetail.setText(newInfo.getDetail());

tvComment.setText(newInfo.getComment() + "跟帖");

return view;

}

@Override

public Object getItem(int position) {

return null;

}

@Override

public long getItemId(int position) {

return 0;

}

}

}

至此,代码完成,相应的资源图片可以自己找图片替代。

上一篇:(转)聊聊Greenplum的那些事


下一篇:2019-02-18 扩展Python控制台实现中文反馈信息之二-正则替换