?

Log in

No account? Create an account
Спустя три тысячи километров на самолете и тридцать километров на машине я таки свернул с оживленной дороги и погрузился в тишину. Доехав до берега я остановился перед склоном и заглушил автомобиль. Наступила тишина нарушаемая только шумом деревьев и отголосками птиц. Открыв дверь машины мне в нос сразу ударил неповторимый запах. Это была помесь жгущихся тут костров, запаха леса и свежего запаха воды. Это был запах приятных воспоминаний, а так же того спокойствия и уверенности в завтрашнем дне, которые несли эти воспоминания. Выйдя из машины я закрыл её и начал спускаться по склону к воде. Спустя три года я вернулся на это место, которое для меня в свое время стало спасением. И вот теперь спустя несколько лет оно снова готово меня спасти. Вода на этот раз была спокойна и только легкий бриз напоминал что я стою около воды. Думать не хотелось, я просто стоял и смотрел в даль. Через какое-то время последние звуки стихли в моей голове и наступила абсолютная тишина. Как же я давно её не слышал. Я даже представить не мог как это важно - слушать тишину мыслей, вместо того что бы высасывать последние соки из своей головы. Убрать гул других голосов погрузиться в тишину. Спасибо случаю, что вернул меня сюда.

Как всегда инженеры Google жгут. В Android 3.0 Google полностью переделал систему рендеринга и добавили параметр hardwareAccelerated, который включает поддержку графического ускорителя, тем самым позволяя графике рисоваться быстрее, но в результате наблюдается забавный эффект. При включении hardwareAccelerated до версии 4.х перестали работать функции:



  • Canvas.clipPath
  • Canvas.clipRegion
  • Canvas.drawPicture
  • Canvas.drawPoints
  • Canvas.drawPosText
  • Canvas.drawTextOnPath
  • Canvas.drawVertices
  • Paint.setLinearText
  • Paint.setMaskFilter
  • Paint.setRasterizer


И ладно бы они пометили их как Depricated, или кидали Exception по этому поводу, так нет же. Никакой подсказки разработчикам кроме записи в блоге, что оно так работает.


А теперь хинт. Если ваш компонент при отрисовке использует указанные выше методы, то для обеспечения нормальной работы на всех устройствах рекомендуется при создании исполнить следующий код.


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && 
    Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
    setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

TODO's:

Мысли о командах

Сегодня я случайно вспомнил о двух коллективах с похожей историей, которые были популярны в 90-х и 2000 годах. Я сейчас говорю о рок-коллективах с прекрасным вокалом, а именно наша российская Ария и финская группа Nightwish. Почему для меня они похожи? Все просто.


Пик популярности Арии пришелся на 90-е годы, когда в ее составе был Валерий Кипелов - вокалист с хорошим голосом. Его голос плюс музыка, которую создавали его коллеги давал прекрасный результат. Это были песни создающие настроение. Сама харизма вокалиста давала группе многое. После их ссоры, если честно, я не могу слушать ни его сольные песни (за исключением альбома 1997 года), ни то, что исполняется сейчас новым составом Арии. В общем группы больше нет и с этим приходится смириться.


Популярность Nightwish пришлась на 1999-2004 года, когда в составе группы пела прекрасная оперная вокалистка Тарья Турунен. Она задавала характер песен. Ее голос незаложенный на "металлическое" звучание музыки со всеми ее аранжировками создали такое звучание, которое хотелось слушать и слушать. Как слушают классическую музыку в рок обработке. Так же как и в случае с Арией, группа не звучит самостоятельно, и самостоятельно не звучит вокалистка. Новая вокалистка изменила само звучание песен и перед нами предстала другая группа.


А к чему я это говорю. 2 коллектива с похожей историей со сдвигом во времени и пространстве. Я просто хочу сказать, что если мы хотим получить по настоящему прекрасные результаты в любой работе - нельзя менять коллектив. Только неизменная команда, которая срасталась годами может создавать то, что будет потрясать воображение. Любая замена в команде приводит к тому, что коллектив теряет былую силу и былые возможности. К несчастью современные руководители об этом часто забывают. Давайте растить команды и делать настоящие инновационные продукты.

Сегодня будет первая часть моего эпоса о том, как все прекрасно в мире обработки пользовательского ввода на Android. И поведаю я о том, как в Android устроен multi-touch.


Вообще, принципы multi-touch в Android простые. Есть события DOWN, UP, FINGER_DOWN, FINGER_UP, которые, я думаю, семантически понятны. (уточню только, что события с приставкой finger случаются начиная со второго пальца) Событие содержит координаты текущих пальцев, и все казалось бы хорошо, но есть одно «но». Но это кроется в алгоритме нумерации пальцев, и постигать это «но» пришлось долгими тернистыми путями. И так алгоритм.



  • Первый палец – опущенный палец всегда помечается 0

  • Каждое последующее событие о том, что коснулись новым пальцем, приходит со своим индексом. Что бы однозначно идентифицировать новый палец нам надо вставить информацию о нем в массив, сдвинув индексы пальцев, больше либо равных новому индексу на единицу. (т.е. если у нас пользователь уже прикоснулся двумя пальцами и нам поступило событие FINGER_DOWN с индексом 1, то теперь информация о состоянии второго пальца будет приходить не во второй ячейке массива, а в третьей, во второй же будет храниться информация о состоянии нового пальца).

  • Если приходит событие о том, что палец оторвали от поверхности экрана, то все аналогично, нам требуется удалить выбранный индекс, и сдвинуть следующие за ним на единицу.


Постигал я эти правила, когда делал распозновалку многопальцовых жестов при помощи декомпозиции их в параллельный поток однопальцевых. Для начала объясню, что было сложного.


Первое и третье правила я постиг за первые 10 минут анализа логов (кстати, это один из тех случаев, когда надо отправить debug туда, где ему и место) и с ними все было пучком. Я написал свой GestureDetector и начал тестировать. Когда тестирование перешло с режима предсказуемых действий в режим обезьяна (случайные движения по перестукиванию пальцами или их скольжению по поверхность) мой компонент с радостным криком грохнулся. После я раскуривал логи еще часа 3, пока до меня не дошло, что мне реально приходит событие от нового пальца, где-то, в середине списка уже зарегистрированных. Это было очень неприятным открытием. Но оно случилось и теперь вы тоже о нем знаете.


Алгоритм, конечно, кажется простым, но вот представьте, что вам требуется понять, что пользователь, зажав двумя пальцами углы вашего компонента, третьим проводит по вашему компоненту сверху вниз, и, не отпуская третьего пальца, делает быстрое движение поднятия и опускания одного из первых двух пальцев. Это только кажется эквилибристикой, но на деле, если ваш компонент обрабатывает жесты Scroll или Fling, то такое странное движение может привести к непредсказуемым последствиям, вплоть до падения приложения. И я вам гарантирую, что найдется немало пользователей, которые такое движение сделают, а потом будут считать вас «снежинками» (термин нагло сперт у cartmendum). В общем и целом – будьте внимательны, когда обрабатываете события касаний на Android.

По моим наблюдениям, 95% программистов, которые пишут программы на Android, сталкиваются с одной очень простой, и в тоже время неприятной проблемой. Итак.


Проблема: Вы написали приложение, и размещаете его в Android Market. Счастливый пользователь его скачивает и в нетерпении запускает. Поигравшись какое-то время, он сворачивает приложение, нажав стандартную для Android кнопку "Home". Через некоторое время он снова решает воспользоваться вашим приложением, запускает его, играется, и тут у него появляется непреодолимое желание поменять свое музыкальное сопровождение. Он, снова сворачивает его. Меняет музыку, и запустив обнаруживает, что приложение стартонуло с нуля. Как будто бы Android и не поддерживает понятие "приложение в фоне". Так повторяется несколько раз. Пользователь уже готов проклясть вас, за такое кривое приложение. Все расстроены.


Описание: На самом деле не все так печально, и вы написали, скорее всего, свое приложение верно. Только не учли один момент. И так. Если бы пользователь не был так нетерпелив, и после установки свернул Android Market, и удосужился запустить ваше гениальное приложение с главного экрана - у него бы не было такой проблемы. Но почему тогда, такая разница в работе? Почему в одном случае android не восстанавливает приложение, а в другом - все в порядке? И почему все зависит от того откуда запускается приложение в первый раз? Ответ оказывается очень простым. Приложение на самом деле не перезапускается. На самом деле, состояние сохранено полностью. И если пользователь, после второго запуска нажмет кнопку "Назад" он увидит в точности тот экран, с которого он ушел. По сути приложение просто снова открывает главный экран, поверх того, что уже было открыто.


Причины: Проблема кроется в том, как Android восстанавливает приложение из фона. По сути приложение не является чем-то монолитным. Каждое приложение в Android состоит из, так называемых, задачь. Если не задумываться о чем именно идет речь - то задача одна. И так, при запуске приложения (на самом деле при любом вызове startActivity(...)), Android пытается понять, какое activity ему запустить. После он определяет, к какой задаче оно относится. Если задача не запущена, то Android запускает ее, и использует текущее событие, что бы пометить его как "активационное" (это моя терминология, и не имеет ничего общего с документацией Google). Если задача уже запущена, то Android сравнивает текущее событие с "активационным" и если они совпадают, просто восстанавливает задачу. Если же события не совпали, то просто запускает новое Activity. В данном же случае многие приложения, запускают другие приложения при помощи событий отличных от событий главного экрана. Соответственно, когда мы пытаемся восстановить приложение свернутое в фон при помощи главного экрана, то если первый запуск приложения происходил не с него - нас ждут проблемы.


Решение: Я пробовал множество вариантов. У каждого есть свои достоинства и недостатки, но самым оптимальным я признал следующий. Надо просто перезапустить программу с правильным событием. Просто вставляем в самое начало onCreate() следующий код.


if (getIntent().getAction() == null || 
    !getIntent().getAction().equals(Intent.ACTION_MAIN) ||
    getIntent().getCategories() == null || 
    getIntent().getCategories().size() != 1 || 
    !getIntent().getCategories().contains(Intent.CATEGORY_LAUNCHER) ||
    getIntent().getFlags() != (Intent.FLAG_ACTIVITY_NEW_TASK | 
                                  Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)) {
        finish();
        startActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER).
                      setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 
                                   | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED).
                      setPackage(getPackageName()));
        return;
}


Он просто перезапустит приложение, если вдруг оно стартует не верно. Данный рецепт работает на всех телефонах и планшетах, с которыми я работал. Удачной вам разработки.

TODO's:

Объекты и модели

Странным образом прервалась череда недовольств по Андроиду. Ну что поделать, лень писать о том, что и так понятно.

Я все время думал, почему некоторые люди быстро пишут большие куски программы, в которых все просто и понятно, а у других получается неповоротливый монстр, который еще и работает как попало. Теперь я понял, в чем проблема. Смешно, но проблема у всех одна - не понимание основополагающих принципов ООП. Тезис простой: "Грамотно построенная объектная модель, сокращает время разработки в несколько раз". Конечно, MVC никто не отменял, но это уже техника, базовое умение правильно распределить обязанности тех или иных сущностей избавит вас от многих проблем. Не знаете, как их распределить - воспользуйтесь шаблонами и наработками старших программистов вашей компании. Соблюдение минимальных правил и правильное деление на функции - вот все, что нужно для успешной реализации View и Controller. Я, конечно, не спорю, что при написании Framework-ов для View и Controller архитектура встает в полный рост - но на то они и Framework-ки - универсальные инструменты разработчика. Я же сейчас разговариваю в рамках написания программ. Как правило, framework для работы с визуальными компонентами уже есть и на его готовой архитектуре легко писать расширения, а для слоя управления, можно применить универсальный метод, базирующийся 2-х или 3-х принципах, поэтому проблемы это не составляет, так что вернемся к модели.

Первые грабли, на которые наступают все новички - это строят модель, базируясь на формате предоставленных данных. К сожалению, данные могут быть предназначены для совершенно другого и не всегда сервисы пишутся грамотными людьми в условиях достаточного (для осознания полной картины) времени специально для вашей программы. Только выполнение этих трех условий может гарантировать вам правильную модель. Рассмотрим невыполнение каждого из условий.

  • Попался неквалифицированный специалист. Он, так же как и вы, будет писать ОМ на основе чего-то другого. Как правило, такие люди говорят что-то вроде "Мне так удобнее" или "Я не могу сделать по-другому". По сути, они навязывают вам не отвечающий требованиям вашей программы интерфейс и даже чем-то мотивируют свои недоделки. Задайте себе вопрос "Кто пишет программу? Я или он?" Наверняка, вы лучше понимаете, что именно вам нужно в данных, а что не нужно.
  • У человека нет времени. Тут все ясно. Он не будет сидеть и обсуждать с вами, как именно надо организовать модель что бы вам было проще работать. Он просто будет по факту исполнять запрос за запросом от руководителя проекта, а что получится в результате - его не волнует.
  • Сервис пишется не для вашей программы. Здесь все и так понятно. Зачем вам знать про количество оборотов на холостом ходу Toyota Camry после заправки 95 бензином, если вы пишите приложение по поиску автозаправочных станций или продаже машин.
  • Есть еще четвертый вариант - объектная модель имеет довольно сложную и не представимую в виде дерева структуру, что передать их через протокол, основанный на JSON или XML, будет довольно сложно, но тут, как правило, хотя бы, сущности выделятся верно. Другое дело, что связей нет, но это не так страшно.

Так что, лучший способ писать приложение - начинать с анализа интерфейса. Как правило, тот или иной экран в приложении не будет использовать больше 3-4 классов. Ему это не за чем. И даже если используется больше - они должны быть тесно связанны. В идеале - ссылаться друг на друга. Если экран содержит 2 разрозненные группы объектов с данными, он легко и логично бьется на 2 части, которые будут работать сами по себе и представлять 2 разных экрана. Второй момент - это Flow. В данном случае множество экранов, можно считать одним большим, который подчиняется предыдущему закону. Не забывайте о наследовании и инкапсуляции. Наследование помогает построить иерархию, объединяя классы в группы, а инкапсуляция избавит от лишних багов.

И так, чем же опасна неверная модель?

  • Контроллеры будут вынуждены постоянно конвертировать данные из одного формата в другой и обратно. Много кода будет написано по этому поводу. Зачем, если можно конвертировать только один раз.
  • Другим людям будет сложнее понять логику вашего приложения или компонента. Особенно эта проблема встречается когда визуально одни и те же данные присутствуют в разных частях модели и невозможно понять какая именно часть нам нужна.
  • Появляется множество потенциальных багов, причем как правило они размазаны по всему коду и ловить их очень сложно. Примером может служить неожиданные изменения в логике, или неправильный алгоритм преобразования данных.
  • Увеличивается количество объектов живущих в каждый момент времени, что приводит к уменьшению производительности системы в целом и крахом при малейших попытках украсить приложение новыми рюшечками или анимированным переходом. (конечно можно использовать GodObject, но номинальное количество объектов не так страшно, как страшен объем который они занимают в памяти)
  • Отсутствуют явные ссылки между объектами, что приводит к ужасным алгоритмам поиска по спискам, плюс к тому, не всегда понятно что искать.
  • Появляется большая избыточность в данных - и куча клонированных методов, которые могут образовывать страшную паутину зависимостей, что в дальнейшем вашу программу проще будет выкинуть и написать с нуля, чем выводить ее на следующий этап разработки.

Страшнее всего тем компаниям, где программисты ушли в "свободное плаванье", т.е. каждый имеет свою зону ответственности, и в нее никто не лезет, пока не настал полный ***. И тут уже есть 2 варианта развития. Первое, забиваем на все и тупо правим визуальные косяки, как можем. Если же не можем либо в дальнейшем планируется, что называется, "продолжение банкета" то выкидываем код и пишем с нуля (как правило, переиспользовать куски старого на этот момент уже нереально). Возможен и третий вариант, когда вначале титаническими усилиями TeamLead-ов мы таки доводим проект до сдачи, а потом сажаем виновников на повторное написание, предварительно прочитав лекцию длинною в несколько часов почему именно они не правы. (цензурность высказываний зависит от лектора, но я бы не советовал особо ей изобиловать в отношении тех кому собственно эта лекция предназначена)

Резюмируя то, что я сказал, добавлю следующее. При разработке любого куска приложения, сложнее "Hello World", в команде должен присутствовать опытный разработчик. И именно он должен писать объектную модель. Больше он может ничего не делать, но это решение сократит время разработки в несколько раз, а главное уменьшит шанс провалить проект.

Ну и напоследок - основные ошибки, как я их вижу.

  • "Внутренности наружу" все очень просто, структура данных не скрыта за объектной оберткой.
  • "Порочный эффект" при вызове какого-нибудь метода у объекта из модели, неявно меняется конфигурация системы.
  • "Строковая дата" поля объекта имеют не тот тип. К примеру, у объекта есть поле date, по которому они сортируются, и оно хранится в виде строки.
  • "Дубль два" появление дубликатов объектов
  • "Мы не знакомы" полное отсутствие каких-либо связей.

TODO's:

Странное дело. Год программирования на платформе привел меня к состоянию, когда обычные задачи не вызывают интереса, а на творческие нет времени. Вот и ищешь активно способы убежать от рутинной работы по подгонке графики вымерению текста и прочей подобной ерунды. Только проблема в том, что кроме тебя так же качественно ее никто не сделает. Вот и сидишь, решая рутину, которая тянет тебя вниз а не в верх. Ума не приложу, что делать с этим.
Не поверите, но я всегда считал, что в Java переменные типа int, double и иже с ними это аналоги типов в С. т.е. просто некоторая область памяти с прямой адресацией. А оказалось, что существуют и такие конструкции. int.class - т.е. с этими типами связаны некоторые классы, которые не наследуются от базового Object.

TODO's:

Андроид. Глава 2.

И так продолжим.
Значит с понятием Interface Bulder для Android разобрались. Его тупо нет. Хотя я думаю, что если бы Google задался этим вопросом в серьез, то они бы сделали его правильно и красиво. В конце-концов есть масса положительных примеров, которыми люди пользуются с удовольствием. Но не в этом дело. Мое отношение к встроенному в Eclipse IB - он просто есть. Как есть еще 1000 никому не нужных библиотек. Другое дело это Debug. Во первых, почему все пишущие на C/C++ люди так любят Breakpoint-ы? Нет, я ничего против не имею, но есть одно но, Java не особо позитивно относится к этим вещам, ибо они превращают ее в интерпритируемый язык. Да и система Exception-ов не зря придумана. И наличие StackTrace-а в них тоже не случайно. 99% ошибок Java-ского flow ловится при помощи правильного написания логов и анализа StackTrace-ов. В любом случае народ активно доказывал мне, что Eclipse круче по причине наличия в нем debug-ера. (замечу что IntelliJ Idea 9, также имеет полноценную поддержку Android со всеми Eclipse-овыми приблудами)

Резюмируя все вышесказанное заключу - для Java-ской разработки под Android не важно в какой Ide писать. Хотя если слова XML и Layout вызывают у вас легкий страх - садитесь на Eclipse. Или даже не садитесь, а изучайте как выращивать комнатные растения, а разработку приложений оставьте профессионалам.

Следующий сюрприз, с которым я столкнулся - автогенеренный класс. Я долго тупил над классом с названием R, который содержал в себе еще несколько статических подклассов. Оказалось, что это просто статически прописываемые ссылки на ресурсы, (просто гениально, и зачем придумали stream-ы и методы типа Class.getRecourceAsStream(String)) которые скармливаются всем кому не поподя начиная непосредственно с RecourceManager-а, и заканчивая медиаплеерами и прочей системной ерундой. Хорошо хоть догадались оставить классические методы. У меня тогда возник вопрос, а что делать когда надо как-то категоризировать ресурсы, ответ оказался очевиден - ничего. Ну не поддерживает платформа разбиение рисунков на подкатегории. Более того, не дай бог тебе положить ресурс с левым именем или содержанием не в ту папку. Ты будешь проклят в веках и твое приложение никогда не соберется. С одной стороны - хорошо, приучает программистов не складывать в одну кучу изображения, XML layout-а и пр ерунду, но где полное описание того, что куда можно положить, что бы этот ежик полетел? (про документацию от google поговорим позже) Где возмоность разбить графику или layout по категориям? В результате таких художественных изысков ресурсы именуются типа "about_screen_header_back_button_image_unfocused.png", что естественно не дает легко и непринужденно читать не только код, но и названия самих файлов.
В принципе, графики в проектах обычно немного и это можно пережить. (Хотя, когда приложение состаит из 3-4 независимых flow, каждое из которых насчитывает около десятка различных экранов, должен появиться легкий дискомфорт. Подобное приложение я писал на Blackberry, и эти flow я разделил изначально.) гораздо интереснее дела обстоят с ID компонентов. Представьте себе, что они тоже все складируются в единой куче. С другой стороны, кажется - зачем ноно все нужно? Зачем вообще нужны ID? Объясняю, я еще ни разу не встречал экранных форм со статическим контентом (разве что экраны с информацией о каком-то действии или приложении, или заставки в приложениях) всегда надо как-то управлять элементами, начиная от навешивания событий на нажатие кнопок, и заканчива анимированным показом слайдов. Везде надо получать ссылки на компоненты, для чего и нужны ID. А тепеь пердставьте - у вас в программе 10-15 экранов (нормальные информационные приложения насчитывают и больше) И каждый содержит 5-7 элементов, которыми надо управлять. И того минимум 50 ID падает в единую кучу. У меня не получилось вписать все имена в 20 символов. Более того, под конец я стал путаться в именованиях. Вобщем - идея хорошая, но реализация сырая до безобразия.

Продолжая разговор о ресурсах, отвечу еще на пару вопросов, которые могли бы возникнуть у нормального человека. Первое, что делать, если тебе вдруг понадобились ресурсы формата не поддерживаемого в Android. Например doc, rtf или вообще свой формат. Ответ прост. В Android проекте папка с ресурсами содержит папку raw. также плоскую папку с ресурсами, которые никак не проверяются, но при этом, так же как и остальные, имеют свои уникальные ID. (Написал и задумался, а имеют ли? Не верьте мне на слово, если нужно будет проверьте при случае.) Так же помимо res есть папка assets, куда складываются "классические" ресурсы. Все это безобразие управляется 2-мя менеджерами представленными в классах Recources и AssetManager. Но будьте осторожны, добывать эти классы стоит непосредственно из Activity, Или другого наследника Context, доступного вам. второй вопрос - доступны ли нам ресурсы самой платформы. т.е. стандартные градиенты, иконки и пр вкусности. Ответ - да, для этого есть класс android.R
Продолжение следует...

Андроид. Глава 1.

И так мои дорогие друзья. Сегодня я себя чувствую по лучше, так что напишу первую заметку.
Андроид.
На первфй взгляд, читая обзоры даешься диву. Действительно, телефон базовой операционкой на котором является Linux впечатляет. А приправленность этой сладости еще и тем, что писать приходится не на низкоуровневых C/C++, а на полноценной Java-машине, создает впечатление рая на земле. Причем, то, что писалось и рассказывалось окружающими создало впечатление, что писать на всей этой ерунде будет одно удовольствие. Сами посудите.

  • готовый встроенный в платформу язык описания интерфейса, который базируется на XML и имеет довольно неплохой набор разных компонентов и layout-менеджеров (к слову будет сказанно, я так и не освоил до конца дао писания на свинге, по причине непонимания представленного в нем набора layout алгоритмов)
  • Полноценная JVM версии 5 или 6. С reflection, auto-boxing, generic, for-each и пр вкусностями. (как потом выяснилось JVM нифига не принадлежал Sun, а был написан "в стенах" Google)
  • Полная кастомизация всего, включая приложение для телефона. (что сейчас мне представляется несколько сомнительным)

Ну что еще нужно? Ощущение рая наивысшее. Но такой уж у меня характер, если все кричат "круто", я всегда ищу подвох. Ну не бывает идеальных SDK. Тем более когда им всего ничего. И так, с чувством легкой тревоги я таки скачал SDK и принялся постигать новые для меня горизонты.
Первое, что как всегда меня взбесило, это идолопокланине этой проклятой IDE основанной на Eclipse SDK (для тех кто не в курсе, Eclipse - это не IDE, а SDK для написания различных IDE).
Я не буду вдаваться в подробности Keymap-ов и прочих мелочах, которые по сути являются делом привычки. Просто у IntelliJ есть ряд фич, которые не предоставляются Eclipse. И самой главной из них, является удобный просмотрщик сигнатуры скомпиленного класса. Без нее я бы помер уже давно. Но это не по теме.
Так вот, просочился слух, что месте с плагином к SDK Google предоставляет...(барабанная дробь) вы неповерите - Interface Builder. Это магическое сочетание взвало бурю оваций и беспричинного мочеиспускания среди моих коллег. Сам я к данным вещам всегда был равнодушным по нескольким причинам.

  1. Принципы layout-а сводят на нет удобство его использования, по причине того, что зачастую компонент располагается не там где мы хотим, а там где решит контейнер.
  2. Я ужасно не люблю мышь, и при наличии легочитаемого (как в принципе и есть в android-е) XML-я предпочитаю его. (в 90% случаев это ускоряет процесс раза в полтора)
  3. Такой инструмент очень быстро отупляет, поскольку человек перестает понимать то, как все это устроено внутри (но это уже из разряда "суровых" программистов)

Опуская разговор, который произошел между нами (Замечу лишь, что каждая из сторон оказалась по своему права и неправа). Я таки ознакомился с тулзой, которая гордо имеавалась почетным званием Interface Builder.
Впечатление отрицательное по всем показателям.

  1. Тулза полностью заточена на мышь. Даже кнопка <delete> не работает.
  2. Все параметры задаются в ручную в списке (ориентироваться по которому не сахар, скажу я вам)
  3. Тулза позволяет делать ошибки, после которых графическому интерфейсу становится не очень хорошо, и приходится лезти и править руками XML.
  4. Выходной формат, как и ожидалось - тот что используется по всему SDK. (Имеется и обратная совместимость.)
  5. Тулза, как потом выяснилось, не поддерживает понятие стилей и тем. А при наличии ссылки на XML какого-нибудь изображения (например градиента) не умеет его загрузить.

Собственно все как и подсказывала мне интуиция и опыт.
Продолжение следует...