无法在Android 4.4 KitKat上快速关闭ChunkedInputStream

我有一个Android Daydream,使用Twitter4j的流媒体实现显示一条推文流。 这适用于Android 4.2和4.3。 但是在4.4上,我无法快速关闭流(在onDreamingStopped )。

我得到这个堆栈跟踪,但NetworkOnMainThreadException不是问题。

连接重用问题似乎与此问题有关。 这个OkHttp变更集 ( 在这里合并到Android中)改变了closeChunkedInputStream行为方式。 如果还有更多要读取的数据,它现在尝试先丢弃流,以便快速重用套接字,而不是简单地将自己标记为“已关闭”,然后断开套接字。 如果它无法丢弃流,则会像以前一样断开套接字。

我现在得到NetworkOnMainThreadException的原因是(正如您从堆栈跟踪中看到的那样)丢弃流现在尝试从流中读取。 这很容易修复 – 我只是在关闭我的Daydream并将其忘记时将其放入AsyncTask

问题是在超时集内没有丢弃流。 查看最新版本源的HttpTransport#discardStream方法 ,它指定套接字上的100ms超时(原始提交指定30ms),然后尝试从流中读取( Util.skipAll )以清空缓冲区。 但是我看到BufferedInputStream.read()调用周围有多秒的延迟。 这种延迟的长度似乎有所不同。

这不是一个大问题 – 因为我现在必须从UI线程关闭此流,我不会导致onDreamingStopped调用需要很长时间才能返回(这导致白日梦停留在屏幕上按下/回家后很长一段时间 – 我最初的错误报告导致我跟随这个兔子洞。 但是,它确实会在关闭之后将此连接暂停一段时间。

我已经测试了使用两个不同活动级别的Twitter帐户关闭流所需的时间。 第一个在我试图关闭流时没有看到任何活动,我一直看到通话大约需要30秒。 第二个帐户有更多的活动,关闭流的时间在这个上更加多变 – 从1.5到30秒不等。 当一条新的推文进入时,它会立即关闭(一个新的块被写入流中)。

为什么我在关闭KitKat的流时遇到这种延迟? 为什么它不尊重正在设置的100ms超时?

这类似于Android KitKat HttpURLConnection断开AsyncTask – 虽然这可能是在引擎盖下使用FixedLengthInputStream ,但同样的更改已应用于该类的close方法。

这是OkHttp中的一个错误。 修复就在这里 。 如果您不介意在应用程序中包含OkHttp jar,则可以解决此问题,直到更新AOSP以包含此修复程序。

 OkHttpClient okHttpClient = new OkHttpClient(); URL.setURLStreamHandlerFactory(okHttpClient); 

OkHttp 1.3没有及时合并修复程序; 你需要等待以后的发布或自己制作jar