用kotlin方式打开《第一行代码:Android》之开发酷欧天气(2)
参考:《第一行代码:Android》第2版——郭霖
注1:本文为原创,例子可参考郭前辈著作:《第一行代码:Android》第2版
注2:本文不赘述android开发的基本理论,不介绍入门知识,不介绍Android Studio基本安装,开门见山,直接使用kotlin改写郭前辈的《第一行代码:Android》中的部分例子,有机会的话自己做一些新例子出来!
注3:本文尝试用Google新官推语言kotlin改写《第一行代码:Android》中的案例,偶尔涉及java作为对比
注4:开发基于Android Studio 3.0,并且新建项目时勾选“support kotlin”
进入实战——开发酷欧天气(2)
本次博文,我将尝试使用kotlin语言对郭前辈的《第一行代码》中的最后那个实战项目“酷欧天气”进行重写
原书:14.5显示天气信息(p509)
上一章,我们已经把省市县数据“爬”到了app中,接下来我们要做的是“爬”天气预报信息,完成app剩下的功能
注册API
先去注册一下郭神提供的weather api(通过他获得在线的天气信息)
http://console.heweather.com/register
注册完成登陆后取得key,并测试访问一下是否能获得天气的json信息
http://guolin.tech/api/weather?cityid=CN101190402&key=e970db87b1f24fb8a00555c6b361e8d4
(访问形式如上,参考原书:p522,地址中的参数cityid就是在上一章中County数据类里的weather_id)
获得数据:
这就说明已经可以成功获取最近的天气数据了!
不过这个json信息量有点大啊!==|||
数据类
上一章已经“吹”过了kotlin强大的data class(数据类)了,这是一种比java pojo类更加方便精简的类!
每一个你建立的POJO类文件最后都转换为一行代码而已
原作中,作者对gson实体类进行了分析(原书p509),可以使用他分析后创建的实体类(只需要转换成kotlin data class的写法)
不过对于这么复杂的json,我使用了在线json转POJO,将刚刚获得的天气json数据先转换为POJO类(这样使得实体类定义更加完整并且比自己一个个手写要块多了,工具是个好东西!)
json转POJO网址:http://www.bejson.com/json2javapojo/
注意从网站上得到的只是java的POJO类,不是kotlin类(反正我还没有找到json直接转kotlin数据类的工具==|||求推荐)
进入Android Studio 3.0,在项目中新建包:weatherapi->新建datas.kt
为什么要新建一个包?
这个包是专门存放kotlin的天气数据类的,因为我发现郭前辈那个api获得天气json转换后的数据类与之前的我的City这个数据类有冲突(那个json里也有个City),故而将这次天气的数据类放到一个单独的包中,保证不会冲突,另外引入时需要注意,别引入了外面那个City类!
尝试转换
先新建一个City.java,这是一个POJO类文件,将json在线转换好的POJO类代码复制进来
这是那个在线json转换出来的City java POJO类:
package cn.cslg.weatherkotlin.weatherapi;
public class City {private String aqi;private String pm10;private String pm25;private String qlty;public void setAqi(String aqi){this.aqi = aqi;}public String getAqi(){return this.aqi;}public void setPm10(String pm10){this.pm10 = pm10;}public String getPm10(){return this.pm10;}public void setPm25(String pm25){this.pm25 = pm25;}public String getPm25(){return this.pm25;}public void setQlty(String qlty){this.qlty = qlty;}public String getQlty(){return this.qlty;}}
使用IDE可以直接将java转换为kotlin代码,这是kotlin类库自带的功能,我们来转这个java类为kotlin类
点击Android Studio 3.0上面的工具栏上的Code->Convert Java File to Kotlin File(在最后一个)
IDE转换结束后,很遗憾,这不是一个kotlin的数据类,自行修修补补,改成data class吧(求工具完全转换!)
以下是我自行修改后:City的dataclass
data class City(val aqi: String, val pm10: String, val pm25: String, val qlty: String)
个人推荐一种办法:
- 先把那个网站转换的所有的类一起复制到一个java文件中,我知道这样会报错,java只能有一个public class
- 转换为kotlin
- 替换所有public,internal为data
- 替换所有的{}为()
- 删除最后一个属性的逗号
- 所有代码合并成一行
- Code->Reformat Code
最终的datas.kt:
package cn.cslg.weatherkotlin.weatherapidata class City(var aqi: String, var pm10: String, var pm25: String, var qlty: String)
data class Aqi(var city: City)
data class Update(var loc: String, var utc: String)
data class Basic(var city: String, var cnty: String, var id: String, var lat: String, var lon: String, var update: Update)
data class Now(var cond: Cond, var fl: String, var hum: String, var pcpn: String, var pres: String, var tmp: String, var vis: String, var wind: Wind)
data class Air(var brf: String, var txt: String)
data class Comf(var brf: String, var txt: String)
data class Cw(var brf: String, var txt: String)
data class Drsg(var brf: String, var txt: String)
data class Flu(var brf: String, var txt: String)
data class Sport(var brf: String, var txt: String)
data class Trav(var brf: String, var txt: String)
data class Uv(var brf: String, var txt: String)
data class Suggestion(var air: Air, var comf: Comf, var cw: Cw, var drsg: Drsg, var flu: Flu, var sport: Sport, var trav: Trav, var uv: Uv)
data class Astro(var mr: String, var ms: String, var sr: String, var ss: String)
data class Tmp(var max: String, var min: String)
data class Daily_forecast(var astro: Astro, var cond: DailyCond, var date: String, var hum: String, var pcpn: String, var pop: String, var pres: String, var tmp: Tmp, var uv: String, var vis: String, var wind: Wind)
data class Cond(var code: String, var txt: String)
data class DailyCond(var code_d:String,var code_n:String,var txt_d:String,var txt_n:String)
data class Wind(var deg: String, var dir: String, var sc: String, var spd: String)
data class Hourly_forecast(var cond: Cond, var date: String, var hum: String, var pop: String, var pres: String, var tmp: String, var wind: Wind)
data class HeWeather(var aqi: Aqi, var basic: Basic, var daily_forecast: List<Daily_forecast>, var hourly_forecast: List<Hourly_forecast>, var now: Now, var status: String, var suggestion: Suggestion)
data class Weather(var HeWeather:List<HeWeather>)
注意最后一个Weather类,这是我单独添加出来的,因为我注意到API返回的json开头就有一个HeWeathter对象并且对应的值是HeWeather数组,Gson映射的时候是以最外层{}开始转换为一个对象的,这个对象将会是这个Weather,而不是HeWeather!
另外注意到,那个工具网站生成的POJO类中有两个Cond!仔细查看json数据格式,确实有两个Cond,而且不一样!所以我另开了一个DailyCond数据类作为daily_forecast下的cond的实体模型
可以树形查看json格式的网站:http://www.qqe2.com/
至此数据类已经建立好了,后面可以放心的用Gson映射为实体对象了!
显示天气
原书:p520
接下来可以开始书写kt代码了,我将会把原书中的java翻译成为简单kotlin代码
原书中有handleWeatherResponse,针对json进行处理,这个我们不需要,我使用Gson映射为数据类实体
WeatherActivity.kt:
package cn.cslg.weatherkotlinimport android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.*
import cn.cslg.weatherkotlin.weatherapi.*
import com.google.gson.Gson
import org.jetbrains.anko.custom.async
import org.jetbrains.anko.find
import org.jetbrains.anko.uiThread
import java.net.URLclass WeatherActivity : AppCompatActivity() {private var weatherLayout: ScrollView? = nullprivate var titleCity: TextView? = nullprivate var titleUpdateTime: TextView? = nullprivate var degreeText: TextView? = nullprivate var weatherInfoText: TextView? = nullprivate var forecastLayout: LinearLayout? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_weather)weatherLayout = find<ScrollView>(R.id.weather_layout)titleCity = find<TextView>(R.id.title_city)titleUpdateTime = find<TextView>(R.id.title_update_time)degreeText = find<TextView>(R.id.degree_text)weatherInfoText = find<TextView>(R.id.weather_info_text)forecastLayout = find<LinearLayout>(R.id.forecast_layout)val weatherId = intent.getStringExtra("weather_id");weatherLayout!!.visibility = View.INVISIBLErequestWeather(weatherId)}//从服务器加载天气信息private fun requestWeather(wid:String){val url="http://guolin.tech/api/weather?cityid="+wid+"&key=e970db87b1f24fb8a00555c6b361e8d4"async {val s = URL(url).readText()uiThread {val weather = Gson().fromJson(s,Weather::class.java)showWeatherInfo(weather.HeWeather[0])}}}//显示出天气信息private fun showWeatherInfo(w: HeWeather){titleCity!!.text=w.basic.citytitleUpdateTime!!.text= w.basic.update.locdegreeText!!.text=w.now.tmp+" ℃"weatherInfoText!!.text=w.now.cond.txt+" "+w.now.wind.dir+" "+w.now.wind.sc+"级"weatherLayout!!.visibility=View.VISIBLEforecastLayout!!.removeAllViews()for( d in w.daily_forecast){val v = LayoutInflater.from(this).inflate(R.layout.forecast_item,forecastLayout,false)val dateText = v.find<TextView>(R.id.date_text)val infoText = v.find<TextView>(R.id.info_text)val maxText = v.find<TextView>(R.id.max_text)val minText = v.find<TextView>(R.id.min_text)dateText.text = d.datemaxText.text = d.tmp.maxminText.text = d.tmp.minif(d.cond.code_d == d.cond.code_n){infoText.text = d.cond.txt_d}else{infoText.text = d.cond.txt_d+"->"+d.cond.txt_n}forecastLayout!!.addView(v)}}
}
一点分析
overwrite的onCreate方法不多解释,主要是获取R中的布局转成控件,隐藏了尚未加载的地方,还从intent中获得了一个参数,用于选择查询的城市
requestWeather方法使用了async请求API的数据,传入城市的weather_id
注意到,这里使用Gson转换的时候并没有上一章的TypeToken,因为这一次获得json数据最外层不是数组,也就不需要List映射,所以直接传入一个对象的类,kotlin使用Object::class.java即可!
showWeatherInfo方法将获取的数据初始化到界面上,其中用到了kotlin的for( in )遍历结构,非常简单!
补充ChooseAreaFragment
ChooseAreaFragment.kt:
class ChooseAreaFragment : Fragment() {
......
override fun onActivityCreated(savedInstanceState: Bundle?) {super.onActivityCreated(savedInstanceState)//列表点击监听事件listView!!.setOnItemClickListener {LEVEL_COUNTY -> {selectedCounty = countyList[position]val intent = Intent(activity,WeatherActivity::class.java)intent.putExtra("weather_id", selectedCounty!!.weather_id)startActivity(intent)activity.finish()
.......
}
往里面添加了:点击县跳转到WeatherActivity的Intent
补充布局
activity_weather.xml:
<?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="@color/colorPrimary"><ScrollViewandroid:id="@+id/weather_layout"android:scrollbars="none"android:overScrollMode="never"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"><include layout="@layout/title"/><include layout="@layout/now"/><include layout="@layout/forecast"/></LinearLayout></ScrollView></FrameLayout>
forecast.xml:
<?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="wrap_content"android:layout_margin="15dp"android:background="#8000"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="15dp"android:layout_marginRight="15dp"android:paddingTop="10sp"android:paddingBottom="10sp"android:text="三天预报"android:textColor="#fff"android:textSize="20sp"/><LinearLayoutandroid:id="@+id/forecast_layout"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"></LinearLayout></LinearLayout>
forecast_item.xml:
<?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="wrap_content"android:layout_margin="15dp"android:orientation="horizontal"><TextViewandroid:id="@+id/date_text"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="2"android:layout_gravity="center_vertical"android:textColor="#fff"/><TextViewandroid:id="@+id/info_text"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:layout_gravity="center_vertical"android:gravity="center"android:textColor="#fff"/><TextViewandroid:id="@+id/max_text"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_weight="1"android:gravity="center"android:textColor="#fff"/><TextViewandroid:id="@+id/min_text"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_weight="1"android:gravity="right"android:textColor="#fff"/></LinearLayout>
now.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_margin="15dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/degree_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="end"android:textColor="#fff"android:textSize="60sp"/><TextViewandroid:id="@+id/weather_info_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="end"android:textColor="#fff"android:textSize="20sp"/></LinearLayout>
title.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"><TextViewandroid:id="@+id/title_city"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textColor="#fff"android:textSize="20sp"/><TextViewandroid:id="@+id/title_update_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="10sp"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:textColor="#fff"android:textSize="16sp"/></RelativeLayout>
效果
结尾
app的大体功能和样式已经实现了,接下来需要对他做更多的美化和完善!
版权
转载请注明出自:http://www.cnblogs.com/devilyouwei/p/6889804.html
转载于:https://www.cnblogs.com/devilyouwei/p/6889804.html
用kotlin方式打开《第一行代码:Android》之开发酷欧天气(2)相关推荐
- 第一行代码 开发酷欧天气DataSupport,ProgressDialog,加载失败,PreferenceManager.getDefaultSharedPreferences()方法
第一行代码学到开发酷欧天气时,在继承DataSupport类时发现DataSupport过时,于是发现LitePalSupport可以替代DataSupport.后面会用到一个DataSupport. ...
- 用kotlin方式打开《第一行代码:Android》之开发酷欧天气(1)
参考:<第一行代码:Android>第2版--郭霖 注1:本文为原创,例子可参考郭前辈著作:<第一行代码:Android>第2版,转载请注明出处! 注2:本文不赘述androi ...
- 第一行代码android的读后感,《第一行代码Android》读书笔记
自学android一段时间了,一开始是看看视频,跟着打打代码,后来也有跟着团队一起做项目,一直都很零散,并没有真正系统的学习过,虽然能跟得上项目,但总觉得基础不牢固扎实,之前有读过郭霖老师博客里的几篇 ...
- 第一行代码Android第二章读书笔记
第一行代码Android第二章读书笔记 Activity 1.1 手动创建活动 1.2 Toast和Menu/销毁活动 Intent 2.1 显示/隐式 2.2 传递/返回数据 活动的生命周期 3.1 ...
- 《第一行代码Android》读书笔记
自学android一段时间了,一开始是看看视频,跟着打打代码,后来也有跟着团队一起做项目,一直都很零散,并没有真正系统的学习过,虽然能跟得上项目,但总觉得基础不牢固扎实,之前有读过郭霖老师博客里的几篇 ...
- 第一行代码 Android读书笔记(二)
第一行代码 Android读书笔记 第三章 软件也要拼脸蛋-UI开发的点点滴滴 常用控件的使用方法 详解4种基本布局 自定义控件 最常用和最难用的控件-ListView 更加强大的滚动控件-Recyc ...
- 晒订单赢图灵图书,《第一行代码——Android》福利活动劲爆来袭!
(已结束) 我的著作<第一行代码--Android>已经预售几天了,这段时间也有不少朋友早早地就订购了这本书,感谢大家对我一如既往的支持,在离发货还有十几天的时候就预订了这本书. 为了特别 ...
- 第一行代码 Android (郭霖 著)
https://github.com/guolindev/booksource 第1章 开始启程----你的第一行Android代码 (已看) 第2章 先从看得到的入手----探究活动 (已看) 第3 ...
- 《第一行代码 Android 第2版》下载
<第一行代码 Android 第2版> https://pan.baidu.com/s/1B718h7h3601iEe8gIN9oAQ
最新文章
- Code-First Migrations随Entity Framework 4.3一同发布
- Pod详解-端口设置
- python的linux电脑上图标不见了怎么办_电脑桌面及桌面图标消失不见怎么找回?
- Asp.Net Core SignalR 与微信小程序交互笔记
- java 二维高斯_Java Random nextGaussian()用法及代码示例
- scrapy 工作流程
- java单例模式实例_Java设计模式之单例模式 通俗易懂 超详细 【内含案例】
- c语言洗牌发牌结构体,C语言程序设计课程设计多功能计算器、洗牌发牌、学生文件处理、链表处理.doc...
- python matplotlib 绘制三次函数图像
- Oracle的方案(Schema)和用户(User)的区别
- QC新旧七图汇总连载10——树状图
- centos linux 查看ip,centos如何查看ip
- Git-远程仓库【转】
- 鲲鹏服务器gpu型号,GPU服务器服务
- mac上Latex的安装及使用教程
- 《计算机绘图》期末试卷d,计算机绘图试卷
- 神奇的手指——可以取代”切水果“的清屏小软件
- Thinkpad W530 笔记本关机后耗电问题
- 摄像头捕获视频流软件AMCAP使用教程(视频采集捕获处理媒体制作微型软件)
- 网络没问题,MSN登录不了解决方法