一、服务器端 生成XML数据
①新建Web工程Web_AsyncTask_Xml
空白处右键->new->other->Web->Dynamic Web Project
②创建XML文件citys.xml
工程下面的WebContent右键->New ->other->XML->XMLFile->citys.xml,把新建的citys.xml文件拷贝一份放到包com.city.action下面,产生数据源,也就是说我在这个包里面把这个XML文件读出来,变成一个字符串而不是访问一个文件。(假设用手机访问天气预报,如果现在天气预报返回的格式是XML, 当然这些数据是来自数据库,我们根本没有必要让这些数据生成一个文件,让用户再读这个文件。做练习是这样的,但是,实际开发开发并不是这样的, 只需要在数据库中读取数据,直接把这些数据变成字符串,这样就少了一次Io读写。)
<?xml version="1.0" encoding="UTF-8"?>
<citys>
<city>
<name>Beijing</name>
</city>
<city>
<name>上海</name>
</city>
<city>
<name>广州</name>
</city>
<city>
<name>深圳</name>
</city>
</citys>
③在包com.city.action下面创建CityAction.java,接着创建CityDataSource.java(仿照上一篇Android之异步任务AsyncTask解析Json数据)
CityAction.java
package com.city.action;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONSerializer;
/**
* Servlet implementation class CityAction
*/
@WebServlet("/CityAction")
public class CityAction extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public CityAction() {
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
this.doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
request.setCharacterEncoding("utf-8");
PrintWriter writer=response.getWriter();
String type=request.getParameter("type");
if(type.equals("xml")){
String xmlString=CityDataSource.getCityListXML();//取出xml
writer.println(xmlString);
}
writer.flush();
writer.close();
}
}
CityDataSource.java
package com.city.action;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
public class CityDataSource {
public CityDataSource() {
// TODO Auto-generated constructor stub
}
/**
* 假设用手机访问天气预报,如果现在天气预报返回的格式是XML, 当然这些数据是来自数据库,我们根本没有必要让这些数据生成一个文件,
* 让用户再读这个文件。做练习是这样的,但是,实际开发开发并不是这样的, 只需要在数据库中读取数据,直接把这些数据变成字符串,这样就少了一次Io读写。
*
* 使用InputStream去读,把XML变成一个字符串
*
*
* 服务器端的工作:把把字节流读取出来,放到StringBuilder中,并且什么都没解析,直接把结果通过一个字符串返回给客户端
* @return
*/
public static String getCityListXML() {
InputStream inputStream = CityDataSource.class.getClassLoader()
.getResourceAsStream("com/city/action/citys.xml");// 通过类的反射,得到一个类的加载器,然后用这个类的加载器去加载一个文件,这个文件就是一个流
Reader reader=new InputStreamReader(inputStream,Charset.forName("utf-8"));//解决乱码
BufferedReader bufferedReader=new BufferedReader(reader);//把一个流文件转换成字符串,把字节流转成字符流
String value="";
StringBuilder builder=new StringBuilder();
try {
while((value=bufferedReader.readLine())!=null){
builder.append(value);
}
//System.out.println(builder.toString());
//return new String(builder.toString().getBytes("iso8859-1"),"utf-8");//如果有乱码问题则加上这句话,在getCityListXML方法返回null
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(bufferedReader!=null){
try {
bufferedReader.close();
} catch (Exception e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
}
}
//return list;
return builder.toString();
//return null;//如果有乱码,则加上getBytes("iso8859-1"),"utf-8")后再加上这句
}
public static void main(String[] args) {
getCityListXML();
}
}
在地址栏输入http://192.168.1.100:8080/Web_AsyncTask_Xml/CityAction?type=xml显示如下
二、手机客户端
activity_main.xml
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.android_asynctask_xml.MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="31dp"
android:layout_marginTop="102dp"
android:textSize="20sp"
android:text="所属城市:" />
<Spinner
android:id="@+id/spinner1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/textView1"
android:layout_marginLeft="14dp"
android:layout_toRightOf="@+id/textView1" />
</RelativeLayout>
①添加访问网络权限
②新建包com.example.android_asynctask_xml.http,在包里面创建HttpUtils.java工具类
package com.example.android_asynctask_xml.http;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
public class HttpUtils {
public HttpUtils() {
// TODO Auto-generated constructor stub
}
/**
*
* @param path 获取指定路径的json信息
* @param encoding 指定编码格式
* @return
*/
public static String sendPostMethod(String path,String encoding){
String result="";
HttpClient httpClient=new DefaultHttpClient();
try {
HttpPost post=new HttpPost(path);
HttpResponse response=httpClient.execute(post);
if(response.getStatusLine().getStatusCode()==200){
result=EntityUtils.toString(response.getEntity(), encoding);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
httpClient.getConnectionManager().shutdown();//关闭连接
}
return result;
}
}
③新建包com.example.android_asynctask_xml.Entity,在包里面创建实体类City.java
package com.example.android_asynctask_xml.Entity;
public class City {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
④新建包com.example.android_asynctask_xml.xml,在包里面创建工具类XMLTools.java
package com.example.android_asynctask_xml.xml;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import com.example.android_asynctask_xml.Entity.City;
public class XMLTools {
public XMLTools() {
// TODO Auto-generated constructor stub
}
/**
*
* 解析XML文件
* 利用XML解析工厂XmlPullParserFactory,通过工厂new一个解析器newPullParser
*
* 在Mainactivity.java中调用
* @param xmlString
* @return
*/
public static List<City> parseXML(String xmlString){
List<City> list=null;
City city=null;
try {
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
XmlPullParser parser=factory.newPullParser();
parser.setInput(new StringReader(xmlString));
int eventType=parser.getEventType();
while(eventType!=XmlPullParser.END_DOCUMENT){
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
list=new ArrayList<City>();
break;
case XmlPullParser.START_TAG:
if("city".equals(parser.getName())){
city=new City();
}else if("name".equals(parser.getName())){
String name=parser.nextText();
city.setName(name);
}
break;
case XmlPullParser.END_TAG:
if("city".equals(parser.getName())){
list.add(city);
city=null;
}
break;
}
eventType=parser.next();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return list;
}
}
⑤在包com.example.android_asynctask_xml里面MainActivity.java
package com.example.android_asynctask_xml;
import java.util.ArrayList;
import java.util.List;
import com.example.android_asynctask_xml.Entity.City;
import com.example.android_asynctask_xml.http.HttpUtils;
import com.example.android_asynctask_xml.xml.XMLTools;
import android.support.v7.app.ActionBarActivity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
public class MainActivity extends ActionBarActivity {
private final String TAG="MainActivity";
private Spinner spinner1;
private final String CITY_PATH="http://192.168.1.100:8080/Web_AsyncTask_Xml/CityAction?type=xml";
private ArrayAdapter<String> adapter;
private ProgressDialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner1=(Spinner) this.findViewById(R.id.spinner1);//加载Spinner控件
//adapter=new ArrayAdapter<String>(context, resource, textViewResourceId);
//spinner1.setAdapter(adapter);//这句话执行完之后,数据就已经有了,所以这行代码应该在另外一个线程中实现,然后再更新UI
dialog=new ProgressDialog(MainActivity.this);
dialog.setTitle("提示");
dialog.setMessage("正在加载...");
new MyTask().execute(CITY_PATH);//执行异步任务
}
class MyTask extends AsyncTask<String, Void, List<City>>{
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
dialog.show();
}
@Override
protected void onPostExecute(List<City> result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
List<String> list=new ArrayList<String>();
for(int i=0;i<result.size();i++){
list.add(result.get(i).getName());
}
adapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_dropdown_item, list);//构建适配器
spinner1.setAdapter(adapter);
dialog.dismiss();
}
/**
* 注意:在做Android开发过程中HttpUtils和JsonTools工具类是必须要有的
* 在一个项目中json数据格式有可能有四到五种,所以工具类里的方法要有四到五个方法来解析
*/
@Override
protected List<City> doInBackground(String... params) {
// TODO Auto-generated method stub
List<City> list=null;
String xmlString=HttpUtils.sendPostMethod(params[0], "utf-8");
//Log.i(TAG, "--->>"+xmlString);//验证能否将xml数据取到本地
list=XMLTools.parseXML(xmlString);
//System.out.println("--list--"+list);
return list;
}
//List<String>这个结果表示json解析之后的结果,结果会很快塞到适配器当中
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
具体步骤可以借鉴上一篇
Android之异步任务AsyncTask解析Json数据
运行效果图