本篇将讲解Android夜间模式,用添加蒙版的方式来实现
异步操作
异步编程 之一 异步操作+Rxjava
讲到异步编程那就得先介绍一下Android当前的架构
Android当前架构
在Android操作系统启动之后,会启动一个名为Zygote的进程,Zygote是负责创建其它大部分应用程序进程的一个进程。Zygote进程启动、加载核心程序库和数据结构到内存后会创建一个Dalvik虚拟机(DVM)进程(SystemServer),这个进程包含了大部分的系统服务(包括上面管理Activity,也就是ActivityManagerService)之后Zygote会为这个app创建一个DVM,在直接fork出一个子进程,这种架构的好处是同时启动多个App 时,多个App进程可以访问共享内存。
简单来说就是,先创建Zygote,在通过Zygote创建SystemServer进行(系统服务进程),最后在要创建的App创建Dalvik虚拟机
Zygote是Android系统创建进程的核心进程,负责启动Dalvik虚拟机,加载一些必要的系统资源和系统类,顺便启动SystemServer进行,最后在等待并处理App创建请求
异步编程
先来讲讲Android中最常见的异步方式
AsyncTask
AsyncTask在Kotlin中已被协程替代(可去<异步编程(三)>了解详情),所以下方将会用Java来进行讲解
介绍
AsyncTask是Android中自带的一个轻量级异步类,可以通过它轻松的实现工作线程和UI线程之间的通讯或切换
使用
AsyncTask是一个抽象类,想要使用它,那么就得先创建一个类来继承它,在重写它的4个方法(一般只用重写4个方法)
需要重写的4个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//这个就是要在后台做的工作,他将运行在后台工作线程上
protected abstract Result doInBackground(Params... params);
//这个时开始执行前的操作,运行在主线程上
protected void onPreExecute();
//doInBackground完成后调用
protected void onPostExecute(Result result);
//实时更新,通过在doInBackground中调用publishProgress()方法
protected void onProgressUpdate(Progress... values);例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33public class AsyncTaskDome extends AppCompatActivity {
private ProgressDialog progressDialog;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task_dome);
progressDialog = new ProgressDialog(this);
new Download().execute("下载地址");
}
-----------------------------------------------
public class Download extends AsyncTask<String, Integer, Boolean> {
protected void onPreExecute() {
progressDialog.show();
//初始化进度条
}
protected Boolean doInBackground(String... strings) {
//这里假装在进行下载
Uri uri = Uri.parse(strings[0]);
return true;
}
protected void onProgressUpdate(Integer... integers) {
//这里对进度条进行更新进度
progressDialog.setMessage(String.valueOf(integers[0]));
}
}
}上方的代码中,我创建了一个Download类用来继承AsyncTask,并重写了它的4个方法。之后就只需要在Activity中创建一个Download对象,然后执行execute添加到队列中去
RxJava
介绍
Rxjava是一个用来实现异步的、基于事件的第三方库(就把它理解成Android Handler 的升级版就行了)
概念
我们先来了解一下Rxjava的概念
- RxJava的异步实现,就是通过一种扩展的观察者模式来实现的
- Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer
使用
先创建一个Observer观察者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17object : Observer<String?> {
override fun onNext(t: String) {
println("onNext --> $t")
}
override fun onError(e: Throwable) {
println("on error --> $e")
}
override fun onSubscribe(d: Disposable) {
println("onSubscribe --> $d")
}
override fun onComplete() {
println("onComplete")
}
}再创建 Observable 被观察者
1
2
3
4val observable: Observable<String> = Observable.create{
it.onNext("continue!")
it.onComplete()
}最后再进行关联
1
observable.subscribe(observer)
当然,也可以直接使用链式调用来写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22Observable.create(ObservableOnSubscribe<String> {
it.onNext("1")
it.onNext("2")
it.onNext("3")
it.onNext("4")
it.onComplete()
}).subscribe(object : Observer<String?> {
override fun onNext(t: String) {
println("onNext --> $t")
}
override fun onError(e: Throwable) {
println("on error --> $e")
}
override fun onSubscribe(d: Disposable) {
}
override fun onComplete() {
println("perform !")
}
})
Scheduler (线程切换)
在不指定线程的情况下, RxJava 遵循的是线程不变的原则,即:在哪个线程调用 subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到 Scheduler (调度器)
在RxJava内部已经内置了几个Scheduler,下面将会进行介绍
Schedulers.newThread()
开启一个新线程并使用
Schedulers.io()
切换到I/O线程,进行操作
I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程
Schedulers.computation()
切换到计算而所使用的线程
这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU
AndroidSchedulers.mainThread()
切换回当前所在的主线程
subscribeOn()
说人话就是数据处理所在的线程
observeOn()
结果返回所在的线程