Kotlin那些让人相见恨晚的小技巧
1.扩展
方法名左边写个类名加个点,就像钻进这个类的源码改了它里面代码一样,左边的类表示哪个类可以调用这个扩展函数。扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响。
fun receiverType.functionName(params){
body
}
- receiverType:表示函数的接收者,也就是函数扩展的对象
- functionName:扩展函数的名称
- params:扩展函数的参数,可以为NULL
防止快速点击
/**
* 防止快速点击
*/
fun View.setSingleClick(clickAction: (view: View) -> Unit) {
val minTime = 1000L
var lastTime = 0L
this.setOnClickListener {
val tmpTime = System.currentTimeMillis()
if (tmpTime - lastTime > minTime) {
lastTime = tmpTime
clickAction.invoke(this)
}
}
}
使用:
binding.ivSetting.setSingleClick {
// 点击后的跳转
}
优雅判空
以前经常写这种代码:
String name = etName.getText().toString();
if (TextUtils.isEmpty(name)) {
ToastTools.showShort("姓名不能为空");
return;
}
String password = ...
if (TextUtils.isEmpty(password)) {
...
return;
}
/**
* EditText优雅判空
*/
fun TextView.getText(message: String): String? {
val text = this.text.toString()
if (TextUtils.isEmpty(text)) {
ToastTools.showShort(message)
return null
}
return text
}
使用:
val name = etName.getText("姓名不能为空") ?: return
单位转换
val Float.dp2px
get() = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
this,
Resources.getSystem().displayMetrics
)
使用:
val padding = 16.0f.dp2px
扩展点击范围
/** * 扩展控件点击范围 * @param leftSize 左侧扩展的大小(像素) * @param topSize 上侧扩展的大小(像素) * @param rightSize 右侧扩展的大小(像素) * @param bottomSize 下侧扩展的大小(像素) */fun View.expandClick(leftSize: Int = 16, topSize: Int = 16, rightSize: Int = 16, bottomSize: Int = 16) {
val viewParent = parent as View val view = this viewParent.post {
val delegateArea = Rect() view.getHitRect(delegateArea) delegateArea.left -= leftSize delegateArea.top -= topSize delegateArea.right += rightSize delegateArea.bottom += bottomSize viewParent.touchDelegate = TouchDelegate(delegateArea, view) }}
权限申请
原生的申请,涉及到申请的地方和onRequestPermissionsResult()
方法,一次申请多个权限之后需要到这个方法里循环遍历,还要想办法区分用户是“拒绝一次”还是“始终拒绝”。现在:
/** * 申请权限扩展 */fun FragmentActivity.requestPermissions( vararg permissions: String, message: String = "", callback: ((granted: Boolean, temp: Boolean) -> Unit)? = null) {
if (permissions.isNotEmpty()) {
RxPermissions(this).requestEachCombined(*permissions) .subscribe(Consumer() {
if (!TextUtils.isEmpty(message) && !it.granted) {
ToastTools.showShort(message) } callback?.invoke(it.granted, it.shouldShowRequestPermissionRationale) }) }}
使用:
requestPermissions(Manifest.permission.CAMERA) {
grant, temp -> if (grant) {
ToastTools.showShort("granted") } else {
ToastTools.showShort("deny") }}
启动界面
/** * 简单地启动Activity */inline fun <reified T : Activity> Context.openActivity() {
val startIntent = Intent(this, T::class.java) startActivity(startIntent)}
使用:
openActivity<MainActivity>()
2.可以直接使用的类
data class
不用写一大堆getter/setter了
data class User(val name: String, val age: Int)
Object class
懒汉式?饿汉式?多线程是否安全?写单例再也不用双层加锁判断、或者静态类实现了,就一句话
object StoreManager {
}
3.其他
可选参数
以前经常这样写很多重载方法:
扫描二维码关注公众号,回复:
13209360 查看本文章
public void doSomething(int a) {
}public void doSomething(String s) {
}public void doSomething(int a, String s) {
}
现在:
fun doSomething(a:Int = 0, s:String = "") {
}
原生字符串
String json = "{\"msg\": \"操作成功\",\"code\": 0,\"data\": {}}";
现在:
val json = """{"msg": "操作成功","code": 0,"data": {}}"""
字符串拼接
String s = "abc" + v + "def";
现在:
val s = "abc${
v}def"