注册

你可能需要了解下的Android开发技巧(一)

callbackFlow {}+debounce()降频


假如当前要做一个实时搜索的功能,监听输入框动态输入的内容向服务器发起搜索请求,这不仅会增大服务器的压力,而且也会产生很多的无用请求。


比如其实你想搜索一个“android”,但随着你在输入框中动态编辑,最多可能会向服务器发送7次请求,很明显前面6次请求都是属于无用请求(暂时不考虑模糊匹配的场景)。


这个时候我们就可以借助于callbackFlow{}将输入框的动态输入转换成流,再借助debounce()对流进行降频即可。关于对debounce()的讲解,可以参考之前的文章:debounce()限流


fun test4(editText: EditText) {
lifecycleScope.launchWhenResumed {
callbackFlow {
val watcher = editText.doAfterTextChanged {
trySend(it?.toString() ?: "")
}

invokeOnClose {
editText.removeTextChangedListener(watcher)
}
}.debounce(200).collect {
//对于输入框中的内容向服务器发起实时搜索请求

}
}
}

判断当前是否为主进程


常见的业务场景中,可能我们会把Service单独放一个进程处理,比如为了单独存放WebView再或者专门开一个服务进程与服务器进行通信,这样当UI进程死掉,也能缓存最新的数据到内容和本地 。


但有时,Service单独放一个进程处理,也会走Application的初始化逻辑,比如初始化第三方SDK、获取某些资源等等,但这些可能是只有UI进程才需要,所以Service进程初始化应该跳过这些逻辑。


所以我们需要判断当前的线程是否属于UI线程,可以利用UI进程的包名和进程名相同的特性实现,代码如下:


fun isMainProcess(): Boolean =
getSystemService<ActivityManager>()?.let {
it.runningAppProcesses.find { info ->
info.pid == Process.myPid()
}?.let { res ->
res.processName == packageName
}
} ?: true

当我写完上面的代码之后,发现Application竟然直接提供了一个获取当前进程名称的方法:


image.png


不过这个只有SDK28以上才能使用,可以判断一下,SDK28以下用上面的代码判断,SDK28及以上用下面的代码判断:


fun isMainProcess2(): Boolean = packageName == getProcessName()

作者:长安皈故里
链接:https://juejin.cn/post/7136913350893502494
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册