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

时间:2013-11-30 22:44:01

标签: java android okhttp

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

我收到了this stacktrace,但NetworkOnMainThreadException不是问题。

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

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

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

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

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

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

这类似于Android KitKat HttpURLConnection disconnect AsyncTask - 尽管可能是在FixedLengthInputStream下使用close,但该类的{{1}}方法也采用了相同的更改。

1 个答案:

答案 0 :(得分:5)

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

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

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