4

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

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

该问题似乎与此问题有关,围绕连接重用。这个 OkHttp 变更集(在这里被合并到 Android中)改变closeChunkedInputStream. 它不再简单地将自己标记为“关闭”,然后如果还有更多数据要读取,则断开套接字,它现在尝试首先丢弃流以启用套接字的快速重用。如果它未能丢弃流,则它会像以前一样断开套接字。

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

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

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

我已经测试了使用不同活动级别的两个 Twitter 帐户关闭流需要多长时间。第一个在我试图关闭流的时候没有看到任何活动,而且我一直看到调用大约需要 30 秒。第二个账户有更多的活动,关闭流的时间在这个账户上变化很大——从 1.5 到 30 秒不等。当有新推文进入时(新块写入流),它似乎会立即关闭。

为什么我看到在 KitKat 上关闭流时出现这种延迟?为什么它不遵守正在设置的 100 毫秒超时?

这类似于Android KitKat HttpURLConnection disconnect AsyncTask - 虽然这可能是FixedLengthInputStream在底层使用,但相同的更改已应用于close该类的方法。

4

1 回答 1

5

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

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

OkHttp 1.3 的修复没有及时合并;您需要等待以后的版本或jar自己构建。

于 2014-01-12T18:45:54.853 回答