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

时间:2022-06-25 19:30:35

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

Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
输入要查询的城市名称,点击查询按钮后,依次出现七天的天气情况。出现时有动画效果
二、实现过程
(一)获取天气预报数据
1、首先搞定天气预报数据来源的问题,提高天气预报服务的有很多网站,这些网站一般都会提供比较详细的 API 接口供应用程序调用,以聚合数据为例,其官网为:https://www.juhe.cn/如下图所示:

Android项目之天气预报 的实现分析
点击注册,进入注册界面:
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
登录成功后,就会进入到如下界面。
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析

点击左侧菜单中我的数据,进入如下界面
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
点击申请新数据,如下所示,必须实名认证
Android项目之天气预报 的实现分析
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析


进入聚合数据首页,选择 API 选项卡,选择免费的天气预报 API
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
点击进入后,只要申请就送 500 次使用,如下图所示。
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
复制其中的 AppKey:ab9d7e2007472d723baf71fcdc4ba094
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
打开全国天气预报 API 后,会有一项请求示例,按照其规则拼接字符串后在地址栏中输入
后可得

Android项目之天气预报 的实现分析
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
具体参照聚合数据的文档
Android项目之天气预报 的实现分析
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
下面是类的展示
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析

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>
Android项目之天气预报 的实现分析Android项目之天气预报 的实现分析
其中 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