天气预报模块的实现分析

一、调用数据

1.获取天气预报数据

登录聚合数据官网https://www.juhe.cn/ ,它会提供比较详细的 API 接口供应用程序调用。获取数据。

二、功能实现

1.编写网络数据访问工具类

首先需要在 uiti 包下定义一个接口HttpCallbackListener,

<span style="font-size:18px;">public interface HttpCallbackListener {
	void onFinish(String response);
	void onError(Exception e);
}</span>
然后定义 HttpUtil 类,代码如下

public class HttpUtil { 
	 public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
		new Thread(new Runnable() {    
			@Override    
			public void run() {     
				HttpURLConnection connection = null;     
				try {      
					URL url = new URL(address);      
					connection = (HttpURLConnection) url.openConnection();
					connection.setRequestMethod("GET");    
					connection.setConnectTimeout(8000);     
                    connection.setReadTimeout(8000); 
                    connection.setDoInput(true);     
                    connection.setDoOutput(true);    
                    InputStream in = connection.getInputStream(); 
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 
                    StringBuilder response = new StringBuilder();      
                    String line;      
                    
                    while ((line = reader.readLine()) != null) { 
                    	response.append(line);      
                    	}      if (listener != null) {       // 回调 onFinish()方法   
                    		listener.onFinish(response.toString()); 
                    		}     
                    	} catch (Exception e) {   
                    		if (listener != null) {       // 回调 onError()方法
                    			listener.onError(e);    
                    			}    
                    		} finally {     
                    			if (connection != null) {   
                    				connection.disconnect();  
                    			}
                    				  
                    		}  
				         }  
			       }).start();  
                    	
               }
2.测试一下能否正常访问天气预报接口得到返回的数据.

public class WeatherGetTest extends AndroidTestCase{  
	 public void testGetData(){  
		 String weatherUrl=
				 "http://v.juhe.cn/weather/index?format=2&cityname= 滨州 &key=ab9d7e2007472d723baf71fcdc4ba094";  
		 HttpUtil.sendHttpRequest(weatherUrl, new HttpCallbackListener() 
		 { 
			 @Override    
			 public void onFinish(String response) {  
				 System.out.println(response);   
				 }        
			 @Override    
			 public void onError(Exception e) {   
				 
			 }
		 });
	 }
 }
3.UI设计

新建 WeatherActivity 

修改自动生成的 activity_weather.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:background="@drawable/activity_weather_bg"
    tools:context=".WeatherActivity" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/etCity"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="20dp"
            android:layout_weight="1"
            android:background="@android:drawable/edit_text"
            android:drawableLeft="@drawable/icons_weather_city"
            android:drawablePadding="5dp"
            android:ems="10"
            android:hint="@string/etCity" >

            <requestFocus />
        </EditText>

        <ImageButton
            android:id="@+id/btnQuery"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginTop="20dp"
            android:background="@null"
            android:src="@drawable/icons_weather_query" />
    </LinearLayout>

    <ListView
        android:id="@+id/lvFutureWeather"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/linearLayout1"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:dividerHeight="10dp"
        android:layoutAnimation="@anim/weather_list_layout_animation" >
    </ListView>

</RelativeLayout>
其中 weather_list_layout_animation.xml 文件是一个设置布局动画的,实现过程如下: 

在 res 目录下新建 anim 文件夹,在其下新建 weather_list_layout_animation.xml 文件,如下:

 

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/weather_list_animation"
    android:animationOrder="normal"
    android:delay="2" /> 
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <scale
        android:duration="1000"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:toXScale="1.0"
        android:toYScale="1.0" />

</set>
定义整体布局中 ListView 控件所对应的子布局 activity_weather_listitem.xml 文件,如下: 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:background="@drawable/list_item_shape"
    android:padding="10dp" >

    <TextView
        android:id="@+id/tvDayofWeek"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="15dp"
        android:text="星期日" />

    <TextView
        android:id="@+id/tvDate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/tvDayofWeek"
        android:layout_alignBottom="@+id/tvDayofWeek"
        android:layout_alignParentRight="true"
        android:text="20160207" />

    <TextView
        android:id="@+id/tvTemperature"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tvDayofWeek"
        android:layout_below="@+id/tvDayofWeek"
        android:layout_marginTop="15dp"
        android:text="temperature" />

    <TextView
        android:id="@+id/tvWeather"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tvTemperature"
        android:layout_below="@+id/tvTemperature"
        android:layout_marginTop="15dp"
        android:text="weather" />

</RelativeLayout>
其中 list_item_shape.xml 文件定义如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

    <corners android:radius="5dp" />

    <solid 
        android:color="@color/azure" />

</shape> 

布局后的效果如图所示




4.在 model 包下定义 Weather 实体类封装所关心的信息,如下:

public class Weather {     
	 private String dayOfWeek;//星期几     
	 private String date;//日期     
	 private String temperature;//温度     
	 private String weather;//天气     
	 public Weather(){           
		 }  
	 public Weather(String dayOfWeek, String date, String temperature,    String weather) {
		 super();   
		 this.dayOfWeek = dayOfWeek;   
		 this.date = date;   
		 this.temperature = temperature;   
		 this.weather = weather; 
	 }
	 public String getDayOfWeek() {   
		 return dayOfWeek;  
     }  
	 public void setDayOfWeek(String dayOfWeek) {   
		 this.dayOfWeek = dayOfWeek;  
     }  
	 public String getDate() {  
		 return date;  
	 }  
	 public void setDate(String date) {   
		 this.date = date; 
	 }  
	 public String getTemperature() {  
		 return temperature;  
	 } 
	 public void setTemperature(String temperature) {   
		 this.temperature = temperature; 
	 }  public String getWeather() {  
		 return weather;  
	 }  public void setWeather(String weather) { 
		 this.weather = weather; 
	 }
 }
5.在 adapter 包下定义适配器 WeatherAdapter,代码如下: 

 public class WeatherAdapter extends ArrayAdapter<Weather> { 
	 private int resourceId;  
	 public WeatherAdapter(Context context, int textViewResourceId,    List<Weather> objects) { 
		 super(context, textViewResourceId, objects);  
		 resourceId = textViewResourceId;  }  
	 @Override  
	 public View getView(int position, View convertView, ViewGroup viewgroup) { 
		 Weather weather=getItem(position);  
		 ViewHolder viewHolder=null;  
		 if(convertView==null){    
			 viewHolder=new ViewHolder();  
			 convertView=LayoutInflater.from(getContext()).inflate(resourceId, null);   
			 viewHolder.tvDayOfWeek=(TextView) convertView.findViewById(R.id.tvDayofWeek);    
			 viewHolder.tvDate=(TextView) convertView.findViewById(R.id.tvDate);  
			 viewHolder.tvTemperature=(TextView) convertView.findViewById(R.id.tvTemperature); 
			 viewHolder.tvWeather=(TextView) convertView.findViewById(R.id.tvWeather); 
			 convertView.setTag(viewHolder);  
			 }else{   
				 viewHolder=(ViewHolder) convertView.getTag(); 
			 }  
		         viewHolder.tvDayOfWeek.setText(weather.getDayOfWeek()); 
				 viewHolder.tvDate.setText(weather.getDate()); 
				 viewHolder.tvTemperature.setText(weather.getTemperature()); 
				 viewHolder.tvWeather.setText(weather.getWeather()); 
				 return convertView; 
				 }  
	 private class ViewHolder{  
		 TextView tvDayOfWeek;  
		 TextView tvDate;  
		 TextView tvTemperature;  
		 TextView tvWeather;  
	}  
 }
				
			
6.编写 WeatherActivity 类 

package cn.edu.bztc.walkersimulate;  
import java.util.ArrayList; 
import java.util.List; 

import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler;
import android.os.Message;
import android.view.View; 
import android.view.View.OnClickListener;
import android.view.animation.LayoutAnimationController; 
import android.view.animation.ScaleAnimation;
import android.widget.EditText; 
import android.widget.ImageButton;
import android.widget.ListView; 
import android.widget.Toast; 

import cn.edu.bztc.walkersimulate.adapter.WeatherAdapter; 
import cn.edu.bztc.walkersimulate.model.Weather; 
import cn.edu.bztc.walkersimulate.util.HttpCallbackListener;
import cn.edu.bztc.walkersimulate.util.HttpUtil;  

import com.google.gson.JsonArray; 
import com.google.gson.JsonObject; 
import com.google.gson.JsonParser; 


public class WeahterActivity extends Activity { 
	private EditText etCity;  
	private ImageButton btnQuery; 
	private ListView lvFutureWeather;
 public static final int SHOW_RESPONSE = 1; 
 private List<Weather> data; 
 private Handler handler = new Handler() {  
	 public void handleMessage(android.os.Message msg) {    
		 switch (msg.what) {    
		 case SHOW_RESPONSE:     
			 String response = (String) msg.obj;    
			 if (response != null) {      
				 parseWithJSON(response);     
				 WeatherAdapter weatherAdapter = new WeatherAdapter(        
						 WeahterActivity.this,        
						 R.layout.activity_weather_listitem, data); 
				 lvFutureWeather.setAdapter(weatherAdapter);    
				 ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0,1);
				 scaleAnimation.setDuration(1000);   
				 LayoutAnimationController animationController = new LayoutAnimationController(
						 scaleAnimation, 0.6f); 
				 lvFutureWeather.setLayoutAnimation(animationController);
				 }    
			 default:    
				 break;   
			 }
		 }
	 
 private void parseWithJSON(String response) {    
		 data = new ArrayList<Weather>(); 
		 JsonParser parser = new JsonParser();// json 解析器    
		 JsonObject obj = (JsonObject) parser.parse(response); 
		 /* 获取返回状态码 */    
		 String resultcode = obj.get("resultcode").getAsString(); 
		 /* 如果状态码是 200 说明返回数据成功 */   
		 if (resultcode != null && resultcode.equals("200")) { 
			 JsonObject resultObj = obj.get("result").getAsJsonObject();
			 JsonArray futureWeatherArray = resultObj.get("future").getAsJsonArray();
			 for (int i = 0; i < futureWeatherArray.size(); i++) {
				 Weather weather = new Weather();
				 JsonObject weatherObject = futureWeatherArray.get(i).getAsJsonObject();
				 weather.setDayOfWeek(weatherObject.get("week").getAsString());
				 weather.setDate(weatherObject.get("date").getAsString()); 
				 weather.setTemperature(weatherObject.get("temperature").getAsString()); 
				 weather.setWeather(weatherObject.get("weather").getAsString());
				 data.add(weather);
			   }   
			 }  
		 }  
	 };  
	 
	 @Override  
	 protected void onCreate(Bundle savedInstanceState) { 
		 super.onCreate(savedInstanceState);  
		 setContentView(R.layout.activity_weahter);
		 initViews();   
		 setListeners();
		  
	 }
	 private void initViews() { 
		 etCity = (EditText) findViewById(R.id.etCity); 
		 btnQuery = (ImageButton) findViewById(R.id.btnQuery);
		 lvFutureWeather = (ListView) findViewById(R.id.lvFutureWeather);
	 }  
	 private void setListeners() { 
		 btnQuery.setOnClickListener(new OnClickListener() { 
			 @Override   
			 public void onClick(View view) {
				 String city = etCity.getText().toString(); 
				 System.out.println("lvFutureWeather=" + lvFutureWeather);
				 Toast.makeText(WeahterActivity.this, "success",Toast.LENGTH_LONG).show(); 
				 String weatherUrl = "http://v.juhe.cn/weather/index?format=2&cityname="+ city + "&key=ab9d7e2007472d723baf71fcdc4ba094";
				 HttpUtil.sendHttpRequest(weatherUrl,new HttpCallbackListener() {       
					 @Override       
					 public void onFinish(String response) {  
						 Message message = new Message(); 
						 message.what = SHOW_RESPONSE;   // 将服务器返回的结果存放到 Message 中        
						 message.obj = response.toString();
						 handler.sendMessage(message); 
						 }  
	                         @Override        
	                         public void onError(Exception e) { 
	                        	 System.out.println("访问失败");
	                         }       
	                   }); 
				 }   
			 });  
	 } 
}
	 

7.测试





 *输入套查询的城市名称,点击查询按钮后,依次出现七天的天气情况,出现时有动画效果。


 









  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值