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

杭州做网站怎么收费多少一些js特效的网站推荐

杭州做网站怎么收费多少,一些js特效的网站推荐,定制规划设计公司,河北省建设厅报名网站先来看一个具体应用:假设我们有一个App,App中有一个退出应用的按钮,点击该按钮后并不是立即退出,而是先弹出一个对话框,询问用户是否确定要退出,用户点了确定再退出,点取消则不退出,…

先来看一个具体应用:假设我们有一个App,App中有一个退出应用的按钮,点击该按钮后并不是立即退出,而是先弹出一个对话框,询问用户是否确定要退出,用户点了确定再退出,点取消则不退出,示例代码如下:

button.setOnClickListener {AlertDialog.Builder(this).setTitle("提示").setMessage("是否要退出应用?").setPositiveButton("确定") { _, _ -> exitApp() }.setNegativeButton("取消", null).show()
}

我们可能经常需要用到对话框,每次都要写很多重复代码,所以就会想要简化一下,比如,首先把链式调用中的 “.” 给去掉,通过使用apply扩展函数,这就是一个带接收者的扩展函数,所以在apply中的接收者this可以省略不写,这样就能不写 “.” 了,如下:

button.setOnClickListener {AlertDialog.Builder(this).apply {setTitle("提示")setMessage("是否要退出应用?")setPositiveButton("确定") { _, _ -> exitApp() }setNegativeButton("取消", null)show()}
}

这里面有一些代码是每次都一模一样的,所以还可以优化,Builder每次都要创建,show()函数每次都要调用,这些可以封装到函数中,如下:

button.setOnClickListener {showDialog(this) { builder ->builder.setTitle("提示").setMessage("是否要退出应用?").setPositiveButton("确定") { _, _ -> exitApp() }.setNegativeButton("取消", null)}
}fun showDialog(context: Context, init: (AlertDialog.Builder) -> Unit) {val builder = AlertDialog.Builder(context)init(builder)builder.show()
}

如上代码所示,我们把Builder的创建和show()方法的调用封装到了方法里面,这样重复的代码就只写一次,不用每次都写了。但是感觉还不是很优雅,每次调用方法都要写 “.”,通过apply可以消除 “.” 的调用,如下:

showDialog(this) { builder ->builder.apply {setTitle("提示")setMessage("是否要退出应用?")setPositiveButton("确定") { _, _ -> exitApp() }setNegativeButton("取消", null)}
}

感觉还是不够优雅,每次都要从builder上调用apply,这也是重复代码,能不能优化成如下这样:

showDialog(this) {setTitle("提示")setMessage("是否要退出应用?")setPositiveButton("确定") { _, _ -> exitApp() }setNegativeButton("取消", null)
}

这就需要用到带接收者的Lambda了,让我们的Lambda接收Builder对象,这样Lambda代码块中默认就有this,这个this对象就是Builder,修改代码如下:

showDialog(this) {setTitle("提示")setMessage("是否要退出应用?")setPositiveButton("确定") { _, _ -> exitApp() }setNegativeButton("取消", null)
}fun showDialog(context: Context, init: AlertDialog.Builder.() -> Unit) val builder = AlertDialog.Builder(context)init(builder)builder.show()
}

OK,这样就完美了,对比showDialog中的参数:

init: (AlertDialog.Builder) -> Unit  // 带参数的Lambda
init: AlertDialog.Builder.() -> Unit // 带接收者的Lambda

从对比上来看,长得差不多,带接收者就是把括号中的参数移到括号前面,并加了一个 “.” ,带 参数 和带 接收者 两种方式能都能实现把Builder的共同代码封装起来,把Builder的不同部分留给调用者设置,但是明显带接收者的Lambda的方式更优雅,带接收者的Lambda还有一点不同,它可像扩展函数那样调用,如下:

fun showDialog(context: Context, init: AlertDialog.Builder.() -> Unit) {val builder = AlertDialog.Builder(context)builder.init()builder.show()
}

如上代码,init是一个Lambda参数的变量名,但是使用时可以像扩展函数一样在接收者Builder的身上直接调用,所以上面代码再结合apply可以简化成一行,如下:

fun showDialog(context: Context, init: AlertDialog.Builder.() -> Unit) {AlertDialog.Builder(context).apply(init).show()
}

啊,这实在是太优雅了,读起来也好理解,对于代码:AlertDialog.Builder(context).apply(init).show(),按顺序理解就行了:创建一个Builder对象,并用init这个LambdaBuilder对象进行初始化,最后调用show进行显示。

总结一下:

  • 无参数的Lambda,调用Lambda时无需传参数,如下:

    val printMessage: () -> Unit = {println("Hello Kotlin")
    }printMessage()
    
  • 带参数的Lambda,调用Lambda时需要传参数,如下:

    val printMessage: (String) -> Unit = { message ->println(message)
    }printMessage("Hello Kotlin")
    

    这里的 message -> 可以省略不写,不写默认参数名为it

  • 带接收者的Lambda,调用Lambda时需要传参数,如下:

    val printMessage: String.() -> Unit = {println(this)
    }
    printMessage("Hello Kotlin")
    

    接收者参数 的区别,我个人感觉功能上是一样的,都是给Lambda使用的一个参数,只不过叫 接收者 的参数有点特别,它在Lambda的代码块中使用this来访问这个参数,而this又是可以省略不写的,基于这个特点,我们不能给带接收者的Lambda起别的参数名,比如下面是错误的,IDE会直接报错:

    val printMessage: String.() -> Unit = { message ->println(message)
    }
    

    如果这样允许的话,那this就不见了,这跟带参数的Lambda就没有区别了,那你为何不直接使用带参数的Lambda呢,所以不允许这样写,带接收者的Lambda就只能用this代表参数,无需多此一举,如果你真的有特殊需求即要用到this,又要同时用到另起一个参数名的话,只能这样:

    val printMessage: String.() -> Unit = {val message = thisprintln(message)println(this)
    }
    

    另外,带接收者的Lambda在调用时可以像扩展函数那样在接收者对象上调用,但是我们知道它实际上就是给Lambda传递了一个this参数,如:

    val printMessage: String.() -> Unit = {val message = thisprintln(message)
    }
    "Hello Kotlin".printMessage() // 等同于:printMessage("Hello Kotlin")
    

现代开发中,显示对话框推荐的做法是使用DialogFragment,但是用了这个感觉变得麻烦了许多,还得先创建一个类继承DialogFragment,如果有多种类型的对话框,那是不是就得创建多个类去继承DialogFragment,以实现多种不同形式?这样做是可以的,但是真的很麻烦,能不能像AlertDialog.Builder那样,一个类就通用,那样多好,学会了带接收者的Lambda后,实现这个功能就太简单了,代码如下:

class MyDialog(private val builder: AlertDialog.Builder) : DialogFragment() {override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {return builder.create()}companion object {fun show(context: Context, fragmentManager: FragmentManager, tag: String, init: AlertDialog.Builder.() -> Unit) {MyDialog(AlertDialog.Builder(context).apply(init)).show(fragmentManager, tag)}fun dismiss(fragmentManager: FragmentManager, tag: String) {(fragmentManager.findFragmentByTag(tag) as? MyDialog)?.dismissAllowingStateLoss()// dismiss()函数在状态保存期间调用会抛异常,比如屏幕旋转时系统会保存界面UI状态,此时调用dismiss()就会抛出异常,// 而调用dismissAllowingStateLoss()则不会抛异常。但是你既然都走到要dismiss的// 地步了,说明不需要对话框了,也不需要系统去恢复了。所以有点搞不懂为什么需要两种取消对话枉的函数}}}

虽然需要声明一个类继承DialogFragment,但是我们只需要声明一次就行,这个类创建对话框时也可以使用AlertDialog.Builder,所以我们通过封装方法把AlertDialog.Builder设置通过带接收者的Lambda交给用户处理即可,使用上也很简单,示例如下:

MyDialog.show(this, supportFragmentManager, "ExitAppTipDialog") {setTitle("提示")setMessage("确定要退出App吗?")setPositiveButton("确定") { dialog, which ->  }setNegativeButton("取消") { dialog, which ->  }
}

这里,对于 “确定” 和 “取消” 按钮也是很常用的,而且不管你是点了确定还是取消,点击之后对话框都会自动取消,所以上面代码中的dialogwhich参数大多数情况下都是用不到的,但是每次都要写也很麻烦,而且函数名setPositiveButtonsetNegativeButton也不好记,常常因为不记得方法名而浪费很多时间去查找方法名,所以我们可以给AlertDialog.Builder增加两个扩展函数来解决这个问题,代码如下:

fun AlertDialog.Builder.setOk(name: String, listener: (() -> Unit)? = null) {setPositiveButton(name) { _, _ -> listener?.invoke() }  
}fun AlertDialog.Builder.setNo(name: String, listener: (() -> Unit)? = null) {setNegativeButton(name) { _, _ -> listener?.invoke() }   
}

当需要显示对话框时代码就简单多了,如下:

MyDialog.show(this, supportFragmentManager, tag) {setTitle("提示")setMessage("确定要退出App吗?")setOk("确定") {  exitApp() }setNo("取消")
}

还能再优化,比如每次要传supportFragmentManager,又长又占空间,它的获取基本上就是从FragmentActivity或者Fragemnt中获取,那就增加重载函数接收这两个类型即可。

还有每次要传tag,早期我们使用AlertDialog的时候也没用过tag啊,所以tag应该可空,当我们没传tag时自动生成一个。示例代码如下:

class MyDialog(private val builder: AlertDialog.Builder) : DialogFragment() {override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {return builder.create()}companion object {private var count = 0fun show(activity: FragmentActivity, tag: String? = null, init: AlertDialog.Builder.() -> Unit) {show(activity, activity.supportFragmentManager, tag, init)}fun show(fragment: Fragment, tag: String? = null, init: AlertDialog.Builder.() -> Unit) {val context = fragment.context ?: returnshow(context, fragment.parentFragmentManager, tag, init)}fun show(context: Context, fragmentManager: FragmentManager, tag: String? = null, init: AlertDialog.Builder.() -> Unit) {val dialogTag = tag ?: "DialogTag_${count++}"MyDialog(AlertDialog.Builder(context).apply(init)).show(fragmentManager, dialogTag)}fun dismiss(fragmentManager: FragmentManager, tag: String) {(fragmentManager.findFragmentByTag(tag) as? MyDialog)?.dismissAllowingStateLoss()}}}fun AlertDialog.Builder.setOk(name: String, listener: (() -> Unit)? = null) {setPositiveButton(name) { _, _ -> listener?.invoke() }
}fun AlertDialog.Builder.setNo(name: String, listener: (() -> Unit)? = null) {setNegativeButton(name) { _, _ -> listener?.invoke() }
}

调用:

MyDialog.show(this) {setTitle("提示")setMessage("确定要退出App吗?")setOk("确定") {  exitApp() }setNo("取消")
}

Ok,事已至此,已经无可挑剔了!

http://www.dtcms.com/wzjs/794684.html

相关文章:

  • 企业网站建设原则做网站需要多少钱知乎
  • 建设类网站有哪些我想自己卖特产怎么做网站
  • 天津河西做网站贵吗成都网站建设 小兵cms
  • 阿里巴巴开通诚信通后网站怎么做网站建设选亿企网络
  • 废品回收网站怎么做网站优化大气金融网站
  • 网站建设模板制作前景如何设置网站关键字
  • 知名高端网站建设企业亚洲影视传媒有限公司
  • 企业内部门户网站建设方案湛江网页设计培训
  • 百度网盘0基础网站开发教程易点科技有限公司
  • 强的网站建设公镇江网页设计师招聘
  • 医疗软件网站建设公司上海做网站站优云一一十六
  • 网站建设全包专业定制珠海市住房和城乡建设部网站
  • 石家庄便宜网站制作国家建筑工程信息平台
  • cloud域名注册网站国家企业信用查询系统
  • 天晴创艺网站建设百度小程序wordpress中常用插件安装
  • 音乐网站用什么语言做手机网站优化怎么做
  • 嘉定php网站开发培训富阳注册公司
  • 福州网站设计哪里好重庆物流最新消息
  • 自己用iis怎么建设网站网络营销的优势与不足
  • 吉林城市建设学校网站wordpress 白屏
  • 网站-网站建设定制一站式服务理念
  • 烟台网站建设首推企汇互联见效付款免认证域名
  • vps怎么上传网站程序四川省工程信息造价网
  • 做英文网站哪个网站比较好wordpress 木马 查
  • 陕西省建设造价协会网站白云区建网站公司
  • 广东加盟网站建设怎么查到代码是哪个网站做的
  • 室内设计网站推荐知乎汕头建站程序
  • 上海专业网站建设精英汕头app制作
  • 如何介绍网站模板久久建筑网官网登录入口
  • 余姚汽车网站建设wordpress本地主机