首页 > 代码库 > 安卓开发之抓取新闻案例

安卓开发之抓取新闻案例

 一、概述
这是一个通过HttpClient抓取网页新闻的demo。涉及知识点:通过HttpClient从网络获取新闻(组织成XML格式的),pull解析XML,Android下ListView的使用及优化,将XML资源文件转成视图view显示,安卓下的简单布局,Android消息处理机制。这里使用到的网页新闻是用tomcat下的一个WEB应用中的new.xml来模拟的,虚拟机访问本机可通过如下链接:http://10.0.2.2:8080/应用名称/new.xml 。

二、步骤  

下面说一下思路:将新闻内容封装到JavaBean中(新闻内容包括图片、标题、详细信息、跟帖数量),当Activity被创建时,开启一个子线程去访问网络资源(因为Android4.0以后不支持主线程访问网络资源,会抛出异常:

技术分享

)。解析得到的XML文件,遍历节点得到新闻信息并封装成bean添加到集合中,将此集合通过Message发送给主线程的Handler对象去处理(只有主线程可以修改用户界面),然后自定义一个适配器,将新闻bean的内容添加到指定的控件上,为ListVIew指定当前适配器来显示新闻。

主要代码分成如下几个部分:

1.从网络获取XML文件的输入流

	/**
	 * 从网络上获取新闻输入流
	 * @return 新闻bean组成的list集合
	 */
	protected List<NewsInfo> getNewsFromIntenet() {
		HttpClient client = null;
		try {
			// 定义一个客户端
			client = new DefaultHttpClient();
			HttpGet get = new HttpGet("http://10.0.2.2:8080/Example/new.xml");// 访问网络资源
			HttpResponse response = client.execute(get);// 执行get请求得到响应
			int code = response.getStatusLine().getStatusCode();// 获得状态码
			if(code == 200){// 请求成功,得到数据并返回
				InputStream in = response.getEntity().getContent();// 获得内容输入流
				newsList = getNewsListFromInputStream(in);// 根据流解析指定XML
				return newsList;// 返回新闻bean组成的list集合
			}else{
				// 请求失败,打印日志
				Log.i(TAG, "请求失败,请检查代码" + code);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(client != null){
				client.getConnectionManager().shutdown();// 关闭客户端资源
			}
		}
		return null;
	}

2.通过解析XML文件获得新闻bean组成的list

/**
	 * 从XML中解析newsList
	 * @return News组成的集合
	 * @throws Exception 
	 */
	private List<NewsInfo> getNewsListFromInputStream(InputStream in) throws Exception {
		XmlPullParser parser = Xml.newPullParser();// 创建一个解析XML的pull解析器
		parser.setInput(in, "utf-8");
		int eventType = parser.getEventType();// 获取事件类型
		List<NewsInfo> list = null;
		NewsInfo newsInfo = null;
		while(eventType != XmlPullParser.END_DOCUMENT){
			String tagName = parser.getName();// 获取标签名
			switch(eventType){
			case XmlPullParser.START_TAG:// 设置指定的内容
				if("news".equals(tagName)){
					list = new ArrayList<NewsInfo>();
				}else if("new".equals(tagName)){
					newsInfo = new NewsInfo();
				}else if("title".equals(tagName)){
					newsInfo.setTitle(parser.nextText());
				}else if("detail".equals(tagName)){
					newsInfo.setDetail(parser.nextText());
				}else if("comment".equals(tagName)){
					newsInfo.setComment(Integer.valueOf(parser.nextText()));
				}else if("image".equals(tagName)){
					newsInfo.setImage(parser.nextText());
				}
				break;
			case XmlPullParser.END_TAG:
				if("new".equals(tagName)){// 一个new结束,将封装好的新闻bean添加到集合中
					list.add(newsInfo);
				}
				break;
				default:
					break;
			}
			eventType = parser.next();// 取下一个事件类型
		}
		return list;
	}

3.将获取到的信息通过Message发送给Handler

	/**
	 * 初始化操作,开启新的线程去网络获取资源
	 */
	public void init() {
		lvNews = (ListView) findViewById(R.id.lv_news);// 找到用来显示新闻的ListView
		new Thread(new Runnable(){// 开启一个线程去访问网络资源
			@Override
			public void run() {
				List<NewsInfo> newsList = getNewsFromIntenet();
				Message msg = new Message();
				if(newsList != null){
					msg.what = SUCCESS;// 指定消息类型
					msg.obj = newsList;
				}else{
					msg.what = FAILED;
				}
				handler.sendMessage(msg);// 发送消息
			}
		}).start();// 开启线程
	}

4.Handler根据Message类型进行相应处理:list为空提示错误,不为空通过适配器将信息展示在ListView上

<span style="color:#ff0000;">	</span>	public View getView(int position, View convertView, ViewGroup parent) {
			View view = null;
			ViewHolder holder = null;
			if(convertView == null){
				
				holder = new ViewHolder();
				view = View.inflate(MainActivity.this, R.layout.layout_news_list, null);
				
				SmartImageView sivIcon = (SmartImageView) view.findViewById(R.id.image);
				sivIcon.setImageUrl(newsList.get(position).getImage());		// 设置图片
				
				holder.tv_title = (TextView) view.findViewById(R.id.tv_title);
				holder.tv_title.setText(newsList.get(position).getTitle());
				holder.tv_comment = (TextView) view.findViewById(R.id.tv_comment);
				holder.tv_comment.setText(newsList.get(position).getComment() + "跟帖");
				holder.tv_detail = (TextView) view.findViewById(R.id.tv_detail);
				holder.tv_detail.setText(newsList.get(position).getDetail());
				
				view.setTag(holder);// 将holder对象中的成员变量添加到view中
			}else{
				view = convertView;
				holder = (ViewHolder) view.getTag();
			}
			return view;
		}
	}
	
	/**
	 * 用来优化重用view的类
	 */
	class ViewHolder{
		public TextView tv_title;
		public TextView tv_detail;
		public TextView tv_comment;
		public ImageView iv_image;
	}

要注意的:

将XML资源文件转成view有三种方法,底层实现是一样的,这里使用如下方式:view = View.inflate(MainActivity.this, R.layout.layout_news_list, null);

在优化ListView时,可以通过重用convertView减少创建view的次数,再进一步,可通过定义一个类将view中控件声明成成员,如上面的ViewHolder类。

最后,上一个效果图吧:

技术分享

安卓开发之抓取新闻案例