Intereting Posts
Пытается запустить Android-игру, используя libgdx на Genymotion Android facebook sdk опубликовать фид на временной шкале пользователя Проверьте, отображается ли мягкая клавиатура с помощью эспрессо Скрытие клавиатуры после вызова новой операции, которая показывает ProgressDialog Аудиовыход на гарнитуре и громкой связи одновременно ViewPager с фрагментами внутри PopupWindow (или DialogFragment) – ошибка не найдена для id для фрагмента Тест, если кнопка запускает новую активность в андроиде junit (pref без robotium)? Как увеличить память для Android Emulator? (INSTALL_FAILED_INSUFFICIENT_STORAGE) Как запустить контекстную панель действий для текстового просмотра программно с копиями опций по умолчанию и выбрать все? Разница между android: id, android: имена и теги имен в файлах Android XML Приложения Android OpenGL перестают работать после загрузки в эмулятор Является ли конструктором частного внутреннего класса также частным? Как установить шрифт для TextView в Android? Командная строка ADB Подвешивание во время установки (PhoneGap) Textureview onSurfaceTextureAvailable никогда не вызывается внутри relativelayout внутри фрагмента

Лучшая практика: расширение или переопределение класса проекта библиотеки Android

Мы используем проект библиотеки Android для совместного использования основных классов и ресурсов в разных сборках (целях) нашего приложения для Android. Android-проекты для каждой конкретной целевой ссылки на проект базовой библиотеки (за кулисами, Eclipse создает и ссылается на банку из проекта библиотеки ссылок).

Переопределение ресурсов, таких как изображения и макеты XML, очень просто. Файлы ресурсов, размещенные в целевом проекте, такие как значок приложения или макет XML, автоматически переопределяют ресурсы базовой библиотеки с тем же именем при создании приложения. Однако иногда класс должен быть переопределен, чтобы включить поведение, специфичное для конкретного объекта. Например, экран настроек целевых настроек Amazon не может содержать ссылку на страницу приложения Google Play, требующую изменения в предпочтениях проекта Amazon .xml и предпочтения класса Activity.

Цель состоит в том, чтобы уменьшить количество дублирующихся кодов среди целевых проектов, удалив при этом как можно больше целевого кода из основной библиотеки. Мы придумали пару подходов к реализации логики, специфичной для разных целей:

  1. Записывайте целевые функции в классы базовой библиотеки и используйте, если / переключаете блоки, чтобы выбрать поведение на основе SKU продукта. Этот подход не очень модульный и раздувает базовую кодовую базу Core.
  2. Расширьте конкретный класс Core в целевом проекте и переопределите основные функции класса (Core) по мере необходимости. Затем сохраните ссылку на объект базового класса в библиотеке Core и создайте экземпляр с расширенным объектом класса (из раздела «Как переопределить класс в проекте библиотеки Android» ) ?

Существуют ли другие стратегии для переопределения или расширения класса проекта библиотеки Android? Каковы некоторые из лучших практик для совместного использования и распространения общих классов среди целевых приложений Android?

Solutions Collecting From Web of "Лучшая практика: расширение или переопределение класса проекта библиотеки Android"

Проект библиотеки ссылается как исходная зависимость проекта (исходный механизм), а не как скомпилированная зависимость jar (механизм библиотеки, основанный на компилированном коде).

@yorkw это неверно для последних версий плагина ADT для Eclipse http://developer.android.com/sdk/eclipse-adt.html

Из версии 17 Журнал изменений

Новые функции сборки Добавлена ​​возможность автоматической настройки зависимостей JAR. Любые файлы .jar в папке / libs добавляются в конфигурацию сборки (подобно тому, как работает система сборки Ant). Кроме того, файлы .jar, необходимые для проектов библиотек, также автоматически добавляются к проектам, которые зависят от этих проектов библиотеки. (больше информации)

Дополнительная информация http://tools.android.com/recent/dealingwithdependenciesinandroidprojects

До этого обновление прошивки проекта Activity from Library было простым, просто исключите класс. Теперь библиотека включена как файл jar, и нет возможности исключить файл класса из jar-зависимости.

РЕДАКТИРОВАТЬ:

Мое решение для перезагрузки / расширения Activity из библиотеки jar:

Я создал простой класс util:

public class ActivityUtil { private static Class getActivityClass(Class clazz) { // Check for extended activity String extClassName = clazz.getName() + "Extended"; try { Class extClass = Class.forName(extClassName); return extClass; } catch (ClassNotFoundException e) { e.printStackTrace(); // Extended class is not found return base return clazz; } } public static Intent createIntent(Context context, Class clazz) { Class activityClass = getActivityClass(clazz); return new Intent(context, activityClass); } } 

Чтобы перезаписать класс «SampleActivity» библиотеки, это проект, который зависит от этой библиотеки, создайте новый класс с именем SampleActivityExtended в проекте в том же пакете и добавьте новое действие в ваш AndroidManifest.xml.

ВАЖНО: все намерения, ссылающиеся на перезаписанные действия, должны быть созданы через класс util следующим образом:

 Intent intent = ActivityUtil.createIntent(MainActivity.this, SampleActivity.class); ... startActivity(intent); 

За кулисами, Eclipse создает и ссылается на банку из проекта библиотеки ссылок.

Это не совсем точно. Проект библиотеки ссылается как исходная зависимость проекта (исходный механизм), а не как скомпилированная зависимость jar (механизм библиотеки, основанный на компилированном коде). В настоящее время Android SDK не поддерживает экспорт проекта библиотеки в автономный файл JAR. Проект библиотеки всегда должен быть скомпилирован / построен косвенно, путем ссылки на библиотеку в зависимом приложении и создания этого приложения. Когда проект, зависящий от сборки, скомпилированный источник и необработанные ресурсы, которые необходимо фильтровать / объединить из проекта библиотеки, копируются и правильно включаются в окончательный файл apk. Обратите внимание, что команда Android приступила к обновлению всего проекта Библиотечного проекта (переместите его из механизма, основанного на нашем языке, на механизм, основанный на компилированном коде) с r14, как упоминалось в этом раннем сообщении в блоге .

Каковы некоторые из лучших практик для совместного использования и распространения общих классов среди целевых приложений Android?

Решение, данное Android, – это проект библиотеки .
Решение, данное Java, – это наследование и полиморфизм .
Приходите вместе, наилучшая практика ИМО – это второй вариант, который вы упомянули в вопросе:

2. Расширьте конкретный класс Core в целевом проекте и переопределите основные функции класса (Core) по мере необходимости. Затем сохраните ссылку на объект базового класса в библиотеке Core и создайте экземпляр объекта с расширенным объектом класса (из проекта библиотеки Android – Как перезаписать класс?)

Из моего личного опыта я всегда использую проект Android Library (иногда с Regular Java Project для реализации / создания common-lib.jar, который содержит только POJO) управляет общим кодом, например SuperActivity или SuperService, и расширяет / реализует соответствующие классы / интерфейсы В зависимом проекте для полиморфизма.

Решение основано на решении PoisoneR и решении Turbo.

 public static Class<?> getExtendedClass(Context context, String clsName) { // Check for extended activity String pkgName = context.getPackageName(); Logger.log("pkgName", pkgName); String extClassName = pkgName + "." + clsName + "Extended"; Logger.log("extClassName", extClassName); try { Class<?> extClass = Class.forName(extClassName); return extClass; } catch (ClassNotFoundException e) { e.printStackTrace(); // Extended class is not found return base return null; } } 

Преимущества этого в том, что

  1. Расширенный класс может быть в пакете проекта, а не в пакете библиотеки. Благодаря Turbo для этой части.

  2. Принимая String в качестве аргумента вместо объекта Class , этот метод можно использовать даже с ProGuard. getName() – это проблема с ProGuard, так как это вернет нечто вроде «a» вместо имени исходного класса. Таким образом, в исходном решении вместо поиска ClassExtended он будет искать aExtended вместо того, чего не существует.

Как насчет использования метода callback здесь? (Хорошо, обратный вызов немного вводит в заблуждение, но в настоящее время у меня нет другого слова для этого:

Вы можете объявить интерфейс в каждой Деятельности, которая должна / может быть расширена пользователем. Этот интерфейс будет иметь такие методы, как List<Preference> getPreferences(Activity activity) (передайте все параметры, которые вам нужны здесь, я бы использовал Activity или хотя бы Context для будущей защиты).

Такой подход может дать вам то, что вы хотите, когда я правильно понял. Хотя я не делал этого раньше и не знаю, как другие люди справятся с этим, я бы попробовал и посмотрел, работает ли это.

Не могли бы вы прояснить, что отличает Kindle и обычный Android? Я думаю – они такие же. Для вас нужны разные ресурсы для Kindle и других устройств. Затем используйте соответствующий ресурс. Например, я использую 2 ссылки для хранения:

 <string name="appStore">&lt;a href=http://market.android.com/details?id=com.puzzle.jigsaw>Android Market&lt;/a> or &lt;a href=http://www.amazon.com/gp/mas/dl/android?p=com.puzzle.jigsaw>Amazon Appstore&lt;/a> &lt;br>http://market.android.com/details?id=com.puzzle.jigsaw &lt;br>href=http://www.amazon.com/gp/mas/dl/android?p=com.puzzle.jigsaw</string> <string name="appStore_amazon">&lt;a href=http://www.amazon.com/gp/mas/dl/android?p=com.puzzle.jigsaw>Amazon Appstore&lt;/a> &lt;br>href=http://www.amazon.com/gp/mas/dl/android?p=com.puzzle.jigsaw</string> 

И использовать appStore для всех продуктов Amazone и appStore_amazon для Kindle.

Как определить, где вы находитесь во время выполнения – это будет еще один вопрос, на который здесь ответили много раз.

Я был вдохновлен ответом PoinsoneR на создание класса Utility для того, чтобы сделать то же самое для Fragments – переопределить фрагмент в библиотеке Android. Шаги похожи на его ответ, поэтому я не буду вдаваться в подробности, но вот класс:

 package com.mysweetapp.utilities; import android.support.v4.app.Fragment; public class FragmentUtilities { private static Class getFragmentClass(Class clazz) { // Check for extended fragment String extClassName = clazz.getName() + "Extended"; try { Class extClass = Class.forName(extClassName); return extClass; } catch (ClassNotFoundException e) { e.printStackTrace(); // Extended class is not found return base return clazz; } } public static Fragment getFragment(Class clazz) { Class fragmentClass = getFragmentClass(clazz); Fragment toRet = null; try { toRet = (Fragment)fragmentClass.newInstance(); return toRet; } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return toRet; } } 

Применение:

 FragmentUtilities.getFragment(MySpecialFragment.class) 

Вы также можете использовать фабрику Activity, если вам нужно предоставить расширенные действия для вариантов вариантов differnt и попросите вашу библиотеку обработать только абстрактную фабрику. Это можно задать в ваших вариантах сборки.