【发布时间】:2013-12-16 20:59:08
【问题描述】:
我有一个 Android Daydream,它使用 Twitter4j 的流实现来显示推文流。这在 Android 4.2 和 4.3 上运行良好。但是,在 4.4 上,我无法快速关闭流(onDreamingStopped)。
我收到了this stacktrace,但NetworkOnMainThreadException 不是问题。
这个问题似乎与this issue 有关,围绕连接重用。 This OkHttp changeset(合并到 Android here)改变了 close 在 ChunkedInputStream 上的行为方式。它不再简单地将自己标记为“已关闭”,然后如果还有更多数据要读取则断开套接字,它现在尝试首先丢弃流以启用套接字的快速重用。如果它未能丢弃流,它会像以前一样断开套接字。
我现在得到NetworkOnMainThreadException 的原因是(正如您从堆栈跟踪中看到的)丢弃流现在尝试从流中读取。这很容易解决 - 我只是在关闭 Daydream 时将其放入 AsyncTask 并忘记它。
问题是流没有在超时设置内被丢弃。查看HttpTransport#discardStream method of the latest version of the source,它在套接字上指定了100ms 的超时时间(原始提交指定为30ms),然后尝试从流(Util.skipAll)中读取以清空缓冲区。但是,我看到BufferedInputStream.read() 调用出现了多秒的延迟。这种延迟的长度似乎有所不同。
这不是一个大问题 - 因为我现在必须从 UI 线程关闭这个流,我不会导致 onDreamingStopped 调用需要很长时间才能返回(这导致白日梦停留按返回/主页后在屏幕上很长时间 - 我最初的错误报告导致我跟随这个兔子洞)。但是,它确实会在它应该关闭后让这个连接挂起一段时间。
我已经测试了使用两个不同活动级别的 Twitter 帐户关闭信息流需要多长时间。第一个在我试图关闭流的时候没有看到任何活动,而且我一直看到调用大约需要 30 秒。第二个账户有更多的活动,关闭流的时间在这个账户上变化很大——从 1.5 到 30 秒不等。当有新推文进入时(新块写入流),它似乎会立即关闭。
为什么我看到在 KitKat 上关闭流时出现这种延迟?为什么它不遵守正在设置的 100 毫秒超时?
这类似于Android KitKat HttpURLConnection disconnect AsyncTask - 虽然这可能在底层使用FixedLengthInputStream,但相同的更改已应用于该类的close 方法。
【问题讨论】: