一个天气预报APP至少应该具备以下功能:

*可以罗列出全国所有的省、市、县;

*可以查看全国任意城市的天气信息;

*可以自由的切换城市,去查看其他城市的天气;

*提供手动更新以及后台自动更新天气的功能;

这里使用和风天气作为天气预报来源,全国省市县的数据信息这里使用的是《第一行代码》的作者郭霖大佬架设的服务器。

具体就是:想要罗列出中国所有的省份,只需要访问这个地址:http://guolin.tech/api/china,服务器会返回一段JSON格式的数据,其中包括了中国所有省份的名称及省份的id:

[{"id":1,"name":"北京"},{"id":2,"name":"上海"},{"id":3,"name":"天津"},

{"id":4,"name":"重庆"},{"id":5,"name":"香港"},{"id":6,"name":"澳门"},

{"id":7,"name":"台湾"},{"id":8,"name":"黑龙江"},{"id":9,"name":"吉林"},

{"id":10,"name":"辽宁"},{"id":11,"name":"内蒙古"},{"id":12,"name":"河北"},

{"id":13,"name":"河南"},{"id":14,"name":"山西"},{"id":15,"name":"山东"},

{"id":16,"name":"江苏"},{"id":17,"name":"浙江"},{"id":18,"name":"福建"},

{"id":19,"name":"江西"},{"id":20,"name":"安徽"},{"id":21,"name":"湖北"},

{"id":22,"name":"湖南"},{"id":23,"name":"广东"},{"id":24,"name":"广西"},

{"id":25,"name":"海南"},{"id":26,"name":"贵州"},{"id":27,"name":"云南"},

{"id":28,"name":"四川"},{"id":29,"name":"西藏"},{"id":30,"name":"陕西"},

{"id":31,"name":"宁夏"},{"id":32,"name":"甘肃"},{"id":33,"name":"青海"},

{"id":34,"name":"新疆"}]

如果想要河北省有那些城市,就把id加上:http://guolin.tech/api/china/12

[{"id":57,"name":"石家庄"},{"id":58,"name":"保定"},{"id":59,"name":"张家口"},

{"id":60,"name":"唐山"},{"id":61,"name":"廊坊"},{"id":62,"name":"沧州"},

{"id":63,"name":"衡水"},{"id":64,"name":"邢台"},{"id":65,"name":"邯郸"},

{"id":66,"name":"秦皇岛"}]

如果想要知道秦皇岛有那些县,就再加上id:http://guolin.tech/api/china/12/66

[{"id":557,"name":"秦皇岛","weather_id":"CN101091101"},{"id":558,"name":"青龙","weather_id":"CN101091102"},

{"id":559,"name":"昌黎","weather_id":"CN101091103"},{"id":560,"name":"抚宁","weather_id":"CN101091104"},

{"id":561,"name":"卢龙","weather_id":"CN101091105"},{"id":562,"name":"北戴河","weather_id":"CN101091106"}]

以上是全国省市县的数据,然后是天气数据的api的使用:

https://free-api.heweather.com/v5/weather?city=yourcity&key=yourkey

这是一个免费的使用方法,一天可以访问4000次,不过要先申请。yourcity部分就填之前获取到的id即可,key的话申请就有了。

https://free-api.heweather.com/v5/weather?city=CN101091101&key=32d1c829ed7d483086f4f5b4d5947cef

这样就能查询到秦皇岛的天气情况,返回的数据就比较复杂了,官方的例子就是:

{"HeWeather5": [

{"alarms": [

{"level": "蓝色",

"stat": "预警中",

"title": "山东省青岛市气象台发布大风蓝色预警",

"txt": "青岛市气象台2016年08月29日15时24分继续发布大风蓝色预警信号:预计今天下午到明天,我市北风风力海上6到7级阵风9级,陆地4到5阵风7级,请注意防范。",

"type": "大风"

}

],"aqi": {

"city": {

"aqi": "60",

"co": "0",

"no2": "14",

"o3": "95",

"pm10": "67",

"pm25": "15",

"qlty": "良", //共六个级别,分别:优,良,轻度污染,中度污染,重度污染,严重污染

"so2": "10"

}

},"basic": {

"city": "青岛",

"cnty": "中国",

"id": "CN101120201",

"lat": "36.088000",

"lon": "120.343000",

"prov": "山东" //城市所属省份(仅限国内城市)

"update": {

"loc": "2016-08-30 11:52",

"utc": "2016-08-30 03:52"

}

},"daily_forecast": [

{"astro": {

"mr": "03:09",

"ms": "17:06",

"sr": "05:28",

"ss": "18:29"

},"cond": {

"code_d": "100",

"code_n": "100",

"txt_d": "晴",

"txt_n": "晴"

},"date": "2016-08-30",

"hum": "45",

"pcpn": "0.0",

"pop": "8",

"pres": "1005",

"tmp": {

"max": "29",

"min": "22"

},"vis": "10",

"wind": {

"deg": "339",

"dir": "北风",

"sc": "4-5",

"spd": "24"

}

}

],"hourly_forecast": [

{"cond": {

"code": "100",

"txt": "晴"

},"date": "2016-08-30 12:00",

"hum": "47",

"pop": "0",

"pres": "1006",

"tmp": "29",

"wind": {

"deg": "335",

"dir": "西北风",

"sc": "4-5",

"spd": "36"

}

}

],"now": {

"cond": {

"code": "100",

"txt": "晴"

},"fl": "28",

"hum": "41",

"pcpn": "0",

"pres": "1005",

"tmp": "26",

"vis": "10",

"wind": {

"deg": "330",

"dir": "西北风",

"sc": "6-7",

"spd": "34"

}

},"status": "ok",

"suggestion": {

"comf": {

"brf": "较舒适",

"txt": "白天天气晴好,您在这种天气条件下,会感觉早晚凉爽、舒适,午后偏热。"

},"cw": {

"brf": "较不宜",

"txt": "较不宜洗车,未来一天无雨,风力较大,如果执意擦洗汽车,要做好蒙上污垢的心理准备。"

},"drsg": {

"brf": "热",

"txt": "天气热,建议着短裙、短裤、短薄外套、T恤等夏季服装。"

},"flu": {

"brf": "较易发",

"txt": "虽然温度适宜但风力较大,仍较易发生感冒,体质较弱的朋友请注意适当防护。"

},"sport": {

"brf": "较适宜",

"txt": "天气较好,但风力较大,推荐您进行室内运动,若在户外运动请注意防风。"

},"trav": {

"brf": "适宜",

"txt": "天气较好,风稍大,但温度适宜,是个好天气哦。适宜旅游,您可以尽情地享受大自然的无限风光。"

},"uv": {

"brf": "强",

"txt": "紫外线辐射强,建议涂擦SPF20左右、PA++的防晒护肤品。避免在10点至14点暴露于日光下。"

}

}

}

]

}

数据返回示例

首先是这次项目需要依赖的库的声明:

compile 'org.litepal.android:core:1.6.0'compile'com.squareup.okhttp3:okhttp:3.9.0'compile'com.google.code.gson:gson:2.8.0'compile'com.github.bumptech.glide:glide:4.0.0'

Litepal用于数据库操作。OkHttp用于进行网络请求,GSON用于解析获得的JSON数据,Glide用于加载展示图片

1、建立数据库和表

先建三张表,分别是省,市,县:

Province:

public class Province extendsDataSupport {private intid;private String provinceName;//省的名字

private int provinceCode;//省的代号

public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}publicString getProvinceName() {returnprovinceName;

}public voidsetProvinceName(String provinceName) {this.provinceName =provinceName;

}public intgetProvinceCode() {returnprovinceCode;

}public void setProvinceCode(intprovinceCode) {this.provinceCode =provinceCode;

}

}

省的数据信息

City:

public class City extendsDataSupport {private intid;private String cityName;//城市的名字

private int cityCode;//城市的代号

private int provinceId;//城市所在省的id值

public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}publicString getCityName() {returncityName;

}public voidsetCityName(String cityName) {this.cityName =cityName;

}public intgetCityCode() {returncityCode;

}public void setCityCode(intcityCode) {this.cityCode =cityCode;

}public intgetProvinceId() {returnprovinceId;

}public void setProvinceId(intprovinceId) {this.provinceId =provinceId;

}

}

市的数据信息

County:

public class County extendsDataSupport {private intid;private String countyName;//县的名字

private String weatherId;//天气的id

private int cityId;//所属市的id

public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}publicString getCountyName() {returncountyName;

}public voidsetCountyName(String countyName) {this.countyName =countyName;

}publicString getWeatherId() {returnweatherId;

}public voidsetWeatherId(String weatherId) {this.weatherId =weatherId;

}public intgetCityId() {returncityId;

}public void setCityId(intcityId) {this.cityId =cityId;

}

}

县的数据信息

然后是Litepal的建表操作,在app/src/main目录下新建assets目录,在其中新建Litepal.xml文件

再然后是配置LitepalApplication:

...

这样三个类加上Litepal的配置,数据库和表会在首次执行任意数据库操作的时候自动创建。

2、遍历全国省市县数据

首先是新建一个HttpUtil类:

/*** 发起一条HTTP请求,传入地址,并注册一个回调来处理服务器响应*/

public classHttpUtil {public static voidsendOkHttpRequest(String address, okhttp3.Callback callback){

OkHttpClient client= newOkHttpClient();

Request request= newRequest.Builder().url(address).build();

client.newCall(request).enqueue(callback);

}

}

然后是一个Utility类:

public classUtility {/***解析和处理服务器返回的省级数据*/

public static booleanhandleProvinceResponse(String response){if(!TextUtils.isEmpty(response)){//如果字符序列不为空或长度为0

try{

JSONArray allProvinces= newJSONArray(response);for(int i = 0; i < allProvinces.length(); i++){

JSONObject provinceObject=allProvinces.getJSONObject(i);

Province province= newProvince();

province.setProvinceName(provinceObject.getString("name"));

province.setProvinceCode(provinceObject.getInt("id"));

province.save();

}return true;

}catch(JSONException e){

e.printStackTrace();

}

}return false;

}/***解析和处理服务器返回的市级数据*/

public static boolean handleCityResponse(String response, intprovinceId){if(!TextUtils.isEmpty(response)){//如果字符序列不为空或长度为0

try{

JSONArray allCities= newJSONArray(response);for(int i = 0; i < allCities.length(); i++){

JSONObject CityObject=allCities.getJSONObject(i);

City city= newCity();

city.setCityName(CityObject.getString("name"));

city.setCityCode(CityObject.getInt("id"));

city.setProvinceId(provinceId);

city.save();

}return true;

}catch(JSONException e){

e.printStackTrace();

}

}return false;

}/***解析和处理服务器返回的县级数据*/

public static boolean handleCountyResponse(String response, intcityId){if(!TextUtils.isEmpty(response)){//如果字符序列不为空或长度为0

try{

JSONArray allCounties= newJSONArray(response);for(int i = 0; i < allCounties.length(); i++){

JSONObject countyObject=allCounties.getJSONObject(i);

County county= newCounty();

county.setCountyName(countyObject.getString("name"));

county.setWeatherId(countyObject.getString("weather_id"));

county.setCityId(cityId);

county.save();

}return true;

}catch(JSONException e){

e.printStackTrace();

}

}return false;

}

}

解析处理数据

因为遍历全国省市的功能经常复用,所以写在碎片里面:

先是一个choose_area.xml作为碎片fragment的布局:

fragment的布局

一个标题栏和一个滚动控件ListView,标题栏是一个RelativeLayout,拥有一个文字标题,一个按钮

然后是fragment的java代码

/*** Created by xbt on 2017/9/8.

* 用于遍历省市县数据的碎片*/

public class ChooseAreaFragment extendsandroid.support.v4.app.Fragment {public static final int LEVEL_PROVINCE = 0;public static final int LEVEL_CITY = 1;public static final int LEVEL_COUNTY = 2;privateProgressBar progressDialog;privateTextView titleText;privateButton backButton;privateListView listView;private ArrayAdapteradapter;private List dataList = new ArrayList<>();/*** 省列表*/

private ListprovinceList;/*** 市列表*/

private ListcityList;/*** 县列表*/

private ListcountyList;/*** 选中的省份*/

privateProvince selectedProvince;/*** 选中的城市*/

privateCity selectedCity;/*** 选中的县*/

privateCounty selectedCounty;/*** 当前被选中的级别*/

private intcurrentLevel;

@Nullable

@OverridepublicView onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

View view= inflater.inflate(R.layout.choose_area,container,false);

titleText=(TextView) view.findViewById(R.id.title_text);

backButton=(Button) view.findViewById(R.id.back_button);

listView=(ListView) view.findViewById(R.id.list_view);

adapter= new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1,dataList);

listView.setAdapter(adapter);returnview;

}public voidonActivityCreated( Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);

listView.setOnItemClickListener(newAdapterView.OnItemClickListener() {

@Overridepublic void onItemClick(AdapterView> adapterView, View view, int position, longid) {if(currentLevel ==LEVEL_PROVINCE){

selectedProvince=provinceList.get(position);

queryCities();

}else if(currentLevel ==LEVEL_CITY){

selectedCity=cityList.get(position);

queryCounties();

}

}

});

backButton.setOnClickListener(newView.OnClickListener() {

@Overridepublic voidonClick(View view) {if(currentLevel ==LEVEL_COUNTY){

queryCities();

}else if(currentLevel ==LEVEL_CITY){

queryProvinces();

}

}

});

queryProvinces();

}/*** 查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询*/

private voidqueryProvinces(){

titleText.setText("中国");

backButton.setVisibility(View.GONE);

provinceList= DataSupport.findAll(Province.class);if(provinceList.size() > 0){

dataList.clear();for(Province province : provinceList){

dataList.add(province.getProvinceName());

}

adapter.notifyDataSetChanged();

listView.setSelection(0);

currentLevel=LEVEL_PROVINCE;

}else{

String address= "http://guolin.tech/api/china";

queryFromServer(address,"province");

}

}/*** 查询全国所有的市,优先从数据库查询,如果没有查到再去服务器上查询*/

private voidqueryCities(){

titleText.setText(selectedProvince.getProvinceName());

backButton.setVisibility(View.VISIBLE);

cityList= DataSupport.where("provinceid = ?", String.valueOf(selectedProvince.getId())).find(City.class);if(cityList.size() > 0){

dataList.clear();for(City city : cityList){

dataList.add(city.getCityName());

}

adapter.notifyDataSetChanged();

listView.setSelection(0);

currentLevel=LEVEL_CITY;

}else{int provinceCode =selectedProvince.getProvinceCode();

String address= "http://guolin.tech/api/china/" +provinceCode;

queryFromServer(address,"city");

}

}/*** 查询全国所有的县,优先从数据库查询,如果没有查到再去服务器上查询*/

private voidqueryCounties(){

titleText.setText(selectedCity.getCityName());

backButton.setVisibility(View.VISIBLE);

countyList= DataSupport.where("cityid = ?", String.valueOf(selectedCity.getId())).find(County.class);if(countyList.size() > 0){

dataList.clear();for(County county : countyList){

dataList.add(county.getCountyName());

}

adapter.notifyDataSetChanged();

listView.setSelection(0);

currentLevel=LEVEL_COUNTY;

}else{int cityCode =selectedCity.getCityCode();int provinceCode =selectedProvince.getProvinceCode();

String address= "http://guolin.tech/api/china/" + provinceCode + "/" +cityCode;

queryFromServer(address,"county");

}

}/*** 根据传入的地址和类型从服务器上查询省市县的数据*/

private void queryFromServer(String address, finalString type){

HttpUtil.sendOkHttpRequest(address,newCallback() {

@Overridepublic voidonFailure(Call call, IOException e) {//通过runOnUiThread回到主线程处理逻辑

getActivity().runOnUiThread(newRunnable() {

@Overridepublic voidrun() {

Toast.makeText(getContext(),"加载失败",Toast.LENGTH_SHORT).show();

}

});

}

@Overridepublic void onResponse(Call call, Response response) throwsIOException {

String responseText=response.body().string();boolean result = false;if("province".equals(type)){

result=Utility.handleProvinceResponse(responseText);

}else if("city".equals(type)){

result=Utility.handleCityResponse(responseText, selectedProvince.getId());

}else if("county".equals(type)){

result=Utility.handleCountyResponse(responseText,selectedCity.getId());

}if(result){

getActivity().runOnUiThread(newRunnable() {

@Overridepublic voidrun() {if("province".equals(type)){

queryProvinces();

}else if("city".equals(type)){

queryCities();

}else if("county".equals(type)){

queryCounties();

}

}

});

}

}

});

}

}

遍历全国省市县的碎片java代码

这段代码的大概逻辑就是其中的这个方法:注释写的格外仔细了些

public voidonActivityCreated( Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);//列表的点击事件响应

listView.setOnItemClickListener(newAdapterView.OnItemClickListener() {

@Overridepublic void onItemClick(AdapterView> adapterView, View view, int position, longid) {//如果当前级别是省,那点击选取的就是某个省,而想要查询的是选中省有那些城市,市同理 ,想要查询这个城市有那些县

if(currentLevel ==LEVEL_PROVINCE){

selectedProvince=provinceList.get(position);

queryCities();//查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询

}else if(currentLevel ==LEVEL_CITY){

selectedCity=cityList.get(position);

queryCounties();//查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询

}

}

});//返回按钮响应

backButton.setOnClickListener(newView.OnClickListener() {

@Overridepublic voidonClick(View view) {//如果当前级别是市,点击返回就是想重新选省,县同理,想重新选市

if(currentLevel ==LEVEL_COUNTY){

queryCities();//查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询

}else if(currentLevel ==LEVEL_CITY){

queryProvinces();//查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询

}

}

});

queryProvinces();//活动刚启动,没有选取省市县就直接展示全国34个省

}

结果:

Java做天气预报app_天气预报APP(1)相关推荐

  1. Java实现旅游app_旅游app源码(在路上)

    [实例简介] [实例截图] [核心代码] package com.yuhj.ontheway.activity; import java.util.ArrayList; import com.yuhj ...

  2. java实现---中央气象局天气预报接口

    一.说明 天气预报的webService地址:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx (天气预报 Web 服务,数据每2 ...

  3. java获取新浪天气预报代码

    package com.test.commons;/*** java获取新浪天气预报代码*/ import java.io.FileNotFoundException; import java.io. ...

  4. python制作在线答题app_如何做线上答题APP、线上答题APP都有哪些功能呢?

    如何做线上答题APP.线上答题APP都有哪些功能呢? 现如今线上答题的系统接踵而至,让家长和学生们都不知道该如何选择,选择怎么样的是对的是好的,下面就来简单介绍一下对于线上教育APP都应该有哪些功能? ...

  5. 天气预报文字版微信_微信里的励志天气预报(每日天气预报加励志)

    微信里的励志天气预报(每日天气预报加励志) 2020-05-18 14:28:25 共10个回答 有个天气预报+励志短语的软件吗 你要是苹果手机,直接到AppStore搜"天气预报",前五个有一个是M ...

  6. java与java ee_CapeDwarf – Java EE上的Google App Engine

    java与java ee 我有很多爱好. 从早期的Java EE规范一路走来,并用Java EE 7进行了"云"之旅,我很好奇看到新宣布的CapeDwarf项目有什么库存,可以在内 ...

  7. java制作安卓客户端,java做服务器,android干客户端,实现数据传输

    java做服务器,android做客户端,实现数据传输 许久未动笔,有个小项目开始动工. 需要用一台windows电脑做服务器,在android端与其进行数据交换,实现一些业务. 简单起见,用java ...

  8. Java生鲜电商平台-App系统架构开发与设计

    Java生鲜电商平台-App系统架构开发与设计 说明:阅读此文,你可以学习到以下的技术分享 1.Java生鲜电商平台-App架构设计经验谈:接口的设计 2.Java生鲜电商平台-App架构设计经验谈: ...

  9. 一步步做一个数字手势识别APP

    一步步做一个数字手势识别APP   这篇博客主要基于我做的一个数字手势识别APP,具体分享下如何一步步训练一个卷积神经网络模型(CNN)模型,然后把模型集成到Android Studio中,开发一个数 ...

最新文章

  1. mocha 测试 mysql_mocha 的基本用法 istanbul 生成测试覆盖率报告 mockjs 模拟网络请求...
  2. Win XP系统的开机菜单具体含义
  3. 项目信息追踪(Log)
  4. Python爬虫(十三)_案例:使用XPath的爬虫
  5. 文本分类和提取关键词算法_文本内容之间的关键词提取和相似度计算
  6. uva 11400——Lighting System Design
  7. ESP32 coredump 分析
  8. HTML+CSS+JS实现 ❤️svg图片透明层文本显示❤️
  9. 图像的频率谱和功率谱代表什么_视频/图像质量评价综述(三)
  10. HTML5 Canvas API详解
  11. 网络硬盘录像机、边缘存储和云存储的优缺点
  12. MySQLdb/_mysql.c(29) : fatal error C1083: Cannot open include file: ‘mysql.h‘: No such file or direc
  13. flutter入门之实现展示机构树的功能
  14. 画质超高的仙侠java游戏_画质超高的仙侠手游
  15. 真正厉害的人,都在延迟满足
  16. VMware虚拟机软件安装国产操作系统 统信 UOS V20 1050e 手把手保姆教程
  17. deepin入坑前必读(懊悔篇)
  18. IPhone弹出基于Phonegap的工程的Admob广告
  19. 找不到全局编录服务器,将 DC 提升至全局编录服务器时出现问题 - Windows Server | Microsoft Docs...
  20. signature=9e4f4b0dad18452c0736b320a827b91f,Lenze CAN-BUS B-C

热门文章

  1. 第七周——复数模板类
  2. 前端性能优化的14个规则
  3. iOS 应用剖析-目录结构
  4. 基于AT89C51单片机的电子时钟设计
  5. 腾讯云Linux服务器搭建(三) Mysql 8.0.11的安装和设置
  6. 必须得会的汽车ECU研发基础—HIL测试简介8
  7. 浅谈三种近场通信技术的特点,对未来近场通信技术的应用场景进行分析与预测
  8. 【能效管理】AcrelEMS-UT综合管廊能效管理平台解决方案应用分析
  9. Centos 7 一键安装Redash (Centos7 + Docker)
  10. 热门技术中的应用:容器技术中的网络-第30讲-容器网络之Flannel:每人一亩三分地