Android项目之天气预报 的实现分析

Android项目之天气预报 的实现分析

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

二、实现过程

(一)获取天气预报数据

1、首先搞定天气预报数据来源的问题,提高天气预报服务的有很多网站,这些网站一般都会提供比较详细的 API 接口供应用程序调用,以聚合数据为例,其官网为:https://www.juhe.cn/如下图所示:

点击注册,进入注册界面:

登录成功后,就会进入到如下界面。

点击左侧菜单中我的数据,进入如下界面

点击申请新数据,如下所示,必须实名认证

进入聚合数据首页,选择 API 选项卡,选择免费的天气预报 API

点击进入后,只要申请就送 500 次使用,如下图所示。

复制其中的 AppKey:ab9d7e2007472d723baf71fcdc4ba094

打开全国天气预报 API 后,会有一项请求示例,按照其规则拼接字符串后在地址栏中输入
后可得

具体参照聚合数据的文档

下面是类的展示

2、编写网络数据访问工具类

首先需要在 uiti 包下定义一个接口,比如将它命名成 HttpCallbackListener,代码如下

package com.example.weather.util;  public interface HttpCallbackListener { 	void onFinish(String response); 	void onError(Exception e); } 

然后定义 HttpUtil 类,代码如下

package com.example.weather.util;  import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL;  import android.util.Log;  public class HttpUtil { 	public static void sendHttpRequest(final String address, final HttpCallbackListener listener) { 		new Thread(new Runnable() { 			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(); 	} }

3、测试一下能否正常访问天气预报接口得到返回的数据

package com.example.weather.test;  import java.io.UnsupportedEncodingException; import java.net.URLEncoder;  import com.example.weather.util.HttpCallbackListener; import com.example.weather.util.HttpUtil;  import android.test.AndroidTestCase;  public class WeatherGetTest  extends AndroidTestCase{ 	 public void testGetData(){	  		 String cityName; 		try { 			cityName = URLEncoder.encode("菏泽", "utf-8"); 			String  weatherUrl="http://v.juhe.cn/weather/index?format=2&cityname="+cityName+"&key=ab9d7e2007472d723baf71fcdc4ba094"; 		 		 HttpUtil.sendHttpRequest(weatherUrl, new HttpCallbackListener() { 			 			public void onFinish(String response) { 				// TODO Auto-generated method stub 				System.out.println(response); 			} 			 			public void onError(Exception e) { 				// TODO Auto-generated method stub 				 			} 			}); 		 }catch (Exception e) { 			// TODO: handle exception 		} 	 	 } } 

由于涉及到访问网络,需要在 AndroidManifest.xml 文件中加入访问网络的权限。
<uses-permission android:name="android.permisson.Internet"/>


(三)UI 设计

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/city"     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/etcity"             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/serch" />     </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>  <span style="color:#ff0000;"></RelativeLayout></span>

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>


其中 weather_list_layout_animation.xml 文件是一个设置布局动画的,实现过程如下 :在 res 目录下新建 anim 文件夹, 在其下新建 weather_list_layout_animation.xml 文件, 如下:

weather_list_animation.xml
 

<?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>

weather_list_layout_animation.xml

<span style="font-size:18px;"><?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" /></span> 

Weather.java

package com.example.weather.moder;  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; 	} 	@Override 	public String toString() { 		return "Weather [dayOfWeek=" + dayOfWeek + ", date=" + date 				+ ", temperature=" + temperature + ", weather=" + weather + "]"; 	}  } 

在 adapter 包下定义适配器 WeatherAdapter

package com.example.weather.adapter;   import java.util.List;  import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView;  import com.example.weather.R; import com.example.weather.moder.Weather;  /**  * 天气适配器  * @author zhupeng  *  */ 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; 	} } 

WeatherActivity.java
 

<span style="font-size:18px;">package com.example.weather;  import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List;  import com.example.weather.adapter.WeatherAdapter; import com.example.weather.moder.Weather; import com.example.weather.util.HttpCallbackListener; import com.example.weather.util.HttpUtil; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser;  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; public class WeatherActivity extends Activity { 	private EditText ecCity; 	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(Message msg){ 			switch (msg.what) { 			case SHOW_RESPONSE: 				String response=(String )msg.obj; 				if(response!=null){ 					parseWithJSON(response); 					WeatherAdapter weatherAdapter=new WeatherAdapter 							(WeatherActivity.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);  				} 				break;  			default: 				break; 			} 		}  		private void parseWithJSON(String response) { 			// TODO Auto-generated method stub 			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_weather); 		initViews(); 		setListeners();  	} 	public void initViews(){ 		ecCity=(EditText) findViewById(R.id.etCity); 		btnQuery=(ImageButton)findViewById(R.id.btnQuery); 		lvFutureWeather=(ListView) findViewById(R.id.lvFutureWeather); 		 data=new ArrayList<Weather>(); 	} 	private void setListeners(){ 		btnQuery.setOnClickListener(new OnClickListener() {  			public void onClick(View v) { 				// TODO Auto-generated method stub 				String cityName=ecCity.getText().toString();   				try { 					cityName = URLEncoder.encode("菏泽", "utf-8"); //这里我弄成默认的城市了,如果想根据输入的值进行搜索,,,可以把这句话换成cityName = URLEncoder.encode(cityName, "utf-8");   				} catch (UnsupportedEncodingException e1) { 					e1.printStackTrace(); 				} 				System.out.println("lvFutureWeather="+lvFutureWeather); 				Toast.makeText(WeatherActivity.this, "success", 						Toast.LENGTH_LONG).show(); 				String weatherUrl = "http://v.juhe.cn/weather/index?format=2&cityname="+cityName+"&key=ab9d7e2007472d723baf71fcdc4ba094"; 				Toast.makeText(WeatherActivity.this, "success"+weatherUrl, 						Toast.LENGTH_LONG).show(); 				HttpUtil.sendHttpRequest(weatherUrl, new HttpCallbackListener() {  					public void onFinish(String response) { 						// TODO Auto-generated method stub 						Message message=new Message(); 						message.what=SHOW_RESPONSE; 						//将服务器返回的结果存放到Message中 						message.obj=response.toString(); 						handler.sendMessage(message); 					}  					public void onError(Exception e) { 						// TODO Auto-generated method stub 						System.out.println("访问失败"); 					} 				}); 			} 		}); 	}  }</span><strong> </strong>


注意:  在进行查询输入城市名时一定要先改编码格式  列如

<span style="font-size:18px;">cityName = URLEncoder.encode("菏泽", "utf-8");</span>


源码地址:http://download.csdn.net/detail/zhupengqq/9560555

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值