从零开始,我们来做一个河北省空气质量自动发布系统的客户端,这这个软件的制作过程中,我会介绍关于信息获取,异步获取网络数据,数据分析,界面设计和程序逻辑等内容,下面介绍一个完整的程序是如何做出来的。文章面向0基础的、只看过一点安卓教程的同学,对于比较基础的内容,也会用红字的链接标出,大家可以点开看详细的介绍。
其实做这个,完全是因为老爸的原因,河北的空气质量太差了,所以他决定天天根据空气质量来决定散步不散步。总是上这个网站过于复杂,于是我就有了做一个客户端的想法。
首先需要找到程序的数据源,找到从网上获得数据接口的网址。
其次,要把数据从网上的格式,转换成我们可以使用的格式。
接下来进行布局的设计,最后把数据填充到布局里,整个程序就完成了。
下面是这个系统的网站,和我做的客户端:
public static String HttpGet(String url) throws ClientProtocolException, IOException {
//新建一个默认的连接
DefaultHttpClient client = new DefaultHttpClient();
//新建一个Get方法
HttpGet get = new HttpGet(url);
//得到网络的回应
HttpResponse response = client.execute(get);
//获得的网页源代码(xml)
String content = null;
//如果服务器响应的是OK的话!
if (response.getStatusLine().getStatusCode() == 200) {
//以下是把网络数据分段读取下来的过程
InputStream in = response.getEntity().getContent();
byte[] data = new byte[1024];
int length = 0;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
while ((length = in.read(data)) != -1) {
bout.write(data, 0, length);
}
//最后把字节流转为字符串 转换的编码为utf-8.
content = new String(bout.toByteArray(), "utf-8");
}
//返回得到的字符串 也就是网页源代码
return content;
}
class GetSource extends AsyncTask<String, Void, String>{
//此函数用来处理后台的事物
@Override
protected String doInBackground(String... params) {
try {
//这里调用了我们刚才写的下载函数
return Util.HttpGet("http://121.28.49.85:8080/datas/hour/130000.xml");
} catch (IOException e) {}
return null;
}
//后台事物完成后,此函数用来更改界面的内容
@Override
protected void onPostExecute(String result) {
//让Log输出运行时的记录
Log.i("test",result);
}
}new GetSource().execute();
<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:context=".MainActivity" >
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_time"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="#7a7"
android:padding="5dp"
android:textColor="#eee"
android:textSize="20sp"
android:textStyle="bold" />
<GridView
android:id="@+id/gv"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_margin="5dp"
android:horizontalSpacing="3dp"
android:verticalSpacing="3dp"
android:numColumns="3" >
</GridView>
</LinearLayout>
<ProgressBar
android:id="@+id/pb1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:visibility="visible"
android:layout_centerVertical="true" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="石家庄"
android:textColor="#4bd"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_aqi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="223"
android:textColor="#4bd"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
@Override
protected void onPostExecute(String result) {
//建立一个解析器
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
InputStream is = new ByteArrayInputStream(result.getBytes());
Document document = builder.parse(is);
Element element = document.getDocumentElement();
//获得所有的Citys节点数据
NodeList cityList = element.getElementsByTagName("Citys");
//获得mapstitle数据,并分解为两部分
NodeList title = element.getElementsByTagName("MapsTitle");
String text1 = title.item(0).getTextContent();
String t[] = text1.split("\\(");
text1 = t[0];
t = t[1].split(",");
tv_time.setText(text1+ "\n" +t[0]);
Element citys = (Element)cityList.item(0);
NodeList city = citys.getChildNodes();
for (int i=0;i < city.getLength();i++){
//此时的city节点的item上,有的是一个城市的所有数据
Node node = city.item(i);
if (node.getNodeName().equalsIgnoreCase("city")) { //这是一个有效的节点
CityData cd = new CityData(node);
nodeList.add(node);
cdList.add(cd);
}
}
} catch (Exception e) {}public class CityData implements Serializable{
/**
* 继承Serializable是为了在两个不同的界面中进行值的传递
*/
private static final long serialVersionUID = -8473485404751986234L;
//城市类包含了一个城市的数据
public String name,dataTime,aqi,level,maxPoll,color,intro,tips;
public List<Pointer> pointerList;
public CityData(Node cityNode) {
super();
//按标签挨个取出相应标签的内容
this.name = getByTag(cityNode, "name");
this.dataTime = getByTag(cityNode, "datatime");
this.aqi = getByTag(cityNode, "aqi");
this.level = getByTag(cityNode, "level");
this.maxPoll = getByTag(cityNode, "maxpoll");
String tmp = getByTag(cityNode, "color");
this.color = tmp.replace("0x", "#");
this.intro = getByTag(cityNode, "intro");
this.tips = getByTag(cityNode, "tips");
Element city = (Element)cityNode;
NodeList pointers = city.getElementsByTagName("Pointer");
//向city的pointer列表中添加监测点
pointerList = new ArrayList<Pointer>();
for (int i=0;i<pointers.getLength();i++){
Node pNode = pointers.item(i);
pointerList.add(new Pointer(pNode));
}
}
//从XML的node中取出相应标签中内容的function
private String getByTag(Node node,String tag) {
for (int i=0;i<node.getChildNodes().getLength();i++){
if (tag.equalsIgnoreCase(node.getChildNodes().item(i).getNodeName()))
return node.getChildNodes().item(i).getTextContent();
}
return null;
}
} class gvAdapter extends BaseAdapter{
//Adapter的数据源,根据这个数据来填充网格列表
List<CityData> cdList;
public gvAdapter(List<CityData> cdList) {
super();
this.cdList = cdList;
}
//根据数据的多少返回相应的数值
@Override
public int getCount() {
return cdList.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//解析之前写好的每个网格的布局
convertView = MainActivity.this.getLayoutInflater().inflate(R.layout.gv, null);
//找到布局中的元素,和布局的背景
TextView tv_city = (TextView)convertView.findViewById(R.id.tv_city);
TextView tv_aqi = (TextView)convertView.findViewById(R.id.tv_aqi);
View bg = convertView.findViewById(R.id.bg);
//根据数据填充每个格子的内容和背景色
tv_city.setText(cdList.get(position).name);
tv_aqi.setText(cdList.get(position).aqi);
bg.setBackgroundColor(Color.parseColor(cdList.get(position).color));
return convertView;
}
}gv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
//从当前的界面跳转到城市详细信息界面
Intent it = new Intent(MainActivity.this, CityActivity.class);
//对象本身无法使用Intent传递,但是我们继承了Serializable,使传递成为了可能
it.putExtra("node", cdList.get(position));
startActivity(it);
}
});<resources>
<string name="app_name">河北空气质量</string>
<string name="title_activity_city">城市数据</string>
</resources>这样,程序的名字就变成了“河北空气质量”,在进入到详细信息界面的时候,标题栏也变成了“城市数据”原文:http://blog.csdn.net/icyfox_bupt/article/details/18953581