前言
该框架主要解决切换异步线程的问题,当然在前不久博主发布的 GT.EventBus 框架 也能实现切换异步线程,但和 GT.Observable 使用的场景均有所不同,相信在某些场景下,你会更喜欢这个异步切换.
提示:GT.EventBus 与 GT.Observable 可以配合着使用会更香
这次框架与RxJava 的异步切换线程有相似之处,也是使用链式结构.接下来我们就来看看具体的使用
假如需要从数据库读取数据后显示在屏幕上,最平常的实现咋实现呢?
第一种写法:
public class MainActivity extends AppCompatActivity {
private TextView tv1;
private List<LoginBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = findViewById(R.id.tv1);
new Thread(new Runnable() {
@Override
public void run() {
list = DbUtils.queryAll();//延时五秒后返回数据
GT.logt("总共数据量:" + list.size());
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
}).start();
}
private Handler handler = new Handler(Looper.getMainLooper()) {
public void handleMessage(Message msg) {
// 处理消息
super.handleMessage(msg);
switch (msg.what) {
case 1:
GT.logt("进行UI更新处理");
tv1.setText("查询出" + list.size() + "条数据");
//...
break;
case 2:
//进行其他处理
break;
}
}
};
}
先用子线程去执行耗时操作.拿到数据后再用 Handler 切换到主线程进行UI更新.当然这么使用 Handler 是会造成内存泄漏的(具体如何防止请自行查看其他资料),本章重点讲异步线程切换逻辑
第二种写法:
public class MainActivity extends AppCompatActivity {
private TextView tv1;
private List<LoginBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = findViewById(R.id.tv1);
new Thread(new Runnable() {
@Override
public void run() {
list = DbUtils.queryAll();//延时五秒后返回数据
GT.logt("总共数据量:" + list.size());
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
GT.logt("进行UI更新处理");
tv1.setText("查询出" + list.size() + "条数据");
}
});
}
}).start();
}
}
使用子线程查询返回数据后,再使用Activity引用切换到主线程进行 UI 更新,代码量相对于使用Handler 要少点,但具体还得看具体的使用场景.
目前的逻辑还是非常简单的,一旦逻辑复杂起来的,使用这些方式来实现异步线程切换处理你就会发现代码会变的非常难以维护,阅读性也变的非常差.
例如:先从本地读取重要的key后,再从后台请求下来数据ID,再进行数据库查询,再进行页面展示,这样的异步切换,来回越多代码也就相对于阅读性越差.再加上其他的逻辑处理,那就更加了,而 GT.Observable 就是来解决在代码越来越多的情况下,依旧能保持非常简洁的阅读性
依赖GT库
在使用GT库里封装的架构当然需要先依赖好GT库:
详细依赖教程请参看
我们先来看看 GT.Observable 是怎么实现的
public class MainActivity extends AppCompatActivity {
private TextView tv1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = findViewById(R.id.tv1);
GT.Observable.getDefault().execute(new GT.Observable.RunJavaR<List<LoginBean>>() {//执行子线程
@Override
public List<LoginBean> run() {
List<LoginBean> list = DbUtils.queryAll();//延迟5秒返回
GT.logt("总共数据量:" + list.size());
return list;
}
}).execute(new GT.Observable.RunAndroidV<List<LoginBean>>() {//切换UI线程
@Override
public void run(List<LoginBean> loginBeans) {
GT.logt("进行UI更新处理");
tv1.setText("查询出" + loginBeans.size() + "条数据");
}
});
}
}
这种是采用链式结构的实现方式,线程的执行方式始终保持着从头到尾(从第一个到最后一个)的顺序执行(当然也支持Handler那样的方式进行切换,后面会讲解到).这样不管你来回切换了多少次线程,你阅读起来始终是那么从头到尾的简洁.
接下来我们一起来看看 GT.Observable 更加详细的使用教程, GT.Observable 共有八个执行方法
子线程切换
第一个:执行子线程,且无形参,无返回值
GT.Observable.getDefault().execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
//执行子线程,且不带返回值与形参
}
});
第二个:执行子线程,且无形参,有返回值(返回数据到下一层线程)
GT.Observable.getDefault().execute(new GT.Observable.RunJavaR<String>() {
@Override
public String run() {
return null;
}
});
第三个:执行子线程,且有形参(接收上层线程的返回值),无返回值
GT.Observable.getDefault().execute(new GT.Observable.RunJavaV<String>() {
@Override
public void run(String s) {
}
});
第四个:执行子线程,且有形参(接收上层线程的返回值),有返回值(返回数据到下一层线程)
GT.Observable.getDefault().execute(new GT.Observable.RunJavaVR<String>() {
@Override
public String run(String s) {
return null;
}
});
以上就是所有子线程切换执行的所有方式了,根据不同的需求指定合适的方式来执行子线程
下面再附上四个UI线程切换的方法:
UI线程切换
第一个:执行子线程,且无形参,无返回值
Observable.RunAndroid<T> runnable
第二个:执行子线程,且无形参,有返回值(返回数据到下一层线程)
Observable.RunAndroidR<T> runnable
第三个:执行子线程,且有形参(接收上层线程的返回值),无返回值
Observable.RunAndroidV<T> runnable
第四个:执行子线程,且有形参(接收上层线程的返回值),有返回值(返回数据到下一层线程)
Observable.RunAndroidVR<T> runnable
在填写这些内部类的时候,有一个小窍门:
RunJava : 切换 Java 子线程
RunAndroid:切换 Android 主线程
其中的 RunJavaV 的 V 代表有形参
其中的 RunJavaR 的 R 代表有返回值
其中的 RunJavaVR 的 VR 代表有形参,有返回值
若既没有V也没有R的代表,既没有形参也没有返回值, RunAndroid 的也是一样的
GT.Observable 共有两种实现的方式,除了链式结构还有另一种实现方式:
public class MainActivity extends AppCompatActivity {
private TextView tv1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = findViewById(R.id.tv1);
GT.Observable.getDefault().execute(new GT.Observable.RunJava<String>() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
setData("传递的数据:" + i);
execute(runAndroidV, false);
GT.Thread.sleep(1000);
}
}
});
}
private GT.Observable.RunAndroidV<String> runAndroidV = new GT.Observable.RunAndroidV<String>() {
@Override
public void run(String s) {
GT.logt("执行UI线程:" + s);
tv1.setText(s);
}
};
}
这种方式是子线程循环10次并发布消息给到UI线程进行更新UI
然后再执行方法上使用的是 execute(runAndroidV, false); 第一个参数是执行的线程,第二个参数是 是否等待完成,是否保证该事件顺序 (默认为 true)
如果填入的是 true ,那就会导致, 先运行完子线程的循环后才会再运行 子线程
上面的使用场景是适合填 false 参数的,那true 的参数是在啥场景呢?我们来看看这段代码
GT.Observable.getDefault().execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行A线程");
}
}).execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行B线程");
for (int i = 0; i < 5; i++) {
GT.logt("读取中..." + i);
GT.Thread.sleep(1000);
}
}
}).execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行C线程");
}
});
运行日志:
在我们看完代码时,我们就知道,运行起来的效果肯定是这样的,因为 GT.Observable 的链式结构始终保持着从头到尾(从第一个到最后一个)的顺序执行 那我们想在执行B线程的时候,不进行等待里面的耗时时间,直接执行下一个线程实现?
很简单,只需要加一个 true 参数即可,(跳过该事件的耗时后,且保证该事件顺序)
GT.Observable.getDefault().execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行A线程");
}
}).execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行B线程");
for (int i = 0; i < 5; i++) {
GT.logt("读取中..." + i);
GT.Thread.sleep(1000);
}
}
},true).execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行C线程");
}
});
运行日志:
加上一个true就代表:跳过该事件的耗时后,且保证该事件顺序, 看是不是线程执行的顺序依旧是 A,B,C的顺序,但B线程中的耗时操作不受顺序影响,当然这个设置在 RunAndroid 线程中也是一样的使用
如果我们中途出现读取数据库异常,不想执行下层的线程了可以这样操作:
GT.Observable.getDefault().execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行A线程");
}
}).execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行B线程");
for (int i = 0; i < 5; i++) {
GT.logt("读取中..." + i);
GT.Thread.sleep(1000);
if (i == 3) {
stop();//强行停止线程,下层线程将不会再执行
break;
}
}
}
}).execute(new GT.Observable.RunJava<Object>() {
@Override
public void run() {
GT.logt("执行C线程");
}
});
运行日志:
还有一个小知识,在获取实例的时候使用的是 getDefault() 方法,但每次使用均是使用新的对象,如需使用已存在的实例对象可填入 true 参数,
结尾: 以上就是 GT.Observable 目前API使用的教程了,今后更新其他的API方法时,会在本章节后面继续添加更新.
点个关注点个赞呗(〃'▽'〃) 关注博主最新发布库:GitHub - 1079374315/GT