Android 学习之获取网络文本文件

上次我们学习如何从网络上获取一张图片,今天我们学习如何从网络上获取文本文件,以XML文件为例子。因为XML文件在实际开发中最为常见。

我们以下面图片为例子学习如何从网络上获取XML文件

我们的xml文件为:

<?xml version="1.0" encoding="UTF-8" ?>
<newslist>
	<news>
		<title>9月起办理手机卡需实名认证</title>
		<detail>方案要求,从2015年2月1日起,基础电信企业和虚拟运营商的各类营销渠道在为用户办理电话入网手续时,停止人工录入方式,改用专用移动应用程序</detail>
		<comment>15687</comment>
		<image>http://192.168.1.100:8080/images/6.jpg</image>
	</news>
	<news>
		<title>富士康50亿美元印度建厂 中国制造成本直逼美国</title>
		<detail>中国制造”和“印度制造”正展开新一轮的竞争与合作关系。全球最大的代工企业、中国台湾的富士康8月8日在印度签约,它到印度投资设厂的计划变为现实</detail>
		<comment>16359</comment>
		<image>http://192.168.1.100:8080/images/7.jpg</image>
	</news>
	<news>
		<title>刘强东也学乔布斯 加入“1元年薪”俱乐部</title>
		<detail>8月8日,京东集团董事长兼CEO刘强东与奶茶妹妹的结婚证照片在朋友圈里刷屏了。可就在前一天,刘强东还将自己未来十年的年薪降至1元</detail>
		<comment>14112</comment>
		<image>http://192.168.1.100:8080/images/7.jpg</image>
	</news>

后面的太长省略了。

既然我们要将xml文件中的内容显示到界面上,那必须先要拿到xml文件中的内容。

1: 从网络上获取XML文件的内容

开启一个子线程从网络上获取服务器的数据

public void getNewsInfo()
    {
    	//在子线程中获取服务器的数据
    	Thread thread = new Thread(){
    		@Override
    		public void run() {
    	    	//1:确定地址
    	    	String path = "http://192.168.1.123:8080/news.xml";
    			try {
    				URL url = new URL(path);
    				//建立连接
    				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    				//设置请求方式
    				conn.setRequestMethod("GET");
    				//设置请求超时时间
    				conn.setConnectTimeout(5000);
    				//设置读取超时时间
    				conn.setReadTimeout(5000);
    				//判断是否获取成功
    				if(conn.getResponseCode() == 200)
    				{
    					//获得输入流
    					InputStream is = conn.getInputStream();
    					//解析输入流中的数据
    					parseXmlInfo(is);
    				}
    			} catch (Exception e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	};

    	//启动线程
    	thread.start();
    }

获取到服务器给的数据,然后解析XML文件,解析XML文件我们使用的是PULL解析器

public void parseXmlInfo(InputStream is)
    {
    	/*我们用pull解析器解析xml文件*/

    	//1.先拿到pull解析器
    	XmlPullParser xParser = Xml.newPullParser();

    	try {

			xParser.setInput(is, "utf-8");
			//获取事件的类型
			int eventType = xParser.getEventType();
			News news = null;
			while(eventType != XmlPullParser.END_DOCUMENT)
			{
				switch (eventType) {
				case XmlPullParser.START_TAG:
					//当事件的开始类型newslist,代表的是xml文件的数据开始
					if("newslist".equals(xParser.getName()))
					{
						//这时候我们就new出来一个list,用于保存数据
						newList = new ArrayList<News>();
					}//当事件类型是news,说明是一条新闻
					else if ("news".equals(xParser.getName())) {
						//new出一个news的对象
						news = new News();
					}
					else if ("detail".equals(xParser.getName())) {
						String detail = xParser.nextText();
						 news.setDetail(detail);
					}
					else if ("title".equals(xParser.getName())) {
						String title = xParser.nextText();
						 news.setTitle(title);
					}
					else if ("comment".equals(xParser.getName())) {
						String comment = xParser.nextText();
						 news.setComment(comment);
					}
					else if ("image".equals(xParser.getName())) {
						String image = xParser.nextText();
						 news.setImage(image);
					}
					break;
				case XmlPullParser.END_TAG:
					//当结束时间是news时,说明一条news已经解析完成,并且加入到集合中
					if("news".equals(xParser.getName()))
					{
						newList.add(news);
					}
					break;
				}

				eventType = xParser.next();
			}

			//打印
			for (News n : newList) {
				System.out.println(n.toString());
			}			

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

    }

打印为:

可以看到我们是从服务器取到了数据,并且数据是正确的。

2: 既然可以正确的取到数据,那我们就将数据显示到界面上,既然要显示, 那就的用listview,既然要用listview,那就必须为listview的每一个增加一个布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:context="${relativePackage}.${activityClass}" >

    <ImageView
        android:id="@+id/iv"
        android:layout_width="90dp"
        android:layout_height="70dp"
        android:src="@drawable/ic_launcher"
        android:layout_centerVertical="true"
        />
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="大标题"
        android:textSize="20sp"
        android:layout_toRightOf="@id/iv"
        android:singleLine="true"
        />

    <TextView
        android:id="@+id/tv_detail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这是新闻的详细信息"
        android:textSize="15sp"
        android:textColor="@android:color/darker_gray"
        android:lines="2"
        android:layout_toRightOf="@id/iv"
        android:layout_below="@id/tv_title"
        />

    <TextView
        android:id="@+id/tv_comment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="19999"
        android:textColor="#FF0000"
        android:layout_alignParentRight="true"
        android:layout_below="@id/tv_detail"
        />
</RelativeLayout>

我们找到listview,然后设置Adapter即可

	        ListView lv = (ListView) findViewById(R.id.lv);
	        lv.setAdapter(new MyAdapter());
class MyAdapter extends BaseAdapter
    {

		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return newList.size();
		}

		@Override
		public Object getItem(int arg0) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public long getItemId(int arg0) {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			//取到一条新闻
			News news = newList.get(position);
			//找到一个view对象
			View v = View.inflate(MainActivity.this, R.layout.item_listview, null);

			//根据ID找到控件
			TextView tv_title = (TextView) v.findViewById(R.id.tv_title);
			TextView tv_detail = (TextView) v.findViewById(R.id.tv_detail);
			TextView tv_comment = (TextView) v.findViewById(R.id.tv_comment);
			ImageView siv = (ImageView)v.findViewById(R.id.iv);

			//设置数据
			tv_title.setText(news.getTitle());
			tv_detail.setText(news.getDetail());
			tv_comment.setText(news.getComment() + "条评论");
			siv.setImageResource(R.drawable.ic_launcher);
			return v;
		}
}

运行看效果,之前,我需要贴出OnCreate方法

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getNewsInfo();

        ListView lv = (ListView) findViewById(R.id.lv);
        lv.setAdapter(new MyAdapter());
    }

运行看效果:

运行效果为NULL指针异常,这是为什么呢?

既然NULL指针异常,代码是哪行有问题?  仔细一看是

lv.setAdapter(new MyAdapter());

这是因为,我们的获取服务器的数据是在一个子线程中运行的,而我们setAdapter的任务是在主线程中获取的,这时候当我们的服务器数据还没获取完毕,我们就设置数据了,就会导致异常发生。所以我们要当服务器的数据获取完后,才去设置adapter

修改代码:增加消息机制

		//当数据接受完成后,发生消息
			handler.sendEmptyMessage(1);

			//打印
			for (News n : newList) {
				System.out.println(n.toString());
			}
	//在消息中设置数据
	Handler handler = new Handler()
	{
		public void handleMessage(android.os.Message msg)
		{
	        ListView lv = (ListView) findViewById(R.id.lv);
	        lv.setAdapter(new MyAdapter());
		};
	};

这样的话就出现了刚开始的截图。但是我们还需要优化listview

优化后的listview

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

			News news = newList.get(position);
			ViewHolder mHolder;
			View v = null;
			//当缓冲为空的时候,创建view对象,并将组件封装到view的tag中
			if(convertView == null)
			{
				v = View.inflate(MainActivity.this, R.layout.item_listview, null);
				mHolder = new ViewHolder();

				mHolder.tv_title = (TextView) v.findViewById(R.id.tv_title);
				mHolder.tv_detail = (TextView) v.findViewById(R.id.tv_detail);
				mHolder.tv_comment = (TextView) v.findViewById(R.id.tv_comment);
				mHolder.siv = (ImageView)v.findViewById(R.id.iv);
				v.setTag(mHolder);
			}
			else {//当缓冲不为空时,就将缓冲的数据取出来用,不用重新创建,这样可节省系统资源
				v = convertView;
				mHolder =(ViewHolder) v.getTag();
			}
			//设置数据到组件
			mHolder.tv_title.setText(news.getTitle());
			mHolder.tv_detail.setText(news.getDetail());
			mHolder.tv_comment.setText(news.getComment() + "条评论");
			mHolder.siv.setImageResource(R.drawable.ic_launcher);
			return v;
		}
    	

这样我们的从服务端的获取数据就算完成了,但是我们还没获取服务器的图片资源,图片资源是通过一个地址封装到xml文件中的,我们需要再次拿到xml文件中的图片地址再次请求服务器获取图片资源,关于如何获取服务器图片资源我上节都讲过了,这里就不做了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 05:40:40

Android 学习之获取网络文本文件的相关文章

Android 通过广播获取网络状态

Android系统网络连接状态的改变会发一个广播,注册一个广播接收者,实时动态的检测网络状态,及时提醒用户,优化用户体验. 本文仅提供WIFI 状态的检测作为参考,其他网络连接方式请对比WIFI连接作出调整. 首先写一个WifiStateBroadcast类继承BroadcastReceiver,重写onRecevie方法,获取网络连接状态管理器,通过管理器拿到对应的网络信息,得到网络状态,判断网络状态,作出相应的业务逻辑. 1 public class WifiStateBroadCast e

一起学android之如何获取网络类型并判断是否可用(20)

ConnectivityManager主要管理和网络连接相关的操作,通过getSystemService(Context.CONNECTIVITY_SERVICE)获 取网络连接的服务.因此我们可以通过ConnectivityManager这个类下的getActiveNetworkInfo()方法来获取当前的网络 连接状态,这个方法返回的是NetworkInfo对象, NetworkInfo描述了当前网络Mobile和Wifi的状态.NetworkInfo类中有 三个方法:(1)getType(

Android学习笔记-Wifi网络操作

Wifi网卡状态 WIFI_STATE_DISABLED Wifi网卡不可用 WIFI_STATE_DIABLING Wifi网卡正在关闭 WIFI_STATE_ENABLED Wifi网卡可用 WIFI_STATE_ENABLING Wifi网卡正在打开 WIFI_STATE_UNKNOWN 未知网卡状态 操作Wifi网卡所需要的权限 CHANGE_NETWORK_STATE 改变网络连接状态 CHANGE_WIFI_STATE 改变Wifi连接状态 ACCESS_NETWORK_STATE

Android 学习笔记---获取RadioGroup的选定值

1,获取RadioGroup控件: RadioGroup radioGroup = (RadioGroup)findViewById(R.id.myRadioGroup); 2,获取RadioButton控件; RadioButton radioButton = (RadioButton)findViewById(radioGroup.getCheckedRadioButtonId()); 3,获取选中的radio的值: String text = radioButton.getText().t

Android学习笔记--获取传感器信息

原文链接:http://www.open-open.com/lib/view/open1423812538326.html android 4.4 (API等级19)支持以下传感器: (注意并不是所有的手机都支持全部的传感器) TYPE_ACCELEROMETER 加速度传感器,单位是m/s2,测量应用于设备X.Y.Z轴上的加速度 传感器类型值(Sensor Type):1 (0x00000001) TYPE_AMBIENT_TEMPERATURE 温度传感器,单位是℃ 传感器类型值(Senso

Android学习之获取系统应用信息列表的实现

前言: 好几天电脑打不开CSDN博客,也不知道怎么回事,今天下班回来突然能打开了,遂将周末实现的一个效果贴上. 实现功能: 获取手机应用图标,名称,时间(安装时间/更新时间),大小,侧滑删除应用,点击应用图标分享等功能. 目标效果: 思路:RecylerView+swipereveallayout 贴上dependencies 介绍:Glide实现图片加载,EventBus通信,swipereveallayout实现侧滑. 获取数据源: private ArrayList<AppInfoMode

Android学习笔记-获取手机内存,SD卡存储空间。

前面介绍到如何保存数据到手机内存或者SD卡,但是问题是,在保存以前,我们还需要对他们的空间(可用空间),进行判断,才可以进行后续操作,所以,本节我们就介绍如何获取手机内存以及Sd卡的空间. //这时获取手机内存的 // File path = Environment.getDataDirectory(); //这时获取SD卡的空间 File path = Environment.getExternalStorageDirectory(); StatFs stat = new StatFs(pat

android 学习随笔八(网络)

1.简单新闻客户端 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:c

Android解析获取网络上的图片(支持bmp格式)

Android学习系列 - 显示网络上的图片(支持bmp格式)) 见如下代码: /** * 到Url地址上去下载图片,并回传Bitmap回來 * * @param imgUrl * @return */ public static Bitmap getBitmapFromUrl(String imgUrl) { URL url; Bitmap bitmap = null; try { url = new URL(imgUrl); InputStream is = url.openConnecti