privateclassFetcher<Data> /** * @param model We really ought to copy the model, but doing so can be hugely expensive and/or * lead to OOMs. In practice it's unlikely that users would pass an array into Glide and * then mutate it. */internalconstructor(privateval model: ByteArray, privateval converter: ByteArrayLoader.Converter<Data>) : DataFetcher<Data> { overridefunloadData(priority: Priority, callback: DataFetcher.DataCallback<inData>) { val result = converter.convert(model) callback.onDataReady(result) }
现在的商业虚拟机大部分都是分代回收算法, 分为新生代(young gen)和老生代(old gen), 其中 young gen 又分为 eden 区, from survior 和 to survior 区. 新生代的 GC 叫做 Minor GC, 老生代的 GC 叫做 Major GC / Full GC . 数据一开始会分配到 Eden 区(大对象直接进入 old gen), young gen 采用的是复制算法, 因为 young gen 的大部分数据都是回马上死亡的, 所以只需复制少部分存货的对象从 From survior 到 To survior. 当 young gen 的数据经历了几次 GC 后(默认15次), 它会从 young gen 移到 old gen. 而 old gen 采用的是标记-整理算法, 可以应用 old gen 中对象 100% 都存活的情况.
Kotlin // UUID 方式 val workId: UUID = oneTimeWorker.getId() WorkManager.getInstance().cancelWorkById(workId)
// Tag 方式 val oneTimeWorker = OneTimeWorkRequest.Builder(TestWorker::class.java) .addTag("myTag") .build() WorkManager.getInstance().cancelAllWorkByTag("myTag")
// A, B, C 就会按顺序执行, 如果全部返回成功或者某一个返回失败, 那该任务链就会结束. WorkManager.getInstance() .beginWith(workA) .then(workB) .then(workC) .enqueue()
// A, B 一起运行, 虽然这2个的开始顺序不定, 但是 C 一定是在这2个运行后才运行. WorkManager.getInstance() .beginWith(Arrays.asList(workA, workB)) .then(workC) .enqueue() // B 一定会在 A 后面运行, D 也一定会在 C 后面运行, 但是 AB 与 CD 这两条链的运行顺序不定, 但是 E 一定是在 B 和 D 都结束后才运行. val chain1 = WorkManager.getInstance() .beginWith(workA) .then(workB) val chain2 = WorkManager.getInstance() .beginWith(workC) .then(workD) val chain3 = WorkContinuation .combine(Arrays.asList(chain1, chain2)) .then(workE) chain3.enqueue()
// A, B, C 就会按顺序执行, 如果全部返回成功或者某一个返回失败, 那该任务链就会结束. WorkManager.getInstance() .beginWith(workA) .then(workB) .then(workC) .enqueue();
// A, B 一起运行, 虽然这2个的开始顺序不定, 但是 C 一定是在这2个运行后才运行. WorkManager.getInstance() .beginWith(Arrays.asList(workA, workB)) .then(workC) .enqueue(); // B 一定会在 A 后面运行, D 也一定会在 C 后面运行, 但是 AB 与 CD 这两条链的运行顺序不定, 但是 E 一定是在 B 和 D 都结束后才运行. WorkContinuation chain1 = WorkManager.getInstance() .beginWith(workA) .then(workB); WorkContinuation chain2 = WorkManager.getInstance() .beginWith(workC) .then(workD); WorkContinuation chain3 = WorkContinuation .combine(Arrays.asList(chain1, chain2)) .then(workE); chain3.enqueue();
相同任务的重复策略
前面提到对于 Worker 来说, 可以通过 UUID 和 Tag 来保证其唯一性, 这样在需要的时候就可以避免任务重复执行. 但对于连续的任务链, 如果任务多了, 这样的方式会很繁琐. 于是, WorkerManager 也提供了相应的 API 来保证其唯一性.
overridefundoWork(): Result { val first = inputData.getInt("KEY_FIRST", 0) val second = inputData.getInt("KEY_SECOND", 0) val result = first + second // 1 + 2 = 3 val output = Data.Builder() .putInt("KEY_RESULT", result) .build() return Result.success(output) } }
// 监听返回 WorkManager.getInstance().getWorkInfoByIdLiveData(worker.id) .observe(this, Observer { info -> if (info != null && info.state.isFinished) { // 获取返回结果, 应该是3 val result = info.outputData.getInt("KEY_RESULT", 0) } })
@NonNull @Override public Result doWork(){ int first = getInputData().getInt("KEY_FIRST", 0); int second = getInputData().getInt("KEY_SECOND", 0); int result = first + second; // 1 + 2 = 3 Data output = new Data.Builder() .putInt("KEY_RESULT", result) .build(); return Result.success(output); } }
// 监听返回 WorkManager.getInstance().getWorkInfoByIdLiveData(worker.getId()) .observe(lifecycleOwner, info -> { if (info != null && info.getState().isFinished()) { // 获取返回结果, 应该是3 int result = info.getOutputData().getInt(KEY_RESULT, 0)); } });
| Call Activity | Standard | SingleTop | SingleTask | SingleInstance
:---: | :---: | :---: | :---: | :---: | :---:
Pay Activity |
Standard | | Y | Y | Y | N
SingleTop | | Y | Y | Y | N
SingleTask | | N | N | N | N
SingleInstance | | N | N | N | N
List list = new LinkedList(); List spy = Mockito.spy(list); spy.add("one"); when(spy.size()).thenReturn(100); spy.add("two"); System.out.println(spy.size());
他在论文中提到 we refer to this kind(指应用程序全局且使用interactor, command以及selection概念的) of controller as a presenter, 所以 Presenter 也是一种 Controller. MVC 和 MVP 的依赖关系图是一样的.
Android 中的 MVP
Android 中的 MVP, Presenter 作为桥梁的功能更加明显, 但是也有一些变种类型, 比如 Google 的 MVP 模式, 添加了 Contract 作为合约类, 定义了 View 和 Presenter 之间的接口, 而 Model 则作为数据中心, 提供所有获取数据的接口, Prsenter 中只需要选择是使用测试的 Data Repo 还是 正式的 Data Repo 即可.