今天終於把天氣預報給弄出來了,心裡小小的高興一下,雖然這東西網上早就有了,但那畢竟是別人的。在想做這個之前,以為
天氣預報軟件好高深,不知道從何下手。不過現在想想這東西也不是想象中那麼復雜。最主要的是自己親手做出來,感覺挺很爽的,要是有真機就更好了!
OK,在下面我把天氣預報簡單叫weather好了,在做weather之前我在網上有搜了一下有關它的資料,知道weather一般的是解析XML文檔來獲取信息。
本文源碼下載:
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /pub/Android源碼集錦/2011年/12月/天氣預報(Android版)/
可能還有別的方式Json....所以就有了之前兩篇學習解析XML的學習天氣預報Dom解析 ( http://www.linuxidc.com/Linux/2011-12/49439.htm ) 和 學習SAX解析 ( http://www.linuxidc.com/Linux/2011-12/49440.htm ) 以這兩篇學習做鋪墊。然
後再結合自己學的Android知識就可以完成本次小程序。本次寫的weather裡主要涉及到AutoCompleteTextView,ListView以及
SAX技術 。先上weather運行時的效果圖:
weather布局很丑,哎,俺沒啥藝術細胞,只想到這樣的布局,重在功能實現上。這次是用SAX解析XML,同樣是用到了谷歌提供
的天氣接口。在上次的學習SAX解析 (http://www.linuxidc.com/Linux/2011-12/49440.htm)中裡面我做的是解析本地的XML,很順利。在做weather的同時我順便寫了個控制台版的天氣
預報,發現了有同樣的問題:結果只出現溫度,而中文信息卻是亂碼。在這上面我糾結了大半天後來才知道為什麼,原因是編碼不
對,最後換成了GBK編碼就搞定了 下面是代碼片段。
- URL url = new URL(path);
- URLConnection conn = url.openConnection();
- InputStreamReader isr = new InputStreamReader(conn.getInputStream(),"GBK"); //GBK編碼就OK,用utf-8還是出現亂碼
- BufferedReader br = new BufferedReader(isr);
- InputSource is = new InputSource(br);
- 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
- package com.weather.manymore13;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.UnsupportedEncodingException;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.net.URLConnection;
- import java.util.ArrayList;
- import java.util.Map;
-
- import javax.xml.parsers.ParserConfigurationException;
- import javax.xml.parsers.SAXParser;
- import javax.xml.parsers.SAXParserFactory;
-
- import org.xml.sax.InputSource;
- import org.xml.sax.SAXException;
- import org.xml.sax.XMLReader;
-
- import android.app.Activity;
- import android.content.Intent;
- import android.graphics.Bitmap;
- import android.graphics.Color;
- import android.os.Bundle;
- import android.text.StaticLayout;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.ArrayAdapter;
- import android.widget.AutoCompleteTextView;
- import android.widget.Button;
- import android.widget.ImageView;
- import android.widget.ListView;
- import android.widget.SimpleAdapter;
- import android.widget.SimpleAdapter.ViewBinder;
- import android.widget.TextView;
-
- public class WeatherActivity extends Activity {
- private AutoCompleteTextView autoText;
- private Button btnConfirm;
- private TextView tViewCurrent;
- private ListView lv;
- private ArrayList<Map<String,Object>> list;
- private ImageView currentIcon;
- private TextView currentInfo;
- private TextView futionTime;
- private SimpleAdapter simpAdapter = null;
- private boolean visit = true;
- public void init()
- {
- autoText = (AutoCompleteTextView)findViewById(R.id.autoTextView);
- btnConfirm = (Button)findViewById(R.id.btn_confirm);
- tViewCurrent = (TextView)findViewById(R.id.current_time);
- lv = (ListView)findViewById(R.id.myListView);
- currentIcon = (ImageView)findViewById(R.id.current_icon);
- currentInfo = (TextView)findViewById(R.id.current_info);
- futionTime = (TextView)findViewById(R.id.future_time);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- init();
-
-
- ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>
- (this, android.R.layout.simple_dropdown_item_1line,
- Tools.city);
- autoText.setAdapter(arrayAdapter);
- btnConfirm.setOnClickListener(new OnClickListener() {
-
- public void onClick(View arg0) {
-
- System.out.println("按鈕被按下");
- String city = autoText.getText().toString().trim();
-
- tViewCurrent.setVisibility(View.INVISIBLE);
- futionTime.setVisibility(View.INVISIBLE);
- if(!(city.equals("")))
- {
- try {
-
-
- obtainWeacherInfo(Tools.SEACH_URL+city);
- if(simpAdapter!=null)
- {
- simpAdapter.notifyDataSetChanged();
- }
-
-
- } catch (MalformedURLException e) {
- System.out.println("url出錯");
- e.printStackTrace();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- }
- });
-
-
- }
-
- public void obtainWeacherInfo(String path) throws ParserConfigurationException, SAXException, UnsupportedEncodingException, IOException
- {
-
- SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-
- SAXParser sp = parserFactory.newSAXParser();
-
- XMLReader xmlReader = sp.getXMLReader();
-
- WeacherHandler handler = new WeacherHandler();
-
- xmlReader.setContentHandler(handler);
-
- URL url = new URL(path);
-
- URLConnection conn = url.openConnection();
-
- InputStreamReader isr = new InputStreamReader(conn.getInputStream(),"GBK");
-
- BufferedReader br = new BufferedReader(isr);
-
- InputSource is = new InputSource(br);
-
- xmlReader.parse(is);
-
- br.close();
-
- displayWeatherInfo(handler);
-
- }
-
-
- public void displayWeatherInfo(WeacherHandler handler)
- {
- list = handler.getForecastWeachers();
-
- //顯示實時信息
- Bitmap bmp = handler.getCurrentWeather().getBmp();
- String currentInfoStr = handler.getCurrentWeather().getCurrentInfo().toString();
- currentIcon.setImageBitmap(bmp);
- currentInfo.setText(currentInfoStr);
-
- if(list.size() < 1)
- {
-
- System.out.println("displayWeatherInfo: list.size() < 1");
-
- currentInfo.setText(R.string.prompt);
-
- currentInfo.setTextColor(Color.YELLOW);
-
- currentInfo.setVisibility(View.VISIBLE);
-
-
- }
-
- // 顯示未來天氣, 我們這裡是在ListView中顯示
- String[] itemName = new String[]{"week","temperature","condition","icon"};
- int[] itemId = new int[]{R.id.week, R.id.temperature, R.id.condition,R.id.icon};
- simpAdapter = new SimpleAdapter(this,
- list,R.layout.list_item,
- itemName,itemId);
- lv.setAdapter(simpAdapter);
- if(list.size() > 0)
- {
- tViewCurrent.setVisibility(View.VISIBLE);
- futionTime.setVisibility(View.VISIBLE);
- }
- // 注意在這裡用到了綁定數據 ImageView綁定了網絡圖片
- simpAdapter.setViewBinder(new ViewBinder() {
-
- public boolean setViewValue(View view, Object data,
- String textRepresentation) {
- if(view instanceof ImageView && data instanceof Bitmap){
- ImageView iv = (ImageView) view;
- iv.setImageBitmap((Bitmap) data);
- return true;
- }else {
- return false;
- }
-
- }
-
- });
- }
- }
在這個裡面跟網絡地址建立連接,需要得到InputStream流,在這種情況下一般得另開一個線程,這都是耗時的操作,不然有的時
候網路出現延遲就會導致程序假死在哪裡就不好使了,在這個weather裡我沒有用線程,隨著一步一步的學習後面再加上,
最後 ,別忘了加這玩意兒 <uses-permission android:name="android.permission.INTERNET"></uses-permission>
這東西讓我蛋疼了很久,升級後,模擬器當時連個錯都不爆,千萬不要忘記。