1.本程序采用和风天气的免费API获取天气数据,在http://guolin.tech/api/weather/register上注册就可免费获取天气信息,天气信息以json的形式返回给我们。故先创建一个json的包用于对json数据的解析,代码如下:
注意:由于一时粗心,API类应该是获取天气中的AQI指数的,此处并不影响。
API类:
public class API {
public APICity city;
public class APICity {
public String aqi;
public String pm25;
}
}
Basic类:
public class Basic {
@SerializedName("city")
public String cityName;
@SerializedName("cid")
public String weatherId;
public Update update;
public class Update{
@SerializedName("loc")
public String updateTime;
}
}
Forecast类:
public class Forecast {
public String date;
@SerializedName("tmp")
public Temperature temperature;
@SerializedName("cond")
public More more;
public class Temperature {
public String max;
public String min;
}
public class More {
@SerializedName("txt_d")
public String info;
}}
Now类;
public class Now {
@SerializedName("tmp")
public String temperature;
@SerializedName("cond")
public More more;
public class More{
@SerializedName("txt")
public String info;
}}
Suggestion类:
public class Suggestion {
@SerializedName("comf")
public Comfort comfort;
@SerializedName("cw")
public CarWash carWash;
public Sport sport;
public class Comfort{
@SerializedName("txt")
public String info;
}
public class CarWash{
@SerializedName("txt")
public String info;
}
public class Sport{
@SerializedName("txt")
public String info;
}
}
Weather类:
public class Weather {
public String status;
public Basic basic;
public API aqi;
public Now now;
public Suggestion suggestion;
@SerializedName("daily_forecast")
public List<Forecast> forecastList;
}
注意:上述代码中的 @SerializedName(""),括号中的属性是由网站中json数据得来的,千万不要出错,不然会拿不到数据。
2.创建一个util包用于写与服务器交互的相关类:
其中HttpUilt使用okhttp和服务器交互,只要传入相应的请求地址即可进行交互,代码如下:
public class HttpUilt {
public static void sendOkHttpRequest(String address,okhttp3.Callback callback){
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url(address).build();
client.newCall(request).enqueue(callback);
}
}
而Utility则是用于解析json数据的方法,代码如下:
public class Utility {
public static Weather handleWeatherResponce(String response){
try{
JSONObject jsonObject=new JSONObject(response);
JSONArray jsonArray=jsonObject.getJSONArray("HeWeather");
String weatherContent=jsonArray.getJSONObject(0).toString();
return new Gson().fromJson(weatherContent,Weather.class);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
3.然后便可以编写布局,由于信息较多,我们在json包中可知我们只用到了现在的天气,预报的天气,空气质量和生活建议。因此我们在布局中使用FrameLayout并在其中嵌套一个ScrollView,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/a">
<ScrollView
android:id="@+id/weather_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:overScrollMode="never">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/title"/>
<include layout="@layout/now"/>
<include layout="@layout/forecast"/>
<include layout="@layout/api"/>
<include layout="@layout/suggestion"/>
</LinearLayout>
</ScrollView>
</FrameLayout>
其他子项布局和郭霖大神的书上一致。
布局后的样式如下:
这里我插入了一张南昌的图片,因为本程序仅能获取南昌的天气。
4.最后便是MianActivity的代码,首先定义初始化使用到的各个控件;
public class WeatherActivity extends AppCompatActivity {
private ScrollView weatherLayout;
private TextView titleUpdateTime;
private TextView degreeText;
private TextView weatherInfoText;
private LinearLayout forecastLayout;
private TextView apiText;
private TextView pm25Text;
private TextView comfortText;
private TextView carWashText;
private TextView sportText;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weather);
weatherLayout=(ScrollView)findViewById(R.id.weather_layout);
titleUpdateTime=(TextView)findViewById(R.id.title_update_time);
degreeText=(TextView)findViewById(R.id.degree_text);
weatherInfoText=(TextView)findViewById(R.id.weather_info_text);
forecastLayout=(LinearLayout) findViewById(R.id.forecast_layout);
apiText=(TextView)findViewById(R.id.api_text);
pm25Text=(TextView)findViewById(R.id.pm25_text);
comfortText=(TextView)findViewById(R.id.comfort_text);
carWashText=(TextView)findViewById(R.id.car_wash_text);
sportText=(TextView)findViewById(R.id.sport_text);
requestWeather();
}
}
上述代码最后一行的requestWeather方法为获取天气信息的一个方法,定义requestWeather函数,用于传入对应的接口地址,并调用HttpUtil.sendOkHttpRequest()向该地址发出请求,得到的json数据调用handleWeatherResponse将数据转换为Weather对象。注意,此处的weathterUrl的网址是我注册和风天气免费api获取的到的网址,cityid指的是南昌市的城市id,后面的key是我注册所得的key,可以拿到相应的天气。代码如下:
public void requestWeather(){
String weatherUrl="http://guolin.tech/api/weather?cityid=CN101240101&key=94df6ecbe100465db73349525a29bef3 ";
HttpUilt.sendOkHttpRequest(weatherUrl, new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseText = response.body().string();
System.out.println("responseText:"+responseText);
final Weather weather= Utility.handleWeatherResponce(responseText);
runOnUiThread(new Runnable() {
public void run() {
if(weather!=null&&"ok".equals(weather.status)){
showWeatherInfo(weather);
}else{
Toast.makeText(WeatherActivity.this,"获取天气信息失败1",Toast.LENGTH_SHORT).show();
}
}
});
}
public void onFailure(Call call, IOException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(WeatherActivity.this,"获取天气信息失败",Toast.LENGTH_SHORT).show();
}
});
}
});
}
6.编写showWeatherInfo函数,将解析好的天气数据进行显示,更新各个控件的内容,代码如下:
private void showWeatherInfo(Weather weather){
String updateTime="更新时间:"+weather.basic.update.updateTime.split(" ")[1];
String degree=weather.now.temperature+"℃";
String weatherInfo=weather.now.more.info;
titleUpdateTime.setText(updateTime);
degreeText.setText(degree);
weatherInfoText.setText(weatherInfo);
forecastLayout.removeAllViews();
for(Forecast forecast : weather.forecastList){
View view= LayoutInflater.from(this).inflate(R.layout.forecast_item,forecastLayout,false);
TextView dateText=(TextView)view.findViewById(R.id.date_text);
TextView infoText=(TextView)view.findViewById(R.id.info_text);
TextView maxText=(TextView)view.findViewById(R.id.max_text);
TextView minText=(TextView)view.findViewById(R.id.min_text);
dateText.setText(forecast.date);
infoText.setText(forecast.more.info);
maxText.setText(forecast.temperature.max);
minText.setText(forecast.temperature.min);
forecastLayout.addView(view);
}
if(weather.aqi!=null){
apiText.setText(weather.aqi.city.aqi);
pm25Text.setText(weather.aqi.city.pm25);
}
comfortText.setText("舒适度:"+weather.suggestion.comfort.info);
carWashText.setText("洗车指数:"+weather.suggestion.carWash.info);
sportText.setText("运动建议:"+weather.suggestion.sport.info);
weatherLayout.setVisibility(View.VISIBLE);
}
7.最后别忘了加上网络依赖,在AndroidManifest.xml中加上:
<uses-permission android:name="android.permission.INTERNET" />
还有在build.gradle(app)中添加依赖,这里我们只要添加okhttp和json的依赖就好:
compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'com.google.code.gson:gson:2.7'
8.最后运行代码,效果如下:
可以看到我们拿到天气内容,成功了。如果像要获取其他地区的天气预报,只要修改MainActivity中的requestWeather方法,把cityid改成对应城市的即可。