今天终于把天气预报给弄出来了,心里小小的高兴一下,虽然这东西网上早就有了,但那毕竟是别人的。在想做这个之前,以为天气预报软件好高深,不知道从何下手。不过现在想想这东西也不是想象中那么复杂。最主要的是自己亲手做出来,感觉挺很爽的,要是有真机就更好了!

       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>