维度的 Trade Off
今天我想先说一个英文单词, 叫 Trade Off. 中文翻译过来可以说叫权衡, 妥协, 但是这么干巴巴的翻译可能不能体现这个词的牛逼之处, 我来举个例子. 比如迪丽热巴和谢娜同时追求我, 虽然迪丽热巴颜值更高, 但是考虑到谢娜在湖南台的地位以及和她在一起之后能给我带来的曝光度, 我选择了谢娜....(以上纯属段子)
Anyway... 这就是 Trade Off, 一个很艰难的选择, 但是最后人都是趋于自己的利益最大化做出最后的决定. Trade Off 这个词贯穿了软件开发的所有流程, 在多线程的选择下面也是有一样的体现.
谷歌官方在 18 年的 IO 大会上放了这么一张图
image
我先来翻译翻译这张图.
横轴从左往右分别是 Best-Effort(可以理解为尽力而为)还有 Guaranteed Execution(保证执行). 竖轴从上往下分别是 Exact Timing(准确的时间点)还有 Deferrable(可以被延迟). 这张图分别从在多线程下执行的代码的可执行性和执行时间来把框架分成了四个维度. 其中我想先说说个人的理解: 对于安卓里面的里面的任何代码, 都逃不开生命周期这个话题. 因为安卓的四大组件有两个都是有生命周期的, 而且对于用户来说, 可见的 Activity 或者 Fragment 才是他们最关心 App 的部分. 所以一段代码, 在保证没有内存泄漏的情况下, 能不能在异步框架下执行完毕, 就得取决于代码所在载体 (Activity/Fragment) 的生命周期了. 比如上一期我们说到的 RxJava 的例子:
- @Override
- protected void onDestroy() {
- super.onDestroy();
- //onDestroy 里面对 RxJava stream 进行 unsubscribe, 防止内存泄漏
- subscription.unsubscribe();
- }
这段代码有可能会阻止我们在 Observable 里面的 API 进行调用.
那么在安卓的生命周期的背景下, 这段代码就是 Best Effort, 尽力而为了. 能跑就跑, 要是 activity 没了, 那就拉倒...
- @Override
- public void onCreate() {
- super.onCreate();
- startForeground(1, notification);
- Log.d(TAG_FOREGROUND_SERVICE, "My foreground service onCreate().");
- }
- class MakeSubscriptionWorker : Worker{
- constructor(context: Context, parameterName: WorkerParameters):super(context,parameterName)
- override fun doWork(): Result {
- //unsubscribe 的 API call 在这里做
- val API = API()
- var response = API.unSubscribe()
- if(response != null){
- return Result.success(response)
- }
- else{
- return Result.failure()
- }
- }
- }
- //1. 创建我们 Worker 的实例并且开始执行!
- WorkManager.getInstance().enqueue(OneTimeWorkRequest.Builder(MakeSubscriptionWorker::class.java!!)
- .addTag(MakeSubscriptionWorker::class.simpleName!!)
- .build())
- //2. 把 API call 的结果转化成 Jetpack 里面的 LiveData, 并且开始监听结果
- WorkManager.getInstance().getWorkInfosByTagLiveData(MakeSubscriptionWorker::class.simpleName!!).observe(this,purchaseObservaer)
- //3. 如果用户退出了 Activity, 那么停止监听结果
- WorkManager.getInstance().getWorkInfosByTagLiveData(MakeSubscriptionWorker::class.simpleName!!).removeObserver(purchaseObservaer)
- B
- .mergeWith(C)
- .concatMap(E)
- .concatMap(F)
- .mergeWith(A
- .concatMap(D))
- //Dispatch code in Main thread , unless we swithc to antoehr
- var job = GlobalScope.launch(Dispatchers.Main) {
- //force task A B C D to run in IO thread
- var A = async (Dispatchers.IO){//do something in IO thread pool }
- var B = async (Dispatchers.IO){//do something in IO thread pool }
- var C = async (Dispatchers.IO){//do something in IO thread pool }
- var D = async (Dispatchers.IO){//do something in IO thread pool }
- //join 4 tasks (similar to merge concept in RxJava),
- A.await()
- B.await()
- C.await()
- D.await()
- WorkManager.getInstance()
- .beginWith(OneTimeWorkRequest.Builder(MakeSubscriptionWorker::class.java!!).build())
- .then(OneTimeWorkRequest.Builder(MakeSubscriptionWorker::class.java!!).build())
- .then(OneTimeWorkRequest.Builder(MakeSubscriptionWorker::class.java!!).build())
- RxJava -> Coroutine -> WorkManager
来源: http://www.jianshu.com/p/b715d0e543b3