Android Weekly Notes Issue #428
Android Weekly Issue #428
Kotlin Flow Retry Operator with Exponential Backoff Delay
这是讲协程Flow系列文章中的一篇.
对于重试的两个操作符:
- retryWhen
- retry
retryWhen的使用:
.retryWhen { cause, attempt ->
if (cause is IOException && attempt < 3) {
delay(2000)
return@retryWhen true
} else {
return@retryWhen false
}
}
retry:
.retry(retries = 3) { cause ->
if (cause is IOException) {
delay(2000)
return@retry true
} else {
return@retry false
}
}
可以把时间指数延长:
viewModelScope.launch {
var currentDelay = 1000L
val delayFactor = 2
doLongRunningTask()
.flowOn(Dispatchers.Default)
.retry(retries = 3) { cause ->
if (cause is IOException) {
delay(currentDelay)
currentDelay = (currentDelay * delayFactor)
return@retry true
} else {
return@retry false
}
}
.catch {
// error
}
.collect {
// success
}
}
Fragments: Rebuilding the Internals
Fragment在Android 10已经废弃, 现在不在framework中了, 只在AndroidX中有.
这个Fragment 1.3.0-alpha08版本的发布, 有一些关于FragmentManager内部状态的重要更新.
解决了很多issue, 简化了fragment的生命周期, 还提供了一个FragmentManager多个back stacks的支持.
核心就是这个FragmentStateManager类.
这个FragmentStateManager负责:
- 转换Fragment的生命周期状态.
- 跑动画和转场.
- 处理延迟转换.
Postponed fragments
关于状态的确定, 有一个case是一个难点: postponed fragments.
这是一个以前就有的东西, 通常跟shared element transition动画有关系.
postponed fragment有两个特点:
- view创建了, 但是不可见.
- lifecycle顶多到
STARTED.
只有调用这个方法: startPostponedEnterTransition()之后, fragment的transition才会跑, view会变成可见, fragment会移动到RESUMED.
所以有这个bug: Postponed Fragments leave the Fragments and FragmentManager in an inconsistent state bug.
这个issue相关联的还有好几个issues.
在容器层面解决问题
用一个SpecialEffectsController(以后名字可能会改)来处理所有动画转场相关的东西.
这样FragmentManager就被解放出来, 不需要处理postponed的逻辑, 而是交给了container, 这样就避免了FragmentManager中状态不一致的问题.
新的StateManager构架
原先: 一个FragmentManager总管所有.
现在: FragmentManager和各个FragmentStateManager的实例交流.
- The
FragmentManageronly has state that applies to all fragments. - The
FragmentStateManagermanages the state at the fragment level. - The
SpecialEffectsControllermanages the state at the container level.
总体
这个改动新发布, 实验阶段, 总体来说是应该没有行为改变的.
如果有行为改变, 对你的程序造成了影响, 也可以暂时关闭(FragmentManager.enableNewStateManager(false)), 并且报告个issue.
A Framework For Speedy and Scalable Development Of Android UI Tests
讲了一整套的测试实践.
没有用Appium, 用的UI Automator和Espresso.
Basic Coroutine Level 1
Kotlin协程的概念.
Android Lint Framework — An Introduction
Android Lint的介绍.
创建一个Lint规则, 保证每个人都用项目自定义的ImageView, 而不是原生的ImageView.
具体做法:
- 首先从创建一个叫做
custom-lint的module. 需要依赖lint-api和lint-checks:
compileOnly "com.android.tools.lint:lint-api:$androidToolsVersion"
compileOnly "com.android.tools.lint:lint-checks:$androidToolsVersion"
这里用了compileOnly是因为不想lint API在runtime available.
- 之后创建自定义规则. 每个lint check的实现都叫一个detector. 需要继承
Detector, 并且利用Scanners来做扫描. 报告错误需要定义Issue. 还可以创建LintFx, 作为quick fix.
class ImageViewUsageDetector : LayoutDetector() {
// Applicable elements
override fun visitElement(context: XmlContext, element: Element) {
context.report(
issue = ISSUE,
location = context.getElementLocation(element),
message = REPORT_MESSAGE,
quickfixData = computeQuickFix()
)
}
private fun computeQuickFix(): LintFix {
return LintFix.create()
.replace().text(SdkConstants.IMAGE_VIEW)
.with(TINTED_IMAGE_VIEW)
.build()
}
// Issue, implementation, and other constants
}
- 然后把定义好的自定义规则注册.
class Registry: IssueRegistry() {
override val issues: List<Issue>
get() = listOf(ImageViewUsageDetector.ISSUE)
override val api: Int = CURRENT_API
}
- 创建入口, 在
build.gradle文件中:
// Configure jar to register our lint registry
jar {
manifest {
attributes("Lint-Registry-v2": "com.tintedimagelint.lint.Registry")
}
}
- 加上依赖和一些配置.
android {
// Configurations above
lintOptions {
lintConfig file('../analysis/lint/lint.xml')
htmlOutput file("$project.buildDir/reports/lint/lint-reports.html")
xmlOutput file("$project.buildDir/reports/lint/lint-reports.xml")
abortOnError false
}
//Configurations below
}
dependencies {
// Dependencies above
// Include custom lint module as a lintCheck
lintChecks project(":custom-lint")
// Dependencies below
}
Codelabs for new Android game technologies
关于Android Game新技术的Codelabs:
- 资源打包: Play Asset Delivery -> https://codelabs.developers.google.com/codelabs/unity-gamepad/#0
- 帧率和图像: Android Performance Tuner -> https://codelabs.developers.google.com/codelabs/android-performance-tuner-unity/#0
都是Unity的game.
Android Vitals - When did my app start?
系列文章之六, 我的app啥时候启动的?
看个结论吧:
Here's how we can most accurately measure the app start time when monitoring cold start:
- Up to API 24: Use the class load time of a content provider.
- API 24 - API 28: Use
Process.getStartUptimeMillis(). - API 28 and beyond: Use
Process.getStartUptimeMillis()but filter out weird values (e.g. more than 1 min to get toApplication.onCreate()) and fallback to the timeContentProvider.onCreate()is called.
Comparing Three Dependency Injection Solutions
比较三种依赖注入的解决方案.
- 手写方式.
- Koin.
- Dagger Hilt.
Avoiding memory leaks when using Data Binding and View Binding
使用Data Binding和View Binding的时候, 注意内存泄漏问题.
Google建议在Fragment中使用binding时, 要在onDestroyView中置为null:
private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = ResultProfileBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
有个博客中介绍的方法, 可以简化成这样:
private val binding: FragmentFirstBinding by viewBinding()
Fragment还有一个参数的构造, 可以传入布局id:
class FirstFragment : Fragment(R.layout.fragment_first) {
private val binding: FragmentFirstBinding by viewBinding()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Any code we used to do in onCreateView can go here instead
}
}
冷知识: DataBinding实现了ViewBinding.
public abstract class ViewDataBinding extends BaseObservable implements ViewBinding
所以ViewBinding和DataBinding方法通用.
Anti-patterns of automated software testing
关于测试的一些anti-patterns.
推荐阅读.
Using bytecode analysis to find unused dependencies
关于这个库: https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin的说明.
Code
- https://github.com/jmfayard/refreshVersions: 一个依赖版本管理的gradle插件.
后记
好久没在博客园发过这个系列.
其实一直还有在更, 只不过写得比较散乱随意, 所以丢在了简书:
https://www.jianshu.com/c/e51d4d597637
最近有点忙, 不太有时间写博客, 积攒了好多话题都是没有完成的.
看博客两个月没更了, 拿这篇刷一下存在感.
是想多写点真正厉害有价值的原创的.
先韬光养晦, 积累一下.
Android Weekly Notes Issue #428的更多相关文章
- Android Weekly Notes Issue #230
Android Weekly Notes Issue #230 November 6th, 2016 Android Weekly Issue #230. Android Weekly笔记, 本期内容 ...
- Android Weekly Notes Issue #227
Android Weekly Issue #227 October 16th, 2016 Android Weekly Issue #227. 本期内容包括: Google的Mobile Vision ...
- Android Weekly Notes Issue #237
Android Weekly Issue #237 December 25th, 2016 Android Weekly Issue #237 这是本年的最后一篇issue, 感谢大家. 本期内容包括 ...
- Android Weekly Notes Issue #229
Android Weekly Issue #229 October 30th, 2016 Android Weekly Issue #229 Android Weekly笔记, 本期内容包括: 性能库 ...
- Android Weekly Notes Issue #221
Android Weekly Issue #221 September 4th, 2016 Android Weekly Issue #221 ARTICLES & TUTORIALS And ...
- Android Weekly Notes Issue #219
Android Weekly Issue #219 August 21st, 2016 Android Weekly Issue #219 ARTICLES & TUTORIALS Andro ...
- Android Weekly Notes Issue #236
Android Weekly Issue #236 December 18th, 2016 Android Weekly Issue #236 本期内容包括: Google的物联网平台Android ...
- Android Weekly Notes Issue #235
Android Weekly Issue #235 December 11th, 2016 Android Weekly Issue #235 本期内容包括: 开发一个自定义View并发布为开源库的完 ...
- Android Weekly Notes Issue #234
Android Weekly Issue #234 December 4th, 2016 Android Weekly Issue #234 本期内容包括: ConstraintLayout的使用; ...
随机推荐
- OKHttp 官方文档【一】
最近工作比较忙,文章更新出现了延时.虽说写技术博客最初主要是写给自己,但随着文章越写越多,现在更多的是写给关注我技术文章的小伙伴们.最近一段时间没有更新文章,虽有工作生活孩子占用了大部分时间的原因,但 ...
- bzoj 5206 [Jsoi2017]原力
LINK:原力 一张无向图 这道题统计三元环的价值和.有重边但是无自环. 我曾经写过三元环计数 这个和那个题差不太多. 不过有很多额外操作 对于重边问题 我们把所有颜色相同的重边缩在一起 这样的话我们 ...
- Chrome划词翻译-Saladict
Saladict 沙拉查词是一款专业划词翻译扩展,为交叉阅读而生.大量权威词典涵盖中英日韩法德西语,支持复杂的 划词操作.网页翻译.生词本.PDF,以及 Vimium 全键盘操作 . 迄今为止最好用的 ...
- 026_go语言中的通道方向
代码演示 package main import "fmt" func ping(pings chan<- string, msg string) { pings <- ...
- SonarQube 扫描 Java 代码
SonarQube 扫描 Java 代码 环境 需要提前安装好 SonarQube7.9,安装步骤见 Docker 安装 SonarQube 步骤 填写项目名 my_project 填写token名 ...
- idea的yml文件不识别问题
idea的yml文件不识别问题 每次当我写yml文件的时候都没有提示,而且yml文件的图标竟然是txt的图标 然后我上网查阅,发现在下面这里竟然连yml文件都无法添加设置为配置文件 然后我使用网上的下 ...
- C++ 对象的初始化
目录 默认初始化 默认构造函数(default constructor) 构造函数初始值列表(cosntructor initializer list) 直接初始化和拷贝初始化 拷贝构造函数(copy ...
- Vue Element-UI 中列表单选的实现
el-table中单选的实现 引用场景: 选择单条数据进行业务操作 实现方式: 给el-table-column设置el-radio Template 代码 <div class="r ...
- 封装react antd的表格table组件
封装组件是为了能在开发过程中高度复用功能和样式相似的组件,以便我们只关注于业务逻辑层的处理,提高开发效率,提高逼格,降低代码重复率,降低劳动时间,减少加班的可能. 本次组件的封装采用了函数式组件即无状 ...
- List 集合的操作
如果当前id存在集合里 去除当前id 如果不在集合里 去除集合最后一个结果Long videoId = 0l; // 当前 IDList<VideoZoneReturnBean> ...