参考:《第一行代码: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)

个人推荐一种办法:

  1. 先把那个网站转换的所有的类一起复制到一个java文件中,我知道这样会报错,java只能有一个public class
  2. 转换为kotlin
  3. 替换所有public,internal为data
  4. 替换所有的{}为()
  5. 删除最后一个属性的逗号
  6. 所有代码合并成一行
  7. 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)相关推荐

  1. 第一行代码 开发酷欧天气DataSupport,ProgressDialog,加载失败,PreferenceManager.getDefaultSharedPreferences()方法

    第一行代码学到开发酷欧天气时,在继承DataSupport类时发现DataSupport过时,于是发现LitePalSupport可以替代DataSupport.后面会用到一个DataSupport. ...

  2. 用kotlin方式打开《第一行代码:Android》之开发酷欧天气(1)

    参考:<第一行代码:Android>第2版--郭霖 注1:本文为原创,例子可参考郭前辈著作:<第一行代码:Android>第2版,转载请注明出处! 注2:本文不赘述androi ...

  3. 第一行代码android的读后感,《第一行代码Android》读书笔记

    自学android一段时间了,一开始是看看视频,跟着打打代码,后来也有跟着团队一起做项目,一直都很零散,并没有真正系统的学习过,虽然能跟得上项目,但总觉得基础不牢固扎实,之前有读过郭霖老师博客里的几篇 ...

  4. 第一行代码Android第二章读书笔记

    第一行代码Android第二章读书笔记 Activity 1.1 手动创建活动 1.2 Toast和Menu/销毁活动 Intent 2.1 显示/隐式 2.2 传递/返回数据 活动的生命周期 3.1 ...

  5. 《第一行代码Android》读书笔记

    自学android一段时间了,一开始是看看视频,跟着打打代码,后来也有跟着团队一起做项目,一直都很零散,并没有真正系统的学习过,虽然能跟得上项目,但总觉得基础不牢固扎实,之前有读过郭霖老师博客里的几篇 ...

  6. 第一行代码 Android读书笔记(二)

    第一行代码 Android读书笔记 第三章 软件也要拼脸蛋-UI开发的点点滴滴 常用控件的使用方法 详解4种基本布局 自定义控件 最常用和最难用的控件-ListView 更加强大的滚动控件-Recyc ...

  7. 晒订单赢图灵图书,《第一行代码——Android》福利活动劲爆来袭!

    (已结束) 我的著作<第一行代码--Android>已经预售几天了,这段时间也有不少朋友早早地就订购了这本书,感谢大家对我一如既往的支持,在离发货还有十几天的时候就预订了这本书. 为了特别 ...

  8. 第一行代码 Android (郭霖 著)

    https://github.com/guolindev/booksource 第1章 开始启程----你的第一行Android代码 (已看) 第2章 先从看得到的入手----探究活动 (已看) 第3 ...

  9. 《第一行代码 Android 第2版》下载

    <第一行代码 Android 第2版> https://pan.baidu.com/s/1B718h7h3601iEe8gIN9oAQ

最新文章

  1. Code-First Migrations随Entity Framework 4.3一同发布
  2. Pod详解-端口设置
  3. python的linux电脑上图标不见了怎么办_电脑桌面及桌面图标消失不见怎么找回?
  4. Asp.Net Core SignalR 与微信小程序交互笔记
  5. java 二维高斯_Java Random nextGaussian()用法及代码示例
  6. scrapy 工作流程
  7. java单例模式实例_Java设计模式之单例模式 通俗易懂 超详细 【内含案例】
  8. c语言洗牌发牌结构体,C语言程序设计课程设计多功能计算器、洗牌发牌、学生文件处理、链表处理.doc...
  9. python matplotlib 绘制三次函数图像
  10. Oracle的方案(Schema)和用户(User)的区别
  11. QC新旧七图汇总连载10——树状图
  12. centos linux 查看ip,centos如何查看ip
  13. Git-远程仓库【转】
  14. 鲲鹏服务器gpu型号,GPU服务器服务
  15. mac上Latex的安装及使用教程
  16. 《计算机绘图》期末试卷d,计算机绘图试卷
  17. 神奇的手指——可以取代”切水果“的清屏小软件
  18. Thinkpad W530 笔记本关机后耗电问题
  19. 摄像头捕获视频流软件AMCAP使用教程(视频采集捕获处理媒体制作微型软件)
  20. 网络没问题,MSN登录不了解决方法

热门文章

  1. 自驾游你会经常自己做饭吗?
  2. 买了基金之后要天天盯着吗?
  3. 一身的债务,信用卡还逾期,我一个女的,怎么办?
  4. 宇宙是什么,有尽头吗,为什么?
  5. 但是的近义词是什么,怎么用但是造句?
  6. 公平的反义词是什么?
  7. 如何找到解决问题的方法?
  8. 实体经济的“数字化”是不可逆转的趋势
  9. 怎么辨别iPhone手机的真伪?
  10. truffle 安装以及基本指令