Последнее время активно чиним баги и зачищаем warning-и от анализаторов. А за это время накопилось несколько довольно занятных примеров. Конечно, когда знаешь, в чем соль, то все просто и очевидно. Но в коде если не знать, то просто пропустишь как есть. Первый пример, про закрывающиеся потоки, обычная java.
stream = new ObjectOutputStream(new BufferedOutputStream(
new FileOutputStream(storageFile)));
//действия со стримом
} finally {
try {
if (strean != null) {
closeable.close();
}
} catch (IOException ignore) {
}
}
}
Это кажется, что это абсолютно безопасный код, написанный по идиомам java. С единственной оговоркой - тут должны быть try-with-resources, но в мире android-а так пока нельзя, к сожалению, если min sdk < 19: скомпилится и в 98% случаев будет работать, но в оставшихся 2% будет крешиться; и эта зависимость трудноотлавливаемая - зависимость от версии jvm на телефоне). Но в этом коде есть проблема и sonar ее радостно находит.[Ответ] Проблема возникнет, если внутренний поток FileOutputStream проинициализируется. А вот во время создания обертки произойдет любой exception. В этом случае поток останется открытым, а stream == null. Здравствуй, утечка ресурсов! Второй пример, про получение аттрибутов из кода, android. У нас в приложении есть внутренний браузер на webview. И у этого браузера есть toolbar. Задаем выстору Toolbar-а через xml: android:layout_height="?attr/actionBarSize" Но после переворота приложения мы же не хотим перезагружать activity. Поэтому не пересоздаем эту активити и указываем: android:configChanges="orientation|screenSize". Но есть одна проблема - после поворота из portrait ориентации в landscape высота toolbar-а не меняется. Это логично с точки зрения кода (ведь ничего не пересоздаем). Но нелогично с точки зрения пользователей - зачем им широкий toolbar в landscape? Тогда пишем небольшой кусочек кода:
@Override
public void onConfigurationChanged(Configuration newConfig) {
public static int getActionBarSize(@NonNull Context context) {
final int[] textSizeAttr = new int[]{android.R.attr.actionBarSize};
TypedArray a = context.obtainStyledAttributes(textSizeAttr);
final int indexOfAttrTextSize = 0;
int size = a.getDimensionPixelSize(indexOfAttrTextSize, -1);
a.recycle();
return size;
}
Это работает... Но не на 4-х android-ах! На них toolbar становится уже, чем был изначально. А в чем же проблема?[Ответ] А проблем несколько! Дело в том, что в данном коде используется системный android.R.attr.actionBarSize. Но это не правильно и корректно использовать appCompat аттрибут (как раз сделано для обратной совместимости ведь). Но при попытке заменить android.R.attr.actionBarSize на android.support.v7.appcompat.R.attr.actionBarSize видим, что возвращается дефолтное значение -1. И тут мы натыкаемся на вторую проблему: нельзя получать StyledAttributes от Context-а. Стили и темы не успевают примениться. И значения просто нет! С использованием системного аттрибута actionBarSize это работало, потому что стили там и не нужны. А теперь - нет. И правильный вариант - передавать activity в эту функцию, а не контекст.