当前位置: 首页 > news >正文

网站建设过程小结共享网站的建设与规划

网站建设过程小结,共享网站的建设与规划,个人网站 flash,网站服务器的安全性首先是实现用户账号的权限设置对变量延迟初始化 Kotlin 语言的许多特性,包括变量不可变,变量不可为空,等等。这些特性 都是为了尽可能地保证程序安全而设计的,但是有些时候这些特性也会在编码时给我们带来不 少的麻烦。 比如,如果你的类中存在很多…

对变量延迟初始化

Kotlin 语言的许多特性,包括变量不可变,变量不可为空,等等。这些特性
都是为了尽可能地保证程序安全而设计的,但是有些时候这些特性也会在编码时给我们带来不
少的麻烦。

比如,如果你的类中存在很多全局变量实例,为了保证它们能够满足Kotlin 的空指针检查语法标
准,你不得不做许多的非空判断保护才行,即使你非常确定它们不会为空。

下面我们通过一个具体的例子来看一下吧,就使用刚刚的UIBestP ractice 项目来作为例子。如
果你仔细观察MainActivity 中的代码,会发现这里适配器的写法略微有点特殊:

class MainActivity : AppCompatActivity(), View.OnClickListener {private var adapter: MsgAdapter? = null override fun onCreate(savedInstanceState: Bundle?) { ... adapter = MsgAdapter(msgList) ... } override fun onClick(v: View?) { ... adapter?.notifyItemInserted(msgList.size - 1) ... } 
}

这里我们将adapter设置为了全局变量,但是它的初始化工作是在onCreate()方法中进行
的,因此不得不先将adapter赋值为null,同时把它的类型声明成MsgAdapter?。

虽然我们会在onCreate()方法中对adapter进行初始化,同时能确保onClick()方法必然在
onCreate()方法之后才会调用,但是我们在onClick()方法中调用adapter的任何方法时仍
然要进行判空处理才行,否则编译肯定无法通过。

而当你的代码中有了越来越多的全局变量实例时,这个问题就会变得越来越明显,到时候你可
能必须编写大量额外的判空处理代码,只是为了满足Kotlin 编译器的要求。

幸运的是,这个问题其实是有解决办法的,而且非常简单,那就是对全局变量进行延迟初始
化。

延迟初始化使用的是lateinit关键字,它可以告诉Kotlin 编译器,我会在晚些时候对这个变量
进行初始化,这样就不用在一开始的时候将它赋值为null了。

接下来我们就使用延迟初始化的方式对上述代码进行优化,如下所示:

class MainActivity : AppCompatActivity(), View.OnClickListener {private lateinit var adapter: MsgAdapter override fun onCreate(savedInstanceState: Bundle?) { ... adapter = MsgAdapter(msgList) ... } override fun onClick(v: View?) { ... adapter.notifyItemInserted(msgList.size - 1) ... } 
}

可以看到,我们在adapter变量的前面加上了lateinit关键字,这样就不用在一开始的时候
将它赋值为null,同时类型声明也就可以改成MsgAdapter了。由于MsgAdapter是不可为空
的类型,所以我们在onClick()方法中也就不再需要进行判空处理,直接调用adapter的任何
方法就可以了。

当然,使用lateinit关键字也不是没有任何风险,如果我们在adapter变量还没有初始化的
情况下就直接使用它,那么程序就一定会崩溃,并且抛出一个
UninitializedP ropertyA ccessEx ception 异常,如图

在这里插入图片描述
当对一个全局变量使用了lateinit关键字时,请一定要确保它在被任何地方调用之前
已经完成了初始化工作,否则Kotlin 将无法保证程序的安全性。

另外,我们还可以通过代码来判断一个全局变量是否已经完成了初始化,这样在某些时候能够
有效地避免重复对某一个变量进行初始化操作,示例代码如下:

class MainActivity : AppCompatActivity(), View.OnClickListener {private lateinit var adapter: MsgAdapter override fun onCreate(savedInstanceState: Bundle?) { ... if (!::adapter.isInitialized) { adapter = MsgAdapter(msgList) } ... }

具体语法就是这样,::adapter.isInitialized可用于判断adapter变量是否已经初始
化。虽然语法看上去有点奇怪,但这是固定的写法。然后我们再对结果进行取反,如果还没有
初始化,那么就立即对adapter变量进行初始化,否则什么都不用做。

使用密封类优化代码

由于密封类通常可以结合RecyclerV iew 适配器中的ViewHolder 一起使用,因此我们就正好借
这个机会在本节学习一下它的用法。当然,密封类的使用场景远不止于此,它可以在很多时候
帮助你写出更加规范和安全的代码,所以非常值得一学。

首先来了解一下密封类具体的作用,这里我们来看一个简单的例子。新建一个Kotlin 文件,文件
名就叫Result.kt 好了,然后在这个文件中编写如下代码:

interface Result 
class Success(val msg: String) : Result 
class Failure(val error: Exception) : Result

这里定义了一个Result接口,用于表示某个操作的执行结果,接口中不用编写任何内容。然后
定义了两个类去实现Result接口:一个Success类用于表示成功时的结果,一个Failure类
用于表示失败时的结果,这样就把准备工作做好了。

接下来再定义一个getResultMsg()方法,用于获取最终执行结果的信息,代码如下所示:

fun getResultMsg(result: Result) = when (result) { is Success -> result.msg is Failure -> result.error.message else -> throw IllegalArgumentException() 
}

getResultMsg()方法中接收一个Result参数。我们通过when语句来判断:如果Result属
于Success,那么就返回成功的消息;如果Result属于Failure,那么就返回错误信息。到
目前为止,代码都是没有问题的,但比较让人讨厌的是,接下来我们不得不再编写一个else条
件,否则Kotlin 编译器会认为这里缺少条件分支,代码将无法编译通过。但实际上Result的执
行结果只可能是Success或者Failure,这个else条件是永远走不到的,所以我们在这里直接
抛出了一个异常,只是为了满足Kotlin 编译器的语法检查而已。

另外,编写else条件还有一个潜在的风险。如果我们现在新增了一个Unknown类并实现
Result接口,用于表示未知的执行结果,但是忘记在getResultMsg()方法中添加相应的条
件分支,编译器在这种情况下是不会提醒我们的,而是会在运行的时候进入else条件里面,从
而抛出异常并导致程序崩溃。

当然,这种为了满足编译器的要求而编写无用条件分支的情况不仅在Kotlin 当中存在,在Java 或
者是其他编程语言当中也普遍存在。

不过好消息是,Kotlin 的密封类可以很好地解决这个问题,下面我们就来学习一下。

密封类的关键字是sealed class,它的用法同样非常简单,我们可以轻松地将Result接口改
造成密封类的写法:

sealed class Result 
class Success(val msg: String) : Result() 
class Failure(val error: Exception) : Result()

可以看到,代码并没有什么太大的变化,只是将interface关键字改成了sealed class。另
外,由于密封类是一个可继承的类,因此在继承它的时候需要在后面加上一对括号

那么改成密封类之后有什么好处呢?你会发现现在getResultMsg()方法中的else条件已经不
再需要了,如下所示:

fun getResultMsg(result: Result) = when (result) { is Success -> result.msg is Failure -> "Error is ${result.error.message}" 
}

为什么这里去掉了else条件仍然能编译通过呢?这是因为当在when语句中传入一个密封类变量
作为条件时,Kotlin 编译器会自动检查该密封类有哪些子类,并强制要求你将每一个子类所对应
的条件全部处理。这样就可以保证,即使没有编写else条件,也不可能会出现漏写条件分支的
情况。而如果我们现在新增一个Unknown类,并也让它继承自Result,此时
getResultMsg()方法就一定会报错,必须增加一个Unknown的条件分支才能让代码编译通
过。

这就是密封类主要的作用和使用方法了。另外再多说一句,密封类及其所有子类只能定义在同
一个文件的顶层位置,不能嵌套在其他类中,这是被密封类底层的实现机制所限制的。

了解了这么多关于密封类的知识,接下来我们看一下它该如何结合MsgAdapter中的
ViewHolder 一起使用,并顺便优化一下MsgAdapter中的代码。

观看MsgAdapter现在的代码,你会发现onBindViewHolder()方法中就存在一个没有实际作
用的else条件,只是抛出了一个异常而已。对于这部分代码,我们就可以借助密封类的特性来
进行优化。首先删除MsgAdapter 中的Lef tViewHolder 和RightViewHolder ,然后新建一个
MsgViewHolder .kt 文件,在其中加入如下代码:

sealed class MsgViewHolder(view: View) : RecyclerView.ViewHolder(view)class LeftViewHolder(view: View) : MsgViewHolder(view) { val leftMsg: TextView = view.findViewById(R.id.leftMsg) 
} class RightViewHolder(view: View) : MsgViewHolder(view) { val rightMsg: TextView = view.findViewById(R.id.rightMsg) 
}

这里我们定义了一个密封类MsgViewHolder,并让它继承自RecyclerView.ViewHolder,
然后让LeftViewHolder和RightViewHolder继承自MsgViewHolder。这样就相当于密封
类MsgViewHolder只有两个已知子类,因此在when语句中只要处理这两种情况的条件分支即
可。

现在修改MsgAdapter中的代码,如下所示:

class MsgAdapter(val msgList: List<Msg>) : RecyclerView.Adapter<MsgViewHolder>() {... override fun onBindViewHolder(holder: MsgViewHolder, position: Int) {val msg = msgList[position] when (holder) { is LeftViewHolder -> holder.leftMsg.text = msg.contentis RightViewHolder -> holder.rightMsg.text = msg.content} } ... 
}

这里我们将RecyclerView.Adapter的泛型指定成刚刚定义的密封类MsgViewHolder,这样
onBindViewHolder()方法传入的参数就变成了MsgViewHolder。然后我们只要在when语
句当中处理LeftViewHolder和RightViewHolder这两种情况就可以了,那个讨厌的else终
于不再需要了,这种RecyclerV iew 适配器的写法更加规范也更加推荐。

http://www.dtcms.com/a/522869.html

相关文章:

  • 网站买空间网站开发与系统开发
  • 福州网站建设团队c 网站开发模式
  • 泌阳县网站建设江苏工程信息网
  • 江苏常州网站建设福州有名的公司网站设计
  • 货运代理公司wordpress建站seo好做吗
  • 做房产网站有哪些网站首页图
  • .net 接单网站深圳专业做网站技术
  • 钓鱼网站免费空间网站开发维护运维
  • 威海 网站开发asp美食网站源码
  • 苏州做网站哪家专业企业推广哪个平台好
  • 明珠信息港网站建设专家旅游网站策划案
  • 蓬莱有做网站的吗修改wordpress登录背景图
  • 邢台做企业网站万能证件p图
  • 网站信息备案管理系统企业信息网查询系统
  • 企业网站管理系统用户裁剪图网站
  • 一个网站建设需要多少人力江苏九天建设有限公司网站
  • 优秀的网站设计图片手机app免费制作
  • 网页视频制作杭州百度人工优化
  • 网站建设公司税负率平面设计多久能学会
  • 宝安网站制作培训wordpress设置404
  • 东营网站app建设周杰伦做的广告网站
  • 做财经比较好的网站有哪些网站建设找谁
  • 档案网站开发小程序wordpress
  • 珠海做网站报价开发一块地需要多少钱
  • 拱墅区哪里有网站建设北京网站建设公司哪些好
  • 建设企业网站费用滑县网站建设公司
  • 网站开发前端课程品牌网站的愿望清单怎么做
  • 网站模板设计开发上海医院网站建设
  • 临汾网站建设价格镇江市住房和城乡建设局网站
  • 网站管理员怎么登陆网站文章伪原创怎么做