IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Looper,kotlin构造器 -> 正文阅读

[移动开发]Looper,kotlin构造器


在一个安静的下午,一妹子在RxHttp群里反馈,自己开发的app,账号被挤下线时,重新登录到首页后,发现有一个请求,代码执行了,却没有任何回调,看得出,妹子很着急。

what ??? 还有这种事?原本安静的群,一下活跃了起来,男同胞们一顿狂猜,我总结了下,如下:

会不会请求代码没执行,妹子自己搞错了吧?

发请求前,出现异常,代码被中断运行?

请求过程伴随着页面跳转,导致页面销毁时,请求被自动关闭?

请求过程出现异常,被RxJava全局异常捕获了,并吃掉了,所以收不到失败回调?

这里解释下,妹子采用RxHttp+RxJava结合的方式发请求

经过第一轮询问后,以上猜想轻而易举的被推翻了,我也大概知道了案件的细节,为此,我用代码来还原一下,为简化案件,还原时,我会适当的做出修改,但意思还是那个意思。

2、案件还原


妹子在首页MainActivity的OnCreate方法,会并行3个请求,如下:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main_activity);

request1();

request2();

request3();

}

public void request1() {

RxHttp.get("/service/…")

.asString()

.to(RxLife.toMain(this)) //页面销毁,自动关闭请求,并在UI线程回调

.subscribe(s -> {

//成功回调

}, throwable -> {

//异常回调

});

}

public void request2() {

//省略请求代码,请求代码类似request1()方法

}

public void request3() {

//省略请求代码,请求代码类似request1()方法

}

这段代码看起来并没有任何问题,正常登录进来后,都是正常的。

但是当账号被挤下线后(挤到登录页),重新登录到首页后,发现request1()request2()request3()三个请求方法都执行了,可request2()方法却迟迟收不到回调,不管成功/失败都收不到。

3、开始办案


以上猜想全部被推翻,接下来怎么办?很明显,我们要明确一点:

请求到底有没有发出去?服务端有没有收到这个请求?

随后,妹子用Adnroid Studio自带的Profiler工具,监控了下,发现请求并未发出来,接着,又找后台人员确认了下,后台也并未收到这个请求。

那就更奇怪了,请求代码执行了,请求却没有发出去?作为程序员的我第一反应,这怎么可能呢?妹子你用的手机有问题吧?要不换个手机试试?显然换了手机,问题一样存在,这就尴尬了。

接下来,跟妹子不断的调试,一而再,再而三的确认了,请求代码没有任何问题,然而,我却陷入了沉思之中,很绝望,很无助,甚至怀疑这是OkHttp的问题。

作为一名老鸟,最后我还是冷静了下来,重新整理了线索,发现又一条线索被遗漏了,那就是账号被挤,自动跳转到登录页面,为什么只有在账号被挤时,才会出现问题?于是乎,我调整了调查方向

账号是如何被挤?又是如何跳转到登录页面的?

终于,凶手露出了水面,凶手就是Looper,原来妹子是通过OkHttp的拦截器来监听账号被挤,并通过Looper来弹出一个Toast提示,并且执行页面跳转逻辑,如下:

public class TokenInterceptor implements Interceptor {

private Context context;

//省略部分代码

@Override

public Response intercept(Chain chain) throws IOException {

Request request = chain.request();

Response originalResponse = chain.proceed(request);

String code =
originalResponse.header(“code”);

if ("-1".equals(code)) { //账号被挤

Looper.prepare();

Toast.makeText(context, “你的账号在其它设备上登录”, Toast.LENGTH_LONG).show();

context.startActivity(new Intent(context, LoginActivity.class));

Looper.loop();

}

return originalResponse;

}

}

也许你会问,这确定有问题?通过Looper在子线程弹出一个Toast,这不是很正常的一件事?经常这么干,从来没出现任何问题,为啥到你这就出问题?

我让妹子把LooperToast代码注释掉,if语句里面只保留一行startActivity,妹子试后开心的跟我说,好了,没问题了,这怎么解释?

4、开始破案


Looper一脸委屈的说道:你说我是凶手,我就是凶手了,证据呢?

ok,我们就来寻找证据,我们知道,Looper.loop()方法内部,会开启一个死循环,如下:

public static void loop() {

//省略部分代码

for (;😉 {

Message msg = queue.next(); // might block

if (msg == null) {

// No message indicates that the message queue is quitting.

return;

}

//省略部分代码

}

//省略部分代码

}

可以看到,queue.next()这行代码官方注释了,有可能会被堵塞,什么时候会堵塞?没有消息的时候,可见,调用Looper.loop()方法所在的线程会进入死循环。

那这个和我们的案件有什么关系呢?

这就要来说说RxJava的线程池了,上面TokenInterceptor回调所在的线程是RxJava的IO线程,而RxJava的IO线程池的配置,却仅允许一条核心线程执行任务,当任务在执行,其它任务过来时,必须等待至上一个任务结束。

IoScheduler类中可以找到静态内部类ThreadWorkerThreadWorker继承至NewThreadWorker,在该类中,我们可以找到线程池对象,如下:

public class NewThreadWorker extends Scheduler.Worker implements Disposable {

private final ScheduledExecutorService executor;

//省略部分代码

public NewThreadWorker(ThreadFactory threadFactory) {

//这里创建了线程池

executor = SchedulerPoolFactory.create(threadFactory);

}

//省略部分代码

}

SchedulerPoolFactory.create方法点进去看看

e {

private final ScheduledExecutorService executor;

//省略部分代码

public NewThreadWorker(ThreadFactory threadFactory) {

//这里创建了线程池

executor = SchedulerPoolFactory.create(threadFactory);

}

//省略部分代码

}

SchedulerPoolFactory.create方法点进去看看

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:43:51  更:2022-02-01 20:43:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:02:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码