今天终于把天气预报给弄出来了,心里小小的高兴一下,虽然这东西网上早就有了,但那毕竟是别人的。在想做这个之前,以为天气预报软件好高深,不知道从何下手。不过现在想想这东西也不是想象中那么复杂。最主要的是自己亲手做出来,感觉挺很爽的,要是有真机就更好了!
OK,在下面我把天气预报简单叫weather好了,在做weather之前我在网上有搜了一下有关它的资料,知道weather一般的是解析XML文档来获取信息。可能还有别的方式Json.... 然后再结合自己学的Android知识就可以完成本次小程序。本次写的weather里主要涉及到AutoCompleteTextView,ListView以及SAX技术 。先上weather运行时的效果图:
weather布局很丑,哎,俺没啥艺术细胞,只想到这样的布局,重在功能实现上。这次是用SAX解析XML,同样是用到了谷歌提供的天气接口。在上次的学习SAX解析 中里面我做的是解析本地的XML,很顺利。在做weather的同时我顺便写了个控制台版的天气预报,发现了有同样的问题:结果只出现温度,而中文信息却是乱码。在这上面我纠结了大半天后来才知道为什么,原因是编码不对,最后换成了GBK编码就搞定了 下面是代码片段。
1. URL url = new URL(path);
2. URLConnection conn = url.openConnection();
3. InputStreamReader isr = new InputStreamReader(conn.getInputStream(),"GBK"); //GBK编码就OK,用utf-8还是出现乱码
4. BufferedReader br = new BufferedReader(isr);
5. InputSource is = new InputSource(br);
6. xmlReader.parse(is);
复制代码
另外,ListView用SimpleAdapter加载图片,这个适配器的数据是键值对(Map)形式的,如果map中包含有图片,而这个图片不是在drawable中存在的,比如网络图片,simpleAdapter本身就不支持的。除非你重写适配器(Adapter),或者用ViewBinder 具体用法见API文档public void setViewBinder (SimpleAdapter.ViewBinder viewBinder)
SimpleAdapter的外部数据(external clients)可以使用这个类将值绑定到视图。你应该用这个类绑定值到那些不能直接通过SimpleAdapter支持的视图,或者改变通过SimpleAdapter支持绑定的方法的视图。
也就是说simpleAdapter不能直接支持ImageView,像TextView就直接支持,不用大费周章绑定数据。
下面是主类继承Activity
1. package com.weather.manymore13;
2.
3. import java.io.BufferedReader;
4. import java.io.IOException;
5. import java.io.InputStreamReader;
6. import java.io.UnsupportedEncodingException;
7. import java.net.MalformedURLException;
8. import java.net.URL;
9. import java.net.URLConnection;
10. import java.util.ArrayList;
11. import java.util.Map;
12.
13. import javax.xml.parsers.ParserConfigurationException;
14. import javax.xml.parsers.SAXParser;
15. import javax.xml.parsers.SAXParserFactory;
16.
17. import org.xml.sax.InputSource;
18. import org.xml.sax.SAXException;
19. import org.xml.sax.XMLReader;
20.
21. import android.app.Activity;
22. import android.content.Intent;
23. import android.graphics.Bitmap;
24. import android.graphics.Color;
25. import android.os.Bundle;
26. import android.text.StaticLayout;
27. import android.view.View;
28. import android.view.View.OnClickListener;
29. import android.widget.ArrayAdapter;
30. import android.widget.AutoCompleteTextView;
31. import android.widget.Button;
32. import android.widget.ImageView;
33. import android.widget.ListView;
34. import android.widget.SimpleAdapter;
35. import android.widget.SimpleAdapter.ViewBinder;
36. import android.widget.TextView;
37.
38. public class WeatherActivity extends Activity {
39. private AutoCompleteTextView autoText;
40. private Button btnConfirm;
41. private TextView tViewCurrent;
42. private ListView lv;
43. private ArrayList<Map<String,Object>> list;
44. private ImageView currentIcon;
45. private TextView currentInfo;
46. private TextView futionTime;
47. private SimpleAdapter simpAdapter = null;
48. private boolean visit = true;
49. public void init()
50. {
51. autoText = (AutoCompleteTextView)findViewById(R.id.autoTextView);
52. btnConfirm = (Button)findViewById(R.id.btn_confirm);
53. tViewCurrent = (TextView)findViewById(R.id.current_time);
54. lv = (ListView)findViewById(R.id.myListView);
55. currentIcon = (ImageView)findViewById(R.id.current_icon);
56. currentInfo = (TextView)findViewById(R.id.current_info);
57. futionTime = (TextView)findViewById(R.id.future_time);
58. }
59.
60. @Override
61. public void onCreate(Bundle savedInstanceState) {
62. super.onCreate(savedInstanceState);
63. setContentView(R.layout.main);
64. init();
65.
66.
67. ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>
68. (this, android.R.layout.simple_dropdown_item_1line,
69. Tools.city);
70. autoText.setAdapter(arrayAdapter);
71. btnConfirm.setOnClickListener(new OnClickListener() {
72.
73. public void onClick(View arg0) {
74.
75. System.out.println("按钮被按下");
76. String city = autoText.getText().toString().trim();
77.
78. tViewCurrent.setVisibility(View.INVISIBLE);
79. futionTime.setVisibility(View.INVISIBLE);
80. if(!(city.equals("")))
81. {
82. try {
83.
84.
85. obtainWeacherInfo(Tools.SEACH_URL+city);
86. if(simpAdapter!=null)
87. {
88. simpAdapter.notifyDataSetChanged();
89. }
90.
91.
92. } catch (MalformedURLException e) {
93. System.out.println("url出错");
94. e.printStackTrace();
95. }
96. catch (Exception e) {
97. e.printStackTrace();
98. }
99. }
100.
101. }
102. });
103.
104.
105. }
106.
107. public void obtainWeacherInfo(String path) throws ParserConfigurationException, SAXException, UnsupportedEncodingException, IOException
108. {
109.
110. SAXParserFactory parserFactory = SAXParserFactory.newInstance();
111.
112. SAXParser sp = parserFactory.newSAXParser();
113.
114. XMLReader xmlReader = sp.getXMLReader();
115.
116. WeacherHandler handler = new WeacherHandler();
117.
118. xmlReader.setContentHandler(handler);
119.
120. URL url = new URL(path);
121.
122. URLConnection conn = url.openConnection();
123.
124. InputStreamReader isr = new InputStreamReader(conn.getInputStream(),"GBK");
125.
126. BufferedReader br = new BufferedReader(isr);
127.
128. InputSource is = new InputSource(br);
129.
130. xmlReader.parse(is);
131.
132. br.close();
133.
134. displayWeatherInfo(handler);
135.
136. }
137.
138.
139. public void displayWeatherInfo(WeacherHandler handler)
140. {
141. list = handler.getForecastWeachers();
142.
143. //显示实时信息
144. Bitmap bmp = handler.getCurrentWeather().getBmp();
145. String currentInfoStr = handler.getCurrentWeather().getCurrentInfo().toString();
146. currentIcon.setImageBitmap(bmp);
147. currentInfo.setText(currentInfoStr);
148.
149. if(list.size() < 1)
150. {
151.
152. System.out.println("displayWeatherInfo: list.size() < 1");
153.
154. currentInfo.setText(R.string.prompt);
155.
156. currentInfo.setTextColor(Color.YELLOW);
157.
158. currentInfo.setVisibility(View.VISIBLE);
159.
160.
161. }
162.
163. // 显示未来天气, 我们这里是在ListView中显示
164. String[] itemName = new String[]{"week","temperature","condition","icon"};
165. int[] itemId = new int[]{R.id.week, R.id.temperature, R.id.condition,R.id.icon};
166. simpAdapter = new SimpleAdapter(this,
167. list,R.layout.list_item,
168. itemName,itemId);
169. lv.setAdapter(simpAdapter);
170. if(list.size() > 0)
171. {
172. tViewCurrent.setVisibility(View.VISIBLE);
173. futionTime.setVisibility(View.VISIBLE);
174. }
175. // 注意在这里用到了绑定数据 ImageView绑定了网络图片
176. simpAdapter.setViewBinder(new ViewBinder() {
177.
178. public boolean setViewValue(View view, Object data,
179. String textRepresentation) {
180. if(view instanceof ImageView && data instanceof Bitmap){
181. ImageView iv = (ImageView) view;
182. iv.setImageBitmap((Bitmap) data);
183. return true;
184. }else {
185. return false;
186. }
187.
188. }
189.
190. });
191. }
192. }
复制代码 在这个里面跟网络地址建立连接,需要得到InputStream流,在这种情况下一般得另开一个线程,这都是耗时的操作,不然有的时候网路出现延迟就会导致程序假死在哪里就不好使了,在这个weather里我没有用线程,随着一步一步的学习后面再加上,最后 ,别忘了加这玩意儿
这东西让我蛋疼了很久,升级后,模拟器当时连个错都不爆,千万不要忘记。
<uses-permission android:name="android.permission.INTERNET"></uses-permission>