GVKun编程网logo

使用Flutter开发的一款天气预报APP(flutter 天气预报)

16

如果您想了解使用Flutter开发的一款天气预报APP和flutter天气预报的知识,那么本篇文章将是您的不二之选。我们将深入剖析使用Flutter开发的一款天气预报APP的各个方面,并为您解答flu

如果您想了解使用Flutter开发的一款天气预报APPflutter 天气预报的知识,那么本篇文章将是您的不二之选。我们将深入剖析使用Flutter开发的一款天气预报APP的各个方面,并为您解答flutter 天气预报的疑在这篇文章中,我们将为您介绍使用Flutter开发的一款天气预报APP的相关知识,同时也会详细的解释flutter 天气预报的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

使用Flutter开发的一款天气预报APP(flutter 天气预报)

使用Flutter开发的一款天气预报APP(flutter 天气预报)

前段时间看了下Flutter相关资料,看完感觉还是啥都不会,决定写个小APP来练习一下吧。
效果图如下:

启动

在这里插入图片描述


项目地址:https://github.com/Zhengyi66/Flutter_weather

项目解析

功能模块

1、天气:
天气模块使用的是pageview,首页展示当天天气信息,第二个页面展示了24小时天气详细信息和一周天气。
2、今日热点
新闻列表展示、刷新、加载,点击跳转链接
3、新闻搜索
新闻搜索功能,点击跳转到新闻详情页
4、选择城市
选择要查看天气的城市,并刷新主页数据

天气模块实现

今日热点

搜索

选择城市

1个人,100天业余时间,用Flutter开发完一个商业APP

1个人,100天业余时间,用Flutter开发完一个商业APP

项目介绍

这个一个淘电商APP,同类型的APP有花生日记、好省、折800等等,基本上一个常规电商APP该有的,这个项目都有了。目前,该项目的完成度为80%,剩余的20%因为没有后台项目支持,所以无法完成。

为啥要做这个东西勒,因为作为Flutter的早期研究者,有不少人都问过我,Flutter现在可不可以做商业项目?现有的原生项目接入Flutter靠不靠谱?Flutter会不会有很多功能不能实现?……

当时我自己也没有正儿八经的做过商业项目,所以都不敢说可以做,基本都是含糊其辞都回答,甚至当作没看到信息,就没有回复了。所以我急切的想做一个商业项目,实际用Flutter开发商业项目,发现开发过程中的问题,用实际开发经历来回答类似的问题。

很巧的是,大约100天前,正好有网友想让我兼职开发一个淘电商APP,正好给了我这个机会,于是我便开始了开发,并记录下项目开始开发以来花费了多少时间。

可以看到,到项目差不多完成时,一共是100天,而开发人员只有我1个人兼职开发,而且还是一个跨iOS、Android双平台的APP。现在,我想我应该可以回答上面提到的几个问题了:

Flutter现在可不可以做商业项目?

  • 通过Google的近几年的发布会可以得知,得益于Google云服务的便利,Flutter已经成为国外开发者开发新项目时的首选
  • 我现在这个淘电商项目应该也可以做一个例子吧

现有的原生项目接入Flutter靠不靠谱?

  • 咸鱼APP的部分页面,已经是使用Flutter实现的
  • 爱奇艺直播助手APP的部分页面,也已经是用Flutter实现的了

Flutter会不会有很多功能不能实现?

  • 目前,Flutter插件仓库里已经有4200多个插件了,其中包含国内常用的各种推送、社会分享、微信QQ支付宝登录、各种授权登陆、微信支付宝支付、淘系电商等对接原生SDK等第三方插件
  • 因为通过插件可以在Flutter与原生代码之间搭建桥梁,所以基本上,原生可以实现的功能,Flutter都可以实现

国内服务提供商对Flutter生态的支持如何?

  • 极光推送已经为开发者准备好了极光推送的Flutter插件
  • 阿里巴巴已经为Flutter贡献了一个视图UI与逻辑代码分离的第三方框架

用Flutter开发应用可以上架App Store吗?

  • 有这个担心其实是因为RN之前有前例,但是理性分析一下,有些RN为啥会被下架呢?不过是因为哪些APP本身违背了App Store的规则,热更新从理性上思考,难道不是一个安全风险吗?
  • Flutter应用如果本身不违背App Store的规则,基本是不用担心这个问题的

Flutter作为跨平台开发的性能好不好?

  • Flutter的性能与原生一模一样,帧频率达到到60帧/秒是基本操作

后面是我对Flutter开发过程中的一些想法:

  • 跨全平台开发很理想,但是现在不可能,在实际开发过程中,你难免会用到第三方的插件,而哪些插件又依赖Android或iOS的原生SDK,那你的项目还怎么在PC、Mac、Web跑呢?除非出现大量用Dart语言编写的插件(“SDK”)出现,不然跨全平台开发就是空中阁楼
  • Flutter的热重载只对微调,比如调大小、移动上下左右几个单位、组件的内容文本图片什么的改一下方便,一旦代码动的多了,一热重载,大部分时候页面都会显示一片红,如何又是一顿代码调整。特别是接口联调,真的别指望热重载能多方便
  • 没有原生开发经验的话,发布应用的时候会踩很多原生开发的坑,因为一旦你要打包Flutter程序,那就涉及到Android、iOS原生开发的知识点了,特别是原生Android打包发布的坑,经常让我一搞就是几个小时甚至更久,心疼原生Android开发的小伙伴一秒
  • 对于之前没有学过原生开发的人来说,学过Flutter以后,估计不会再去学习原生开发了,毕竟原生开发只能开发单平台,毕竟如果你可以开发多平台的APP时,你还会满足单平台开发吗?
  • 就目前来说,因为目前Flutter插件还没有完全覆盖国内的移动开发生态,你难免会需要自己去开发插件,以接入国内的某个服务SDK,这时候,除了找原生开发的小伙伴帮忙以外,就只剩下你自己开发的路可以走了。不过自己开发的难度也还好,因为各种原生SDK怎么使用在百度上一堆现成的代码,你只要会一些原生基础完全搞的定

APP展示

项目地址:https://github.com/hekaiyou/jedi
2019秋招必备面试题汇总+阿里P6P7安卓进阶资料分享

7*24小时天气预报api

7*24小时天气预报api

24小时天气预报api提供数据气象方面,包括天气预报和空气质量预报的精细化的服务

根据输入区号查询实况天气数据

接口地址:http://v.juhe.cn/xiangji_weather/real_time_weather.php

支持格式:json

请求方式:get

请求示例:http://v.juhe.cn/xiangji_weather/real_time_weather.php?areaid=101010100&key=YOURKEY

接口备注:根据输入区号查询实况天气数据

JSON返回示例:

{
    "reason": "success",
    "result": {
        "pubTime": "20160115172532",//发布时间(yyyyMMddHHmmss) 
  
        "reqTime": "20160115173718",//收到请求时间(yyyyMMddHHmmss) 
   
        "data": {
            "cw": "01",//天气现象编码
            "w": "多云",//天气现象
            "rh": 55,//相对湿度
            "cwd": "东风",//风向描述
            "wd": "2 级",//风力描述
            "wdg": 2,//风力级别
            "tmp": 3,//温度
            "airp": 1015,//气压
            "st": 3//体感温度
        }
    },
    "error_code": 0
}

逐小时预报天气数据

接口地址:http://v.juhe.cn/xiangji_weather/weather_byHour_areaid.php

支持格式:json

请求方式:get

请求示例:http://v.juhe.cn/xiangji_weather/weather_byHour_areaid.php?areaid=101010100&startTime=2016011501&endTime=2016011714&key=YOURKEY

接口备注:根据输入区号和起始时间查询逐小时预报天气数据

JSON返回示例:

{
    "reason": "success",
    "result": {
        "startTime": "2016011513",//开始时间(yyyyMMddHH),对应series中第一条数据
        "pubTime": "20160115175358",//发布时间(yyyyMMddHHmmss) 
        
         reqTime:"20150831171212",//收到请求时间(yyyyMMddHHmmss) 
  
        "series": [//逐小时数据序列,每个小时一个值,第一条对应starttime 
  
            {
                "cw": "01",//天气现象编码
                "w": "多云",//天气现象
                "rh": 30,//相对湿度
                "cwd": "07",//风向编码
                "wd": "东风",//风向描述
                "wdg": 0,//风力级别
                "tmp": 3,//预测温度
                "airp": 1019,//气压
                "st": -4//体感温度
            },
            {
                "cw": "01",
                "w": "多云",
                "rh": 30,
                "cwd": "07",
                "wd": "东风",
                "wdg": 0,
                "tmp": 4,
                "airp": 1019,
                "st": -4
            }
        ],
        "count": 2,//数据条数,endTime-­‐startTime+1的小时数
        "endTime": "2016011514"//结束时间,对应series中最后一条数据 
  
    },
    "error_code": 0
}

15天概览天气预报数据

接口地址:http://v.juhe.cn/xiangji_weather/15_area.php

支持格式:json

请求方式:get

请求示例:http://v.juhe.cn/xiangji_weather/15_area.php?areaid=101010100&startTime=20160116&endTime=20160201&key=YOURKEY

接口备注:根据输入地区编码查询15天概览天气预报数据,发布频率每日一次,北京时间点,空间范围:全国 空间分辨率 公里级别 时间范围 当天点-点:未来14 天(含今天) 当天点-23 点:未来15 天(含今天) 时间分辨率 逐日级别

JSON返回示例:

{
    "reason": "success",
    "result": {
        "pubTime": "20160116223359",
        "startTime": "20160116",
        "series": [
            {
                "cw_am": "02",//天气现象编码上午
                "w_am": "阴",//天气现象上午
                "cw_pm": "15",//天气现象编码下午
                "w_pm": "中雪",//天气现象下午
                "wd": "东北风",//风向描述
                "wind": "3 级",//风力
                "cwd": "06",//风向编码
                "tmp_max": -1,//预测最高温度
                "tmp_min": -5,//预测最低温度
                "sunrise": "07:34",//日出时间
                "sunset": "17:14"//日落时间
            },
            {
                "cw_am": "14",
                "w_am": "小雪",
                "cw_pm": "01",
                "w_pm": "多云",
                "wd": "东北风",
                "wind": "3 级",
                "cwd": "06",
                "tmp_max": -2,
                "tmp_min": -7,
                "sunrise": "07:34",
                "sunset": "17:15"
            },
            {
                "cw_am": "00",
                "w_am": "晴",
                "cw_pm": "00",
                "w_pm": "晴",
                "wd": "东北风",
                "wind": "微风",
                "cwd": "06",
                "tmp_max": -3,
                "tmp_min": -9,
                "sunrise": "07:33",
                "sunset": "17:17"
            },
            {
                "cw_am": "00",
                "w_am": "晴",
                "cw_pm": "00",
                "w_pm": "晴",
                "wd": "北风",
                "wind": "4 级",
                "cwd": "05",
                "tmp_max": 0,
                "tmp_min": -10,
                "sunrise": "07:33",
                "sunset": "17:18"
            },
            {
                "cw_am": "01",
                "w_am": "多云",
                "cw_pm": "02",
                "w_pm": "阴",
                "wd": "西北风",
                "wind": "5 级",
                "cwd": "04",
                "tmp_max": -1,
                "tmp_min": -7,
                "sunrise": "07:32",
                "sunset": "17:19"
            },
            {
                "cw_am": "02",
                "w_am": "阴",
                "cw_pm": "02",
                "w_pm": "阴",
                "wd": "东北风",
                "wind": "4 级",
                "cwd": "06",
                "tmp_max": -3,
                "tmp_min": -6,
                "sunrise": "07:32",
                "sunset": "17:20"
            },
            {
                "cw_am": "02",
                "w_am": "阴",
                "cw_pm": "00",
                "w_pm": "晴",
                "wd": "北风",
                "wind": "3 级",
                "cwd": "05",
                "tmp_max": -5,
                "tmp_min": -9,
                "sunrise": "07:31",
                "sunset": "17:21"
            },
            {
                "cw_am": "01",
                "w_am": "多云",
                "cw_pm": "01",
                "w_pm": "多云",
                "wd": "东北风",
                "wind": "微风",
                "cwd": "06",
                "tmp_max": -10,
                "tmp_min": -15,
                "sunrise": "07:31",
                "sunset": "17:22"
            },
            {
                "cw_am": "01",
                "w_am": "多云",
                "cw_pm": "01",
                "w_pm": "多云",
                "wd": "东北风",
                "wind": "3 级",
                "cwd": "06",
                "tmp_max": -4,
                "tmp_min": -14,
                "sunrise": "07:30",
                "sunset": "17:23"
            },
            {
                "cw_am": "00",
                "w_am": "晴",
                "cw_pm": "02",
                "w_pm": "阴",
                "wd": "西北风",
                "wind": "5 级",
                "cwd": "04",
                "tmp_max": -1,
                "tmp_min": -10,
                "sunrise": "07:29",
                "sunset": "17:25"
            },
            {
                "cw_am": "01",
                "w_am": "多云",
                "cw_pm": "00",
                "w_pm": "晴",
                "wd": "西风",
                "wind": "微风",
                "cwd": "03",
                "tmp_max": 2,
                "tmp_min": -8,
                "sunrise": "07:28",
                "sunset": "17:26"
            },
            {
                "cw_am": "01",
                "w_am": "多云",
                "cw_pm": "02",
                "w_pm": "阴",
                "wd": "西风",
                "wind": "微风",
                "cwd": "03",
                "tmp_max": 2,
                "tmp_min": -7,
                "sunrise": "07:28",
                "sunset": "17:27"
            },
            {
                "cw_am": "02",
                "w_am": "阴",
                "cw_pm": "02",
                "w_pm": "阴",
                "wd": "北风",
                "wind": "微风",
                "cwd": "05",
                "tmp_max": 4,
                "tmp_min": -6,
                "sunrise": "07:27",
                "sunset": "17:28"
            },
            {
                "cw_am": "02",
                "w_am": "阴",
                "cw_pm": "02",
                "w_pm": "阴",
                "wd": "东北风",
                "wind": "微风",
                "cwd": "06",
                "tmp_max": 4,
                "tmp_min": -6,
                "sunrise": "07:26",
                "sunset": "17:29"
            },
            {
                "cw_am": "02",
                "w_am": "阴",
                "cw_pm": "02",
                "w_pm": "阴",
                "wd": "北风",
                "wind": "3 级",
                "cwd": "05",
                "tmp_max": 5,
                "tmp_min": -4,
                "sunrise": "07:25",
                "sunset": "17:31"
            }
        ],
        "count": 15,
        "endTime": "20160130"
    },
    "error_code": 0
}

城市实况指数数据

接口地址:http://v.juhe.cn/xiangji_weather/exponential_byAreaId.php

支持格式:json

请求方式:get

请求示例:http://v.juhe.cn/xiangji_weather/exponential_byAreaId.php?areaid=101010100&key=YOURKEY

接口备注:根据输入地区编码查询城市实况指数数据

JSON返回示例:

{
    "reason": "success",
    "result": {
        "pubTime": "20160116000000",
        "reqTime": "20160116225821",
        "data": [
            {
                "i5": "风力稍大,较不宜晨练,室外锻炼请注意选择避风的地点,避免迎风锻炼。",//提醒内容
                "i4": "较不宜",//级别
                "i3": "",//别称
                "i2": "晨练指数",//穿衣指数
                "i1": "cl"//英文简称
            },
            {
                "i5": "天气寒冷,建议着厚羽绒服、毛皮大衣加厚毛衣等隆冬服装。年老体弱者尤其要注意保暖防冻。",
                "i4": "寒冷",
                "i3": "",
                "i2": "穿衣指数",
                "i1": "ct"
            },
            {
                "i5": "天气寒冷,请用滋润保湿型化妆品,少扑粉,使用润唇膏后再抹口红。",
                "i4": "保湿",
                "i3": "",
                "i2": "化妆指数",
                "i1": "pp"
            },
            {
                "i5": "天空状况还是比较好的,但温度比较低,且风稍大,会让人感觉有点冷。外出请备上防风保暖衣物。",
                "i4": "一般",
                "i3": "",
                "i2": "旅游指数",
                "i1": "tr"
            },
            {
                "i5": "不宜洗车,未来24小时内有雪,如果在此期间洗车,雪水和路上的泥水可能会再次弄脏您的爱车。",
                "i4": "不宜",
                "i3": "",
                "i2": "洗车指数",
                "i1": "xc"
            },
            {
                "i5": "温度不高,其他各项气象条件适宜,中暑机率极低。",
                "i4": "无",
                "i3": "",
                "i2": "中暑指数",
                "i1": "zs"
            }
        ]
    },
    "error_code": 0
}

实况空气质量数据

接口地址:http://v.juhe.cn/xiangji_weather/live_air.php

支持格式:json

请求方式:get

请求示例:http://v.juhe.cn/xiangji_weather/live_air.php?key=YOURKEY

接口备注:返回所有地区空气质量最近一次观测值

JSON返回示例:

{
    "reason": "success",
    "result": {
        "count": 2504,
        "kdatalistey": [
            {
                "areaid": "101010100",
                "uptime": "20160116230000",
                "so2": 36,//二氧化硫
                "co": 2.24,//一氧化碳
                "no2": 70,//二氧化碳
                "o3": 11,//臭氧
                "p10": 166,//pm10
                "p25": 139//pm2.5
            },
            {
                "areaid": "101290312",
                "uptime": "20160116230000",
                "so2": 12,
                "co": 1.16,
                "no2": 25,
                "o3": 83,
                "p10": 50,
                "p25": 41
            }
        ]
    },
    "error_code": 0
}


Android天气预报app改进版

Android天气预报app改进版

最近总是有人来和我说我以前写的一个小app无法正常获取数据~Android简易版天气预报app
今天就又运行了下来查找问题,发现或许是接口有限制吧,不能在多台手机使用同个apikey
然后,发现了我写的代码实在乱七八糟,界面也实在不好看,就又重写了一遍,小小地修改了一遍,开发环境改为了Android Studio

最终效果图如下

这里写图片描述

 

工程图如下

一、获取地区信息

做这么一个天气预报app,首先就要获取到国内地区列表
(在我的另一篇博客有介绍:向任意网址发起数据请求)
中国天气网开放有天气预报接口,访问“http://www.weather.com.cn/data/list3/city.xml”就可以获取到国内省份列表以及其代号了

这里写图片描述

如果想要获取广东省下的城市列表,由上图可知广东省的代号为28,则接口地址是 “http://www.weather.com.cn/data/list3/city28.xml”,获取到的城市列表及代号如下:

这里写图片描述

 

依次类推还可以获取到更加详细的地区信息,这样就完成了开头部分

二、天气信息的获取

百度的APIStore拥有丰富的接口,涵盖了生活的许多方面。例如,我们就可以通过APIStore的某个接口获取到含有天气信息的JSON数据,从而实现天气预报功能
(在我的另一篇博客有介绍:获取含天气信息的JSON数据)
首先,使用者要有一个百度账号,然后登陆以下网址:中国和世界天气预报
该接口是免费的,不过因此也就不够稳定,我在调试的时候就经常出错
然后在API选项下点击“您自己的apikey”,查看自己的apikey。该值是每个开发者和app的唯一标识,需要妥善保管,有了apikey才可以进行下一步的操作

这里写图片描述

获取到的天气信息是JSON格式的,需要在程序中再来解析

 

三、数据库的设计

地区列表这些信息一般都是固定不变的,所以我们可以把第一次联网获取到的数据存进数据库里,下次再次访问时就从数据库里读取即可
首先要设定四个Model,包括:省份、城市、县、每小时天气预测,用来承载数据
每个Model包括几个属性以及相应的get和set方法
例如,省份Province的设计如下所示,城市City和县County的设计类似

/**
 * 省份
 */
public class Province {
 //省份名
 private String provinceName;
 //省份ID
 private String provinceId;

 public String getProvinceId() {
  return provinceId;
 }

 public String getProvinceName() {
  return provinceName;
 }

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

 public void setProvinceName(String provinceName) {
  this.provinceName = provinceName;
 }
}

每小时天气预测HourlyWeather的设计如下:

/**
 * Created by ZY on 2016/7/21.
 */
public class HourlyWeather {

 //预测时间
 private String time;
 //温度
 private String temp;
 //降水概率
 private String pop;
 //风力
 private String wind;

 public HourlyWeather(String time,String temp,String pop,String wind) {
  this.time = time;
  this.temp = temp;
  this.pop = pop;
  this.wind = wind;
 }

 public String getTime() {
  return time;
 }

 public String getTemp() {
  return temp;
 }

 public String getPop() {
  return pop;
 }

 public String getwind() {
  return wind;
 }
}

然后,新建一个DatabaseHelper类继承于sqliteOpenHelper,用来建立三个数据库表

public class DatabaseHelper extends sqliteOpenHelper {

 private final String CREATE_PROVINCE = "create table Province ("
   + "provinceName text," + "provinceId text )";

 private final String CREATE_CITY = "create table City("
   + "cityName text," + "cityId text," + "provinceId text)";

 private final String CREATE_COUNTY = "create table County("
   + "countyName text," + "countyId text," + "cityId text)";

 public DatabaseHelper(Context context,String dbname,CursorFactory factory,int version) {
  super(context,dbname,factory,version);
 }

 @Override
 public void onCreate(sqliteDatabase db) {
  db.execsql(CREATE_PROVINCE);
  db.execsql(CREATE_CITY);
  db.execsql(CREATE_COUNTY);
 }

 @Override
 public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) {

 }

}

然后,再建立一个WeatherDB类,用来进行实际的数据库操作,包括存取省份信息、城市信息、县信息等
需要注意的是,因为每个城市都是包含在某个省份下的,所以查询某个省份下的所有城市列表,需要将省份的ID传入作为唯一标识

public class WeatherDB {

 private final String DataBaseName = "ZyWeather";

 private final int VERSION = 1;

 private sqliteDatabase database;

 private static WeatherDB weatherDB;

 private WeatherDB(Context context) {
  DatabaseHelper dataBaseHelper = new DatabaseHelper(context,DataBaseName,null,VERSION);
  database = dataBaseHelper.getWritableDatabase();
 }

 //获取实例
 public static WeatherDB getInstance(Context context) {
  if (weatherDB == null) {
   weatherDB = new WeatherDB(context);
  }
  return weatherDB;
 }

 //保存省份信息
 public void saveProvinces(List<Province> provinceList) {
  if (provinceList != null && provinceList.size() > 0) {
   ContentValues values = new ContentValues();
   for (int i = 0; i < provinceList.size(); i++) {
    values.put("provinceName",provinceList.get(i).getProvinceName());
    values.put("provinceId",provinceList.get(i).getProvinceId());
    database.insert("Province",values);
    values.clear();
   }
  }
 }

 //保存城市信息
 public void saveCities(List<City> cityList) {
  if (cityList != null && cityList.size() > 0) {
   ContentValues values = new ContentValues();
   for (int i = 0; i < cityList.size(); i++) {
    values.put("cityName",cityList.get(i).getCityName());
    values.put("cityId",cityList.get(i).getCityId());
    values.put("provinceId",cityList.get(i).getProvinceId());
    database.insert("City",values);
    values.clear();
   }
  }
 }

 //保存乡村信息
 public void saveCounties(List<County> countyList) {
  if (countyList != null && countyList.size() > 0) {
   ContentValues values = new ContentValues();
   for (int i = 0; i < countyList.size(); i++) {
    values.put("countyName",countyList.get(i).getCountyName());
    values.put("countyId",countyList.get(i).getCountyId());
    values.put("cityId",countyList.get(i).getCityId());
    database.insert("County",values);
    values.clear();
   }
  }
 }

 //返回所有省份信息
 public List<Province> getAllProvince() {
  Cursor cursor = database.query("Province",null);
  List<Province> list = new ArrayList<>();
  Province province;
  if (cursor.movetoFirst()) {
   do {
    province = new Province();
    province.setProvinceName(cursor.getString(cursor.getColumnIndex("provinceName")));
    province.setProvinceId(cursor.getString(cursor.getColumnIndex("provinceId")));
    list.add(province);
   } while (cursor.movetoNext());
  }
  return list;
 }

 //返回指定省份下的所有城市
 public List<City> getAllCity(String provinceId) {
  List<City> list = new ArrayList<>();
  City city;
  Cursor cursor = database.query("City","provinceId = ?",new String[]{provinceId},null);
  if (cursor.movetoFirst()) {
   do {
    city = new City();
    city.setCityName(cursor.getString(cursor.getColumnIndex("cityName")));
    city.setCityId(cursor.getString(cursor.getColumnIndex("cityId")));
    city.setProvinceId(provinceId);
    list.add(city);
   } while (cursor.movetoNext());
  }
  return list;
 }

 //返回指定城市下的所有乡村
 public List<County> getAllCountry(String cityId) {
  List<County> list = new ArrayList<>();
  Cursor cursor = database.query("County","cityId=?",new String[]{cityId},null);
  County county;
  if (cursor.movetoFirst()) {
   do {
    county = new County();
    county.setCountyName(cursor.getString(cursor.getColumnIndex("countyName")));
    county.setCountyId(cursor.getString(cursor.getColumnIndex("countyId")));
    county.setCityId(cityId);
    list.add(county);
   } while (cursor.movetoNext());
  }
  return list;
 }

}

四、联网操作

整个app用同一个函数来完成各种数据数据操作,该函数包含在HttpUtil类下,为静态函数
当中需要填入自己申请的apikey,该key仅在获取天气信息时有用,在获取地区信息时是不需要的,这里只是为了简便,所以就一起写上了

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.setRequestProperty("apikey","填入自己的apikey");
     connection.connect();
     InputStream inputStream = connection.getInputStream();
     InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"UTF-8");
     BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
     StringBuilder response = new StringBuilder();
     String line;
     while ((line = bufferedReader.readLine()) != null) {
      response.append(line);
     }
     if (listener != null) {
      listener.onFinish(response.toString());
     }
    } catch (Exception e) {
     if (listener != null) {
      listener.onError(e);
     }
    } finally {
     if (connection != null) {
      connection.disconnect();
     }
    }
   }
  }).start();
 }
}

五、工具类

在联网访问数据成功或失败后,都需要通过回调方法进行数据处理,所以需要设定一个接口HttpCallbackListener

public interface HttpCallbackListener {

 void onFinish(String response);

 void onError(Exception e);

}

此外,使用HttpUtil 类获取到地区信息后,因为数据包含一些分隔符,无法直接存入数据库,而且获取到的天气信息也是JSON格式的,也需要进行数据解析,所以还需要有一个Utility类用来进行数据处理

public class Utility {

 // 保存服务器返回的省级数据
 public static boolean saveProvincesResponse(WeatherDB weatherDB,String response) {
  if (!TextUtils.isEmpty(response)) {
   String[] allProvinces = response.split(",");
   if (allProvinces != null && allProvinces.length > 0) {
    Province province;
    List<Province> provinceList = new ArrayList<>();
    for (String p : allProvinces) {
     String[] array = p.split("\\|");
     province = new Province();
     province.setProvinceId(array[0]);
     province.setProvinceName(array[1]);
     provinceList.add(province);
    }
    weatherDB.saveProvinces(provinceList);
    return true;
   }
  }
  return false;
 }

 // 保存服务器返回的市级数据
 public static boolean saveCitiesResponse(WeatherDB weatherDB,String response,String provinceId) {
  if (!TextUtils.isEmpty(response)) {
   String[] allCities = response.split(",");
   if (allCities != null && allCities.length > 0) {
    City city;
    List<City> cityList = new ArrayList<>();
    for (String c : allCities) {
     String[] array = c.split("\\|");
     city = new City();
     city.setCityId(array[0]);
     city.setCityName(array[1]);
     city.setProvinceId(provinceId);
     cityList.add(city);
    }
    weatherDB.saveCities(cityList);
    return true;
   }
  }
  return false;
 }

 // 保存服务器返回的县级数据
 public static boolean saveCountiesResponse(WeatherDB weatherDB,String cityId) {
  if (!TextUtils.isEmpty(response)) {
   String[] allCounties = response.split(",");
   if (allCounties != null && allCounties.length > 0) {
    County county;
    List<County> countyList = new ArrayList<>();
    for (String c : allCounties) {
     String[] array = c.split("\\|");
     county = new County();
     county.setCountyId(array[0]);
     county.setCountyName(array[1]);
     county.setCityId(cityId);
     countyList.add(county);
    }
    weatherDB.saveCounties(countyList);
    return true;
   }
  }
  return false;
 }

 // 处理服务器返回的json数据
 public static void handleWeatherResponse(Context context,String response) {
  try {
   JSONObject jsonobject = new JSONObject(response);
   JSONArray title = jsonobject.getJSONArray("HeWeather data service 3.0");
   JSONObject first_object = (JSONObject) title.get(0);

   JSONObject basic = (JSONObject) first_object.get("basic");

   //更新时间
   JSONObject update = (JSONObject) basic.get("update");
   JSONArray daily_forecast = (JSONArray) first_object.get("daily_forecast");
   JSONObject daily_forecast_first = (JSONObject) daily_forecast.get(0);
   JSONObject cond = (JSONObject) daily_forecast_first.get("cond");
   //温度
   JSONObject temp = (JSONObject) daily_forecast_first.get("tmp");

   JSONObject astro = (JSONObject) daily_forecast_first.get("astro");

   JSONObject wind = (JSONObject) daily_forecast_first.get("wind");

   JSONArray hourly_forecast = (JSONArray) first_object.get("hourly_forecast");

   WeatherActivity.weatherList.clear();

   for (int i = 0; i < hourly_forecast.length(); i++) {
    JSONObject json = hourly_forecast.getJSONObject(i);
    JSONObject json_wind = (JSONObject) json.get("wind");
    String date = json.getString("date");
    String[] array = date.split(" ");
    String dir = json_wind.getString("dir");
    String sc = json_wind.getString("sc");
    String hourly_clock = array[1];
    String hourly_temp = "温度:" + json.getString("tmp") + "℃";
    String hourly_pop = "降水概率:" + json.getString("pop");
    String hourly_wind = "风力:" + dir + " " + sc + "级";
    HourlyWeather weather = new HourlyWeather(hourly_clock,hourly_temp,hourly_pop,hourly_wind);
    WeatherActivity.weatherList.add(weather);
   }
   //日出
   String sunriseTime = astro.getString("sr");
   //日落
   String sunsetTime = astro.getString("ss");
   //白天天气
   String dayWeather = cond.getString("txt_d");
   //夜晚天气
   String nightWeather = cond.getString("txt_n");
   //风力
   String windText = wind.getString("dir") + " " + wind.getString("sc") + "级";
   //降水概率
   String pop = daily_forecast_first.getString("pop");
   //温度
   String tempText = temp.getString("min") + "℃~" + temp.getString("max") + "℃";
   //更新时间
   String updateTime = update.getString("loc");
   //城市名
   String cityName = basic.getString("city");
   saveWeatherInfo(context,cityName,sunriseTime,sunsetTime,dayWeather,nightWeather,windText,pop,tempText,updateTime);
  } catch (Exception e) {
   e.printstacktrace();
  }
 }

 private static void saveWeatherInfo(Context context,String cityName,String sunriseTime,String sunsetTime,String dayWeather,String nightWeather,String windText,String tempText,String updateTime) {
  SharedPreferences.Editor editor = context.getSharedPreferences("Weather",Context.MODE_PRIVATE).edit();
  editor.putString("cityName",cityName);
  editor.putString("sunriseTime",sunriseTime);
  editor.putString("sunsetTime",sunsetTime);
  editor.putString("dayWeather",dayWeather);
  editor.putString("nightWeather",nightWeather);
  editor.putString("wind",windText);
  editor.putString("pop",pop);
  editor.putString("temp",tempText);
  editor.putString("updateTime",updateTime);
  editor.commit();
 }
}

 六、适配器
由上边的动态图可以看到每小时的天气预测信息,那是使用ListView呈现的,这就要为其提供一个适配器了
ListView使用的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="horizontal">

 <!-- 时间 -->

 <TextView
  android:id="@+id/forecastTime"
  android:layout_width="0dp"
  android:layout_height="match_parent"
  android:layout_weight="2"
  android:gravity="center"
  android:textSize="20sp"
  android:text/>

 <LinearLayout
  android:layout_width="0dp"
  android:layout_height="match_parent"
  android:layout_weight="5"
  android:orientation="vertical">

  <!-- 温度 降水概率 -->

  <LinearLayout
   android:layout_width="match_parent"
   android:layout_height="0dp"
   android:layout_weight="1"
   android:gravity="center"
   android:orientation="horizontal">

   <!-- 温度 -->

   <TextView
    android:id="@+id/forecastTemp"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center" />

   <!-- 下雨概率 -->

   <TextView
    android:id="@+id/forecastPop"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center" />
  </LinearLayout>

  <!-- 风力 -->

  <TextView
   android:id="@+id/forecastwind"
   android:layout_width="match_parent"
   android:layout_height="0dp"
   android:layout_weight="1"
   android:gravity="center" />
 </LinearLayout>

</LinearLayout>

然后新建一个WeatherAdapter继承于ArrayAdapter< HourlyWeather>
只要重写getView(int position,View convertView,ViewGroup parent)方法即可

public class WeatherAdapter extends ArrayAdapter<HourlyWeather> {

 private int resourceId;

 private Context context;

 public WeatherAdapter(Context context,int textViewResourceId,List<HourlyWeather> objects) {
  super(context,textViewResourceId,objects);
  this.context = context;
  this.resourceId = textViewResourceId;
 }

 public View getView(int position,ViewGroup parent) {
  HourlyWeather weather = getItem(position);
  View view = LayoutInflater.from(context).inflate(resourceId,null);

  TextView forecastTime = (TextView) view.findViewById(R.id.forecastTime);
  TextView forecastTemp = (TextView) view.findViewById(R.id.forecastTemp);
  TextView forecastPop = (TextView) view.findViewById(R.id.forecastPop);
  TextView forecastwind = (TextView) view.findViewById(R.id.forecastwind);

  forecastTime.setText(weather.getTime());
  forecastTemp.setText(weather.getTemp());
  forecastPop.setText(weather.getPop());
  forecastwind.setText(weather.getwind());
  return view;
 }

}

七、Activity的编写
首先要完成地区选择界面ChooseAreaActivity
ChooseAreaActivity的界面仅包括一个居中的TextView和一个ListView
布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">

 <RelativeLayout
  android:layout_width="match_parent"
  android:layout_height="50dp">

  <TextView
   android:id="@+id/title"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerInParent="true"
   android:textSize="24sp" />
 </RelativeLayout>

 <ListView
  android:id="@+id/listView"
  android:layout_width="match_parent"
  android:layout_height="match_parent" />

</LinearLayout>

ChooseAreaActivity 需要完成的操作有:完成地区列表的加载、将选择的County名传递给WeatherActivity
此外,当中使用了showProgressDialog()来呈现一个进度对话框,也设为无法通过返回键关闭,而我又没有在弱网环境下调试过,每次加载都是很快,也没见到对话框出来过,所以也不知道showProgressDialog()到底有没有bug啥的~

public class ChooseAreaActivity extends AppCompatActivity {

 // 标记当前列表为省份
 public static final int LEVEL_PROVINCE = 0;
 // 标记当前列表为城市
 public static final int LEVEL_CITY = 1;
 // 标记当前列表为县
 public static final int LEVEL_COUNTY = 2;
 // 进度对话框
 private ProgressDialog progressDialog;
 // 标题栏
 private TextView titleText;
 // 数据列表
 private ListView listView;
 // 列表数据
 private ArrayAdapter<String> adapter;
 // 数据库
 private WeatherDB weatherDB;

 private List<String> dataList;

 private List<Province> provinceList;

 private List<City> cityList;

 private List<County> countyList;
 //选择的省份
 private Province selectedProvince;
 //选择的城市
 private City selectedCity;
 //当前选择的列表类型
 private int currentLevel;
 //标记是否从WeatherActivity跳转而来的
 private boolean isFromWeatherActivity;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  isFromWeatherActivity = getIntent().getBooleanExtra("ChooseArea",false);
  SharedPreferences sharedPreferences = getSharedPreferences("Weather",Context.MODE_PRIVATE);

  // 如果country已选择且本Activity不是从天气界面启动而来的,则直接跳转到WeatherActivity

  if (!TextUtils.isEmpty(sharedPreferences.getString("CountyName","")) && !isFromWeatherActivity) {
   Intent intent = new Intent(this,WeatherActivity.class);
   startActivity(intent);
   finish();
   return;
  }
  setContentView(R.layout.activity_choose_area);
  if (getSupportActionBar() != null) {
   getSupportActionBar().hide();
  }
  listView = (ListView) findViewById(R.id.listView);
  titleText = (TextView) findViewById(R.id.title);
  dataList = new ArrayList<>();
  adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,dataList);
  listView.setAdapter(adapter);
  weatherDB = WeatherDB.getInstance(this);
  listView.setonItemClickListener(new AdapterView.OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView<?> arg0,View arg1,int index,long arg3) {
    if (currentLevel == LEVEL_PROVINCE) {
     selectedProvince = provinceList.get(index);
     queryCities();
    } else if (currentLevel == LEVEL_CITY) {
     selectedCity = cityList.get(index);
     queryCounties();
    } else if (currentLevel == LEVEL_COUNTY) {
     //当点击到县列表时,就利用Intent跳转到天气信息界面
     String countyName = countyList.get(index).getCountyName();
     Intent intent = new Intent(ChooseAreaActivity.this,WeatherActivity.class);
     intent.putExtra("CountyName",countyName);
     startActivity(intent);
     finish();
    }
   }
  });
  queryProvinces();
 }


 private void queryProvinces() {
  showProgressDialog();
  provinceList = weatherDB.getAllProvince();
  if (provinceList.size() > 0) {
   dataList.clear();
   for (Province province : provinceList) {
    dataList.add(province.getProvinceName());
   }
   adapter.notifyDataSetChanged();
   listView.setSelection(0);
   titleText.setText("中国");
   currentLevel = LEVEL_PROVINCE;
   closeProgressDialog();
  } else {
   queryFromServer(null,"province");
  }
 }

 private void queryCities() {
  showProgressDialog();
  cityList = weatherDB.getAllCity(selectedProvince.getProvinceId());
  if (cityList.size() > 0) {
   dataList.clear();
   for (City city : cityList) {
    dataList.add(city.getCityName());
   }
   adapter.notifyDataSetChanged();
   listView.setSelection(0);
   titleText.setText(selectedProvince.getProvinceName());
   currentLevel = LEVEL_CITY;
   closeProgressDialog();
  } else {
   queryFromServer(selectedProvince.getProvinceId(),"city");
  }
 }

 private void queryCounties() {
  showProgressDialog();
  countyList = weatherDB.getAllCountry(selectedCity.getCityId());
  if (countyList.size() > 0) {
   dataList.clear();
   for (County county : countyList) {
    dataList.add(county.getCountyName());
   }
   adapter.notifyDataSetChanged();
   listView.setSelection(0);
   titleText.setText(selectedCity.getCityName());
   currentLevel = LEVEL_COUNTY;
   closeProgressDialog();
  } else {
   queryFromServer(selectedCity.getCityId(),"county");
  }
 }

 private void queryFromServer(final String code,final String type) {
  String address;
  // code不为空
  if (!TextUtils.isEmpty(code)) {
   address = "http://www.weather.com.cn/data/list3/city" + code + ".xml";
  } else {
   address = "http://www.weather.com.cn/data/list3/city.xml";
  }
  HttpUtil.sendHttpRequest(address,new HttpCallbackListener() {
   @Override
   public void onFinish(String response) {
    boolean result = false;
    if ("province".equals(type)) {
     result = Utility.saveProvincesResponse(weatherDB,response);
    } else if ("city".equals(type)) {
     result = Utility.saveCitiesResponse(weatherDB,response,selectedProvince.getProvinceId());
    } else if ("county".equals(type)) {
     result = Utility.saveCountiesResponse(weatherDB,selectedCity.getCityId());
    }
    if (result) {
     runOnUiThread(new Runnable() {
      @Override
      public void run() {
       if ("province".equals(type)) {
        queryProvinces();
       } else if ("city".equals(type)) {
        queryCities();
       } else if ("county".equals(type)) {
        queryCounties();
       }
      }
     });
    }
   }

   @Override
   public void onError(Exception e) {
    runOnUiThread(new Runnable() {
     @Override
     public void run() {
      Toast.makeText(ChooseAreaActivity.this,"加载失败",Toast.LENGTH_SHORT).show();
     }
    });
   }
  });
  closeProgressDialog();
 }

 private void showProgressDialog() {
  if (progressDialog == null) {
   progressDialog = new ProgressDialog(this);
   progressDialog.setMessage("正在加载……");
   progressDialog.setCanceledOnTouchOutside(false);
  }
  progressDialog.show();
 }

 private void closeProgressDialog() {
  if (progressDialog != null) {
   progressDialog.dismiss();
  }
 }

 @Override
 public void onBackpressed() {
  if (currentLevel == LEVEL_COUNTY) {
   queryCities();
  } else if (currentLevel == LEVEL_CITY) {
   queryProvinces();
  } else {
   if (isFromWeatherActivity) {
    Intent intent = new Intent(this,WeatherActivity.class);
    startActivity(intent);
   }
   finish();
  }
 }
}

WeatherActivity的布局相对复杂些,包含了许多个TextView,我也只是想着简单就好,就简单地把数据用文本呈现出来

// 城市切换按钮
 private Button citySwitch;
 // 刷新数据按钮
 private Button weatherRefresh;
 // 城市名
 private TextView cityName;
 // 白天夜晚天气描叙
 private TextView DayNightWeather;
 // 温度
 private TextView temp;
 // 日出时间
 private TextView sunriseTime;
 // 日落时间
 private TextView sunsetTime;
 // 风力
 private TextView wind;
 // 降水概率
 private TextView pop;
 // 发布时间
 private TextView updateTime;
 // 今日天气预测列表
 private ListView listview;

 public static List<HourlyWeather> weatherList = new ArrayList<>();

 private SharedPreferences sharedPreferences;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.weather);
  if (getSupportActionBar() != null) {
   getSupportActionBar().hide();
  }
  init();
 }

 private void init() {
  citySwitch = (Button) findViewById(R.id.citySwitch);
  weatherRefresh = (Button) findViewById(R.id.weatherRefresh);
  citySwitch.setonClickListener(this);
  weatherRefresh.setonClickListener(this);
  cityName = (TextView) findViewById(R.id.cityName);
  DayNightWeather = (TextView) findViewById(R.id.DayNightWeather);
  temp = (TextView) findViewById(R.id.temp);
  sunriseTime = (TextView) findViewById(R.id.sunriseTime);
  sunsetTime = (TextView) findViewById(R.id.sunsetTime);
  wind = (TextView) findViewById(R.id.wind);
  pop = (TextView) findViewById(R.id.pop);
  updateTime = (TextView) findViewById(R.id.updateTime);
  listview = (ListView) findViewById(R.id.hourlyForecast);
  sharedPreferences = getSharedPreferences("Weather",Context.MODE_PRIVATE);

  String countyName = getIntent().getStringExtra("CountyName");
  // 当countyName不为空
  if (!TextUtils.isEmpty(countyName)) {
   SharedPreferences.Editor editor = sharedPreferences.edit();
   editor.putString("CountyName",countyName);
   editor.commit();
  } else {
   countyName = sharedPreferences.getString("CountyName","");
  }
  weatherRefresh.setText("同步中……");
  queryFromServer(countyName);
 }

 @Override
 public void onClick(View view) {
  switch (view.getId()) {
   case R.id.citySwitch:
    Intent intent = new Intent(this,ChooseAreaActivity.class);
    intent.putExtra("ChooseArea",true);
    startActivity(intent);
    finish();
    break;
   case R.id.weatherRefresh:
    weatherRefresh.setText("同步中……");
    String countyName = sharedPreferences.getString("CountyName","");
    if (!TextUtils.isEmpty(countyName)) {
     queryFromServer(countyName);
    }
    break;
  }
 }

 private void queryFromServer(final String countyName) {
  try {
   String url = "http://apis.baidu.com/heweather/weather/free?city=";
   String name = new String(countyName.getBytes("UTF-8"),"iso-8859-1");
   HttpUtil.sendHttpRequest(url + name,new HttpCallbackListener() {
    @Override
    public void onFinish(String response) {
     Utility.handleWeatherResponse(WeatherActivity.this,response);
     runOnUiThread(new Runnable() {
      @Override
      public void run() {
       showWeather();
      }
     });
    }

    @Override
    public void onError(Exception e) {
     runOnUiThread(new Runnable() {
      @Override
      public void run() {
       Toast.makeText(WeatherActivity.this,"同步失败",Toast.LENGTH_LONG).show();
       weatherRefresh.setText("更新数据");
      }
     });
    }
   });
  } catch (Exception e) {
   e.printstacktrace();
  }

 }

 private void showWeather() {
  cityName.setText(sharedPreferences.getString("cityName","未知"));
  sunriseTime.setText("日出:" + sharedPreferences.getString("sunriseTime","未知"));
  sunsetTime.setText("日落:" + sharedPreferences.getString("sunsetTime","未知"));
  DayNightWeather.setText("日:" + sharedPreferences.getString("dayWeather","未知") + " 夜:" + sharedPreferences.getString("nightWeather","未知"));
  temp.setText("温度:" + sharedPreferences.getString("temp","未知"));
  wind.setText("风力:" + sharedPreferences.getString("wind","未知"));
  pop.setText("降水概率:" + sharedPreferences.getString("pop","未知"));
  updateTime.setText("发布时间:" + sharedPreferences.getString("updateTime","未知"));
  WeatherAdapter adapter = new WeatherAdapter(this,R.layout.hourly_weather,weatherList);
  listview.setAdapter(adapter);
  Toast.makeText(WeatherActivity.this,"已经是最新数据了",Toast.LENGTH_SHORT).show();
  weatherRefresh.setText("更新数据");
 }

}

八、说明
很奇怪的是,这个小app在我的4.4版本的小米手机上运行无误,可在5.1系统的模拟器和华为手机上却提示无法获取到数据,返回的JSON数据提示说城市未知,查看了很久也没搞明白,只能作罢~~

代码下载地址:Android简易版天气预报app的实现(改进版)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

android天气预报app源码(包运行)

android天气预报app源码(包运行)

本实例讲解了一个天气预报的android项目, 项目只有前台,没有后台, 后台获取的天气预报数据取自网络上的一个服务, 本项目可以显示全国所有地理位置信息,选择省份后,可以选择相对应的市, 然后选择市下面的县和县级市, 最后显示县及市的天气状况  【点击下载实例】

 

项目对应的实例代码可以通过右侧【下载实例】按钮获取

开发工具: Android Studio 2.2.2

 

【项目包含内容】(见下图):   

【CoolWeather_New】          项目源代码

blob.png

 

【项目配置】

1. 将项目导入到 Android Studio 2.2.2

2.build.gradle

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

android {

 

    compileSdkVersion 25

    buildToolsVersion ''25.0.2''

 

    defaultConfig {

        applicationId "com.coolweather.android"

        minSdkVersion 21

        targetSdkVersion 25

        versionCode 1

        versionName "1.1"

    }

    buildTypes {

        release {

            minifyEnabled false

            proguardFiles getDefaultProguardFile(''proguard-android.txt''), ''proguard-rules.pro''

        }

    }

    aaptOptions.cruncherEnabled = false

    aaptOptions.useNewCruncher = false

}

 

dependencies {

    compile fileTree(dir: ''libs'', include: [''*.jar''])

    testCompile ''junit:junit:4.12''

    compile ''com.android.support:appcompat-v7:25.2.0''

    compile ''com.github.bumptech.glide:glide:3.7.0''

    compile ''org.litepal.android:core:1.3.2''

    compile ''com.squareup.okhttp3:okhttp:3.4.1''

    compile ''com.google.code.gson:gson:2.7''

}

3. gradle-wrapper.properties

1

2

3

4

5

distributionBase=GRADLE_USER_HOME

distributionPath=wrapper/dists

zipStoreBase=GRADLE_USER_HOME

zipStorePath=wrapper/dists

distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

 

【项目运行效果】

blob.png  blob.png

今天的关于使用Flutter开发的一款天气预报APPflutter 天气预报的分享已经结束,谢谢您的关注,如果想了解更多关于1个人,100天业余时间,用Flutter开发完一个商业APP、7*24小时天气预报api、Android天气预报app改进版、android天气预报app源码(包运行)的相关知识,请在本站进行查询。

本文标签: