2013-11-30 6 views
4

У меня есть Android Daydream, который отображает поток твитов с использованием потоковой реализации Twitter4j. Это отлично работает на Android 4.2 и 4.3. Однако в 4.4 я не могу быстро закрыть поток (в onDreamingStopped).Невозможно быстро закрыть ChunkedInputStream на Android 4.4 KitKat

Я получаю this stacktrace, но NetworkOnMainThreadException не является проблемой.

Проблема, похоже, связана с this issue, вокруг повторное использование соединения. This OkHttp changeset (который сливается в Android here) меняет способ, которым close ведет себя на ChunkedInputStream. Вместо того, чтобы просто маркировать себя как «закрытые», а затем отключать сокет, если еще было прочитано больше данных, теперь он пытается сначала отказаться от потока, чтобы обеспечить быстрое повторное использование сокета. Если он не удаляет поток, он отключает сокет, как и раньше.

Причина, по которой я сейчас получаю NetworkOnMainThreadException, состоит в том, что (как вы видите из трассировки стека) отбрасывание потока теперь пытается прочитать из потока. Это достаточно легко исправить - я просто бросаю его в AsyncTask, когда закрываю свой меч и забываю об этом.

Проблема в том, что поток не отбрасывается в течение установленного таймаута. Рассматривая HttpTransport#discardStream method of the latest version of the source, он задает тайм-аут 100 мс в сокете (первоначальный фиксатор задан 30 мс), затем пытается прочитать из потока (Util.skipAll), чтобы освободить буфер. Однако я вижу многосекундную задержку в вызове BufferedInputStream.read(). Длина этой задержки, по-видимому, меняется.

Это не проблема, так как теперь мне нужно закрыть этот поток от нити пользовательского интерфейса, я не вызываю вызов onDreamingStopped, чтобы возвратить его (что заставило мечту остаться на экран в течение долгого времени после нажатия назад/домой - мой первоначальный отчет об ошибке, который заставил меня следовать за этой кроличьей дырой). Тем не менее, это оставляет эту связь висящей на некоторое время после того, как она должна быть закрыта.

Я проверил, сколько времени требуется, чтобы закрыть поток с двумя учетными записями в Twitter с различными уровнями активности. Первый не видел никакой активности в то время, когда я пытался закрыть поток, и я постоянно наблюдал, что звонок занимает около 30 секунд. Вторая учетная запись имеет гораздо больше активности, и время закрытия потока было намного более разнообразным на этом - от 1,5 до 30 секунд. Кажется, он мгновенно закрывается, когда приходит новый твит (новый поток записывается в поток).

Почему я вижу эту задержку при закрытии потока на KitKat? Почему он не соблюдает установленный тайм-аут 100 мс?

Это похоже на Android KitKat HttpURLConnection disconnect AsyncTask - хотя это, вероятно, используя FixedLengthInputStream под капотом, то же самое изменение было применено к close метод этого класса.

ответ

5

Это была ошибка в OkHttp. Исправлено here. Если вы не возражаете, включая банку OkHttp в своем приложении, вы можете обойти эту проблему до тех пор, пока AOSP не будет обновлен, чтобы включить исправление.

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

Исправление не было объединено во времени для OkHttp 1.3; вам нужно будет подождать более позднюю версию или самостоятельно построить jar.

+0

Спасибо, Джесси, оцените это. Будет строить и включать это сегодня, было довольно проблематично для меня в KitKat! –

+0

Это не работает для меня, к сожалению; Я вижу то же поведение, что и раньше. Я попытался построить из ветки исправлений, а также последние изменения от мастера. JDK 1.7.0_45, цель Android 4.4.2. [Мои изменения] (https://gist.github.com/adamsp/2c32ddd9d3cec1985c6a). –

+0

Я также проверил Twitter4J, чтобы узнать, установил ли он свой собственный обработчик потока; здесь пусто. Он висит на ['BufferedInputStream.read'] (https://github.com/square/okhttp/pull/430/files#diff-852ddaac3fda31af3b33f3e85ca939f0R298) вызов/ –

 Смежные вопросы

  • Нет связанных вопросов^_^