博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
极简Kotlin-For-Android(二)
阅读量:6378 次
发布时间:2019-06-23

本文共 8377 字,大约阅读时间需要 27 分钟。

上一篇我们做到了从网络获取数据,并写好了实体类.接着我们需要创建domain层,这一层为app执行任务.

构建domain层

首先需要创建command:

public interface Command
{ fun execute() : T}复制代码

创建DataMapper:

class ForecastDataMapper {    fun convertFromDataModel(forecast: ForecastResult): ForecastList {        return ForecastList(forecast.city.name, forecast.city.country, convertForecastListToDomain(forecast.list))    }    fun convertForecastListToDomain(list: List
) : List
{ return list.map { convertForecastItemToDomain(it) } } private fun convertForecastItemToDomain(forecast: ForecastResult.ForeCast): ModelForecast { return ModelForecast(convertDate(forecast.dt), forecast.weather[0].description, forecast.temp.max.toInt(), forecast.temp.min.toInt())} private fun convertDate(date: Long): String { val df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()) return df.format(date * 1000) } data class ForecastList(val city: String, val country: String,val dailyForecast:List
) data class Forecast(val date: String, val description: String, val high: Int,val low: Int)}复制代码

Tips:

list.map:循环这个集合并返回一个转换后的新list.

准备就绪:

class RequestForecastCommand(val zipCode : String) : Command
{ override fun execute(): ForecastDataMapper.ForecastList { return ForecastDataMapper().convertFromDataModel(Request(zipCode).execute()) }}复制代码

绑定数据,刷新ui:

doAsync {    val result = RequestForecastCommand("94043").execute()    uiThread {        recycler.adapter = ForecastListAdapter(result)    }}复制代码

同时需要修改adapter数据类型:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {        with(items.dailyForecast[position]){            holder.textView.text = "$date -  $description  -  $high/$low"        }    }    override fun getItemCount(): Int {        return items.dailyForecast.size    }复制代码

Tips:

关于with函数:它接收一个对象和一个扩展函数作为它的参数,然后使这个对象扩展这个函数。这表示所有我们在括号中编写的代码都是作为对象(第一个参数)的一个扩展函数,我们可以就像作为this一样使用所有它的public方法和属性。当我们针对同一个对象做很多操作的时候这个非常有利于简化代码。

运行一下项目,可以看到效果如下图:

添加item点击事件

先看下效果图:

我们把对应的item布局修改为图上的样子后,修改ForecastDataMapper:

private fun convertForecastItemToDomain(forecast: ForecastResult.ForeCast): ModelForecast {        return ModelForecast(convertDate(forecast.dt),                forecast.weather[0].description,                forecast.temp.max.toInt(),                forecast.temp.min.toInt(),                generateIconUrl(forecast.weather[0].icon))}    private fun convertDate(date: Long): String {        val df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault())        return df.format(date * 1000)    }    private fun generateIconUrl(iconCode : String) : String{        return "http://openweathermap.org/img/w/$iconCode.png"    }        data class Forecast(val date: String, val description: String, val high: Int,val low: Int,val iconUrl : String)复制代码

修改adapter:

class ForecastListAdapter(val items : ForecastDataMapper.ForecastList,                          val itemCLick : onItemClickListenr) :        RecyclerView.Adapter
(){ override fun onBindViewHolder(holder: ViewHolder, position: Int) { with(items.dailyForecast[position]){ holder.bindForecast(items.dailyForecast[position]) } } override fun getItemCount(): Int { return items.dailyForecast.size } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_forecast,parent,false) return ViewHolder(view,itemCLick) } class ViewHolder(view : View , val onItemClick : onItemClickListenr) : RecyclerView.ViewHolder(view){ private val iconView : ImageView private val dateView : TextView private val descriptionView : TextView private val maxTemperatureView : TextView private val minTemperatureView : TextView init { iconView = view.find(R.id.icon) dateView = view.find(R.id.date) descriptionView = view.find(R.id.description) maxTemperatureView = view.find(R.id.maxTemperature) minTemperatureView = view.find(R.id.minTemperature) } fun bindForecast(forecast : ForecastDataMapper.Forecast ){ with(forecast){ Glide.with(itemView.context).load(iconUrl).into(iconView) dateView.text = date descriptionView.text = description maxTemperatureView.text = high.toString() minTemperatureView.text = low.toString() itemView.setOnClickListener(){ onItemClick(forecast) } } } } public interface onItemClickListenr{ operator fun invoke(forecast : ForecastDataMapper.Forecast) }}复制代码

之后绑定数据:

doAsync {            val execute = RequestForecastCommand("94043").execute()            uiThread {                recycler.adapter = ForecastListAdapter(execute, object :ForecastListAdapter.onItemClickListenr{                    override fun invoke(forecast: ForecastDataMapper.Forecast) {                        toast("点击了item")                    }                })            }        }复制代码

有时候我们可能会遇到一个异常:

[Kotlin]kotlin.NotImplementedError: An operation is not implemented: not implemented

原因 : Android里面加个TODO并不会影响程序运行,可是在Kotlin里面就不一样啦,如果你在某个函数的第一行添加TODO的话,那么很抱歉,它不会跳过,然后运行下一行代码
解决方案: 我们只需要把TODO("not implemented") 这句话去掉就可以啦!

简化setOnCLickListener kotlin版的点击事件:

view.setOnClickListener(object : View.OnClickListener{            override fun onClick(v: View?) {                toast("click")            }        })复制代码

或者

view.setOnClickListener {    toast("click")}复制代码

Kotlin Android Extensions

这个插件自动创建了很多的属性来让我们直接访问XML中的view。这种方式不需要你在开始使用之前明确地从布局中去找到这些views。这些属性的名字就是来自对应view的id,所以我们取id的时候要十分小心.

dependencies {            classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"   }复制代码

使用的时候我们只需要做一件事:在activity或fragment中手动import以kotlinx.android.synthetic开头的语句 + 要绑定的布局名称:

import kotlinx.android.synthetic.main.activity_main.*复制代码

然后删掉你的find(findviewbyid)吧,直接使用xml中的布局id来做操作 简化你在activity和adapter中的代码吧!

Tips: 如果布局中包含includ标签的布局,还需要在activity中再导入include的布局才能使用

委托模式

所谓委托模式 ,就是为其他对象提供一种代理以控制对这个对象的访问,在 Java 开发过程中,是继承模式之外的很好的解决问题的方案。

interface Base {    fun print()}class A(val a: Int) : Base {    override fun print() {        Log.d("wxl", "a=" + a)    }}class B (val base: Base):Base by base复制代码

调用:

val a = A(1)Log.d("wxl", "a=" + B(a).print())复制代码

集合和函数操作符

关于函数式编程:

很不错的一点是我们不用去解释我们怎么去做,而是直接说我想做什么。比如,如果我想去过滤一个list,不用去创建一个list,遍历这个list的每一项,然后如果满足一定的条件则放到一个新的集合中,而是直接食用filer函数并指明我想用的过滤器。用这种方式,我们可以节省大量的代码。

Kotlin提供的一些本地接口:

  • Iterable:父类。所有我们可以遍历一系列的都是实现这个接口.
  • MutableIterable:一个支持遍历的同时可以执行删除的Iterables.
  • Collection:这个类相是一个范性集合。我们通过函数访问可以返回集合的size、是否为空、是否包含一个或者一些item。这个集合的所有方法提供查询,因为connections是不可修改的.
  • MutableCollection:一个支持增加和删除item的Collection。它提供了额外的函数,比如add、remove、clear等等.
  • List:可能是最流行的集合类型。它是一个范性有序的集合。因为它的有序,我们可以使用get函数通过position来访问.
  • 。MutableList:一个支持增加和删除item的List.
  • Set:一个无序并不支持重复item的集合.
  • MutableSet:一个支持增加和删除item的Se.。
  • Map:一个key-value对的collection。key在map中是唯一的,也就是说不能有两对key是一样的键值对存在于一个map中.
  • MutableMap:一个支持增加和删除item的map.

kotlin中的null安全

指定一个变量是可null是通过在类型的最后增加一个问号:

val a: Int? = null//如果你没有进行检查,是不能编译通过的a.toString()//必须进行判断if(a!=null){        a.toString()}复制代码

控制流-if表达式

用法和 Java 一样,Kotlin 中一切都是表达式,一切都返回一个值。

val l = 4val m = 5  // 作为表达式(替换java三元操作符)val n = if (l > m) l else m复制代码

When 表达式 When 取代 Java switch 操作符。

val o = 3when (o) {    1 -> print("o == 1")    2 -> print("o == 2")    else -> {        print("o == 3")    }}复制代码

还可以检测参数类型:

when(view) {    is TextView -> view.setText("I'm a TextView")    is EditText -> toast("EditText value: ${view.getText()}")    is ViewGroup -> toast("Number of children: ${view.getChildCount()} ")        else ->         view.visibility = View.GONE}复制代码

For 循环

for (item in collection) {    print(item)}复制代码

需要使用index:

for (i in list.indices){    print(list[i])}复制代码

泛型

泛型编程包括,在不指定代码中使用到的确切类型的情况下来编写算法。用这种方式,我们可以创建函数或者类型,唯一的区别只是它们使用的类型不同,提高代码的可重用性。

创建一个指定泛型类:

classTypedClass
(parameter: T) { val value: T = parameter}复制代码

这个类现在可以使用任何的类型初始化,并且参数也会使用定义的类型(kotlin编译器可以判断类型,所以尖括号可以省略):

val t1 = TypedClass
("Hello World!")val t2 = TypedClass
(25)复制代码

一首好音乐:

音乐人: 約納斯住宿加早餐旅館
首张收录专辑: The Proven Theory
发行时间: 2011 年
流派: 嘻哈/饒舌

项目已经更新到github:

转载地址:http://kzxqa.baihongyu.com/

你可能感兴趣的文章
高可用haproxy调度后端服务器实现动静分离集群架构
查看>>
Java 进行 RSA 加解密
查看>>
Hbase原理、基本概念、基本架构
查看>>
MQ 对比
查看>>
实战:RHEL6配置dhcp服务器并绑定主机IP
查看>>
RHEL7/centos7 安装XEN
查看>>
百度不收录原因分析——Spider抓取篇
查看>>
ROS记录上网日志到remote syslog服务器
查看>>
Confluence 6 配置校验和识别
查看>>
Ubuntu Server 上安装 Jexus
查看>>
二台inux主机之间scp复制文件
查看>>
Android studio 申请签名,设置签名key位置 查看 sha1
查看>>
浏览器渲染原理及解剖浏览器内部工作原理
查看>>
向大院大所要智慧——江苏创新转型扫描
查看>>
dubbo连接zookeeper注册中心因为断网导致线程无限等待问题【转】
查看>>
Spring Boot项目配置RabbitMQ集群
查看>>
bash 交互与非交互
查看>>
怎么提高自身技术
查看>>
北京游泳馆
查看>>
cacti安装与配置
查看>>