Pull to refresh

Comments 47

Я тоже недавно начала заниматься разработкой под Android. Многое разумно и нравится, что-то бесит (в частности поворот экрана), но больше всего меня убила бага, которая с Android на связана вообще. Эту беду я откапывал 3 часа:

String s1 = "123";
String s2 = "123";
write(s1 == s2); // false

Собственно, оказалось что Java, будучи языком архи-высокого уровня, не перегрузила оператор == для строк, и сравнивает ссылки. Я понимаю почему в С такая шутка вернула бы false, но от Java не ожидал.

Вывод очень прост, перед тем как учить Android, учите Java)
да, учите Java! String — это объект же! если хотите сравнить объекты — используйте метод equals(..). Вас, наверное, позабавит ещё такой пример:

Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a==b);
System.out.println(c==d);

если поймёте, почему в консоль выводится именно то, что выводится — в несколько раз повысите своё знания явы
String — это объект же!

Qt / C++:
QString s1 = "123";
QString s2 = "123";
write(s1 == s2); //true

Истинна, и пофиг, что QString объект. Того-же мнения C#, и большинство того с чем я работал.

Другими словами, это не так очевидно, как вы об этом говорите. Перегрузку операторов никто не отменял. И честно говоря, я так и не понял, почему в Java сделано именно так.
Перегрузку операторов никто не отменял

В яве никогда не было перегрузки операторов. Java — это не C++, и даже не C#
Внезапно. Это многое объясняет.

Да прям уж в несколько раз:-)
UFO just landed and posted this here
Это азы Java, но с неизменяемостью никак не связано.

1. Если бы строки были изменяемымы (тьфу-тьфу-тьфу), equals и == работали бы так же, как сейчас. Для примера см. java.util.Date.

2. В тех языках, где строки иммутабельны, а == используется для проверки равенства объектов (а не равенства ссылок, как в Java), вернулось бы true.
UFO just landed and posted this here
> Как раз поведение в итоге связано, строки везде используются, и если они иммутабельны тогда их легко оптимизировать в JVM, а так как это еще и объекты, то == не работает как в С++.

Поведение == в Java одинаково для всех объектов, независимо от того, мутабельны они или нет. Поэтому мне непонятно, в каком смысле поведение == в приведённом изначально примере связано с их иммутабельностью. Если бы Вы сказали «это связано с тем, что строки — объекты», возражений у меня не было бы.

Насчёт вопроса 1: они ещё нужны при взаимодействии с нативным кодом. И первые версии компилятора вряд ли смогли бы хорошо оптимизировать работу с обёртками.

Насчёт 2 Вы же сами правильно сказали: если бы String можно было расширять, то возможности его оптимизировать сильно уменьшились бы. Плюс потенциальные проблемы с безопасностью и т.д.
Не поймите меня не правильно. Суть моего комментария сводится к тому, что нужно учить Java, а то будет LOL, как в моем случае.
да всё ок, не ошибаются только те, кто ничего не делает
String s1 = "123";
String s2 = "123";

В этом конкретном случае как раз s1 == s2 будет true. Строка «123» попадет в пул констант и обе переменные s1 и s2 будут ссылаться на одну и ту же строку. Где только про это не написано…
Ну конкретно этот случай я не проверял, просто пытался объяснить суть проблемы. Может много где и написано, но я то не читал…
А в Android так же? Спрашиваю потому, что там dalvikVM, совсем не Sun JRE или OpenJDK jre.
Спасибо за статью, но я не совсем согласен, что везде нужно try-catch использовать. Проблему разрушения активити в ходе асинхронного запроса можно решить использованием паттерна подписчик и сервисов
Да, я согласен, что можно решить и подписку и сервис (что кстати еще больше увеличит количество кода). Я не совсем имел в виду что везде надо использовать try/catch (я там как раз и написал что кое-где это некрасиво, но решает проблему). Я больше имел в виду что поломаться может все, даже то на что сразу не подумаешь (системный web browser например), поэтому это надо пытаться учитывать и добавлять дополнительную обработку. А try/catch тут как самый простой (но не всегда самый верный) путь.
пересоздание активити при повороте вполне логично с учетом того, что часто активити используют разные разметки для разных ориентаций экрана. то есть, в таких случаях, при повороте необходимо реинфлейтить интерфейс.

для сложных задач используйте сервисы вместо асинктасков. асинктакс для очень быстрых и легких операций (загрузить одну мелкую картинку к примеру).

«android.view.WindowManager$BadTokenException: Unable to add window — token» у вас вылетает потому что контекст активити, на который ссылается прогресс диалог стал невалидным (активити выгрузилась из памяти). это довольно частая ситуация в системе и она проявляется не только при поворотах. еще входящий звонок, нехватка памяти устройства и еще куча всего. такое надо обрабатывать.

И еще совет вам. Вместо того, чтобы собирать сообщения об ошибках у пользователей, а потом оборачивать их в try/catch, пишите модульные и интеграционные тесты, используйте CI сервера и тестируйте поведение вашего приложения во всех ситуациях, включая повороты, заранее.
дак кто против того чтобы разметку экрана поменять при повороте? Пусть layout заново отработает. Но зачем все Activity пересоздавать — вот это вообще не понятно. Так как оно не только UI содержит но и его состояние (ну там например может содержать на каком месте в тексте курсор стоит и т.д.). Я все равно не вижу смысла все пересоздавать.

А про использование сервисов — дак я уже писал. Мне все-лишь надо из базы поднять 10-20 записей на экран. И почему для этого я должен сервис делать и кучу кода писать для этого? По моему — дак это и есть легкая операция.

И вот отказываться от сбора ошибок у пользователей и надеяться что ваши тесты покроют все варианты железа и софта — это уж нет… Сами так делайте. Я против тестов ничего не имею, но это совсем разные вещи и они только дополняют друг друга, а не заменяют.
на новой разметке вашего текста с курсором может уже и не быть. Поэтому на мой взгляд пересоздание обосновано. Особые состояния API позволяет сохранять без проблем.

Я не говорил отказываться от сбора ошибок. Просто если б вы покрыли ваш код тестами, все вышеперечисленные ошибки вы ьы выловили до релиза.

Для вытягивания записей из базы в подобных случаях рекомендую CursorLoader.
Часто бывает layout абсолютно другой (может даже кнопки другие), а у вас в onCreate к кнопкам listener вешаются. Или вы их предлагаете в onResume делать?
Если у вас не используются разные layout'ы для различных ориентаций экрана, то можно использовать достаточно простой (и неочевидный хак) – в манифесте для активити указать android:configChanges="orientation|keyboardHidden"
что значит хак и почему неочевидный, если об этом в документации написано .
Потому что просто «orientation» не работает. Хотя, согласно документации, этого должно было бы хватить.
поясните пожалуйста вашу мысль. orientation где? В configChanges у меня всегда прекрасно работало без нареканий.
Я не знаю, что у вас работало, но только что создал новый проект для 2.2. Добавьте в onCreate строку Log.d("dd", "Activity created");, в манифест android:configChanges="orientation" и поменяйте ориентацию в эмуляторе и посмотрите в лог. У меня оно пересоздается.
хм. на эмуляторе действительно ведет себя как вы сказали. На Desie и Huawei IDEOS (оба с 2.2) работает как надо. Кроме как на эмуляторе наблюдали проблему еще где-нибудь?
Я наблюдал, на Samsung Galaxy Tab 7" как на прошивке 2.2 так и на 2.3… Столкнулся когда писал свою программу, в итоге — сделал таки корректный отлов поворота и восстановление текущего состояния приложения после перерисовки.
На моторе с клавиатурой (дроид вроде первый).
Несколько общих наблюдений.

1) Не используйте ProgressDialog. Вообще. Он блокирует UI (а если нет, то что будет, если юзер нажмет назад, диалог уйдет, а данных нет и отображать нечего? – user interaction сломан), если вы в фоне что-то грузите, то работать с ним еще неудобнее. Замените его элементом UI вашей активити: надо подгрузить данные – отобразите progress bar, данные подгружены – замените layout на другой, с данными. Используйте индикатор в заголовке окна приложения.

2) Android Annotation реально упрощают жизнь и уменьшают кол-во строк кода. На производительности не сказывается, т.к. они все compile-time. С внедрением их в проект все AsyncTask'и были выброшены.

3) RoboGuice – тут исходя из задачи, но посмотреть стоит.
Спасибо за советы. ProgressDialog нам самим не нравится, надеемся его заменить в будующем. И Android Annotation вещь интересная… Похоже действительно могут упростить создание сервисов.
Вот только сегодня прочитал «Getting started» на developer.android.com. Потратил часа полтора. Половина проблем из данной статьи (о повороте экрана, о поддержке фич в разных версиях) там обсуждается. Разве это «подводные камни» — если о них пишут на пятой странице руководства новичка, сразу после создания «Hello world»?
Открыл для себя, на удивление, очень недавно. Читаем очень внимательно, все просто и прекрасно :) теперь. А именно: Fragments и Loaders
Простите, но сохранения лоадеров при пересоздании фрагмента и активити, плюс еще сохранения инстанца фрагмента, для меня это просто праздник.
UFO just landed and posted this here
У нас из 10-15 ошибок что вообще нашлись с начала размещения в маркете только 2 видны там (т.е. пользователи их туда засабмитили). Так что всю основную информацию об ошибках мы имеем именно благодаря ACRA.
UFO just landed and posted this here
ACRA собирает ВСЕ ошибки, независимо от того, нажал юзер кнопку «Отправить» или нет.
Чем мне нравится программировать для Андроид (пока что), так это тем, что нет еще громоздких фреймверков, огромных библиотек и т.п. (ну типа там WPF всякого) — процесс ближе к «олдскульной» разработке времен Borland C++ 3.11. Но, думаю, не долго осталось:)

А что касается статьи — подводными камнями это назвать трудно. Даже на «особенности» не тянет, я б сказал — «общеизвестные моменты в разработке под Андроид»
Комуто общеизвестно, а новичкам пользительно. Спасибо за статью.
Вы говорите про то, что у пользователя была версия Android 2.1. Но ведь можно в AndroidManifest указать минимальную версию SDK, которую Вы поддерживаете. А если уж поддерживаете 2.1, то мне кажется, что в эмуляторе эту проблему можно было бы увидеть.
Only those users with full accounts are able to leave comments. Log in, please.