首页   

Kotlin回调方法可以支持指定线程执行

BestNevermore  ·  · 3 年前
阅读 30

Kotlin回调方法可以支持指定线程执行

背景

记录一个输入法应用线上P0事故产生的迭代线.

  1. 迭代1

在键盘上有个运营位弹窗,在键盘收起的时候关闭弹窗. 代码如下:

fun Activity.showExampleDialog(view: View) {
    AppCompatDialog(this).apply {
        setContentView(
            Button(this@showExampleDialog).apply {
                setOnClickListener {
                    dismiss()
                }
            }
        )
    }.show();
}
复制代码
  1. 迭代2 在收起键盘的时候有可能执行一些耗时操作,如果有耗时操作dismiss会被放入到子线程执行
    Executors.newSingleThreadExecutor().execute(Runnable {
    // 可能的耗时操作
        dismiss()
    });
复制代码
  1. 迭代3 线上发现一些可疑崩溃,鉴于键盘已经收起来了,RD评估影响不大. 直接把整个回调代码块try了起来.
    Executors.newSingleThreadExecutor().execute(Runnable {
        try {
        // 可能的耗时操作
            dismiss()
        } catch (e: Exception) {
        }
    });
复制代码
  1. 迭代4 因需求需要,把Dialog换成了PopupWindow`.
fun Activity.showExamplePopWindow(view: View) {
    PopupWindow(this).apply {
        setContentView(
            Button(this@showExamplePopWindow).apply {
                setOnClickListener {
                    Executors.newSingleThreadExecutor().execute(Runnable {

                        try {
                            dismiss()
                        } catch (e: Exception) {
                        }
                    });
                }
            }
        )
    }.showAsDropDown(view);
}
复制代码
  1. 事故

这个需求的弹窗平时很少用到,上诉修改完后几个月没有用,突然有天推送了一个运营弹窗,推送完后发现线上大量用户反馈:

键盘上有一个弹窗无法关闭,因为挡住了键盘,键盘也无法输入了.
复制代码

(PS:绝大部分用户不知道怎么杀死输入法,应用没有做兜底,也失去了自救的机会)

原因

  1. Dialog的dismiss方法系统已经帮开发者做了线程判断,如果在子线程使用,系统会自动切回到主线程执行,但是PopupWindow确不行.
  2. 几个迭代下来,代码解构已经发生改变,执行dismiss函数的代码已经被放到其他类里面, 执行线程也被切换到了子线程.

改进

抛开其他,仅对程序员来说:

  1. 粗暴的try...catch,切子线程能解决的只是当时的问题,一些问题不明就里的处理方式带来的后果比崩溃严重.
  2. 后浪在改代码的时候,一定要找个前浪问清楚需求的背景和帮忙review下
  3. 做可以支持指定线程执行的回调方法.
fun android.view.View.onClick(
    context: CoroutineContext = Dispatchers.Main,
    handler: suspend CoroutineScope.(v: android.view.View?) -> Unit
) {
    setOnClickListener { v ->
        CoroutineScope(context).launch {
            v?.let { handler(it) }
        }
    }
}
复制代码

总结

通过这个扩展顺便熟悉下Kotlin的语法

对比着Java实现,体会下Koltin代码的简洁.

推荐文章
哲学王  ·  一个人的书房,就是这个人的全部  ·  23 小时前  
哲学王  ·  张鸣:互害社会的局面怎么破?  ·  4 天前  
哲学园  ·  四十多年前的大学生活什么样?  ·  5 天前  
哲学人  ·  庄振华:为什么要读黑格尔的逻辑学?  ·  1 周前  
华策影视  ·  《去有风的地方》研讨会 | ...  ·  6 天前  
言鼎动作学苑  ·  线下课 | 五月广州又有好课?还有活动价!  ·  1 年前  
国信研究  ·  特步国际(01368.HK)快评:Q3压力之 ...  ·  2 年前  
ittbank  ·  突发!中芯国际宣布:科创板上市!  ·  4 年前  
互撸漫话  ·  没点演技,都不好意思出轨了!  ·  5 年前  
小鹿情感先生  ·  坏男孩招聘公众号编辑&签约作者  ·  6 年前  
© 2022 精读
删除内容请联系邮箱 2879853325@qq.com