Несколько Проблем При Разработке Android-Приложений И Пути Их Решения

В этой статье я хотел бы представить несколько проблем, с которыми я столкнулся при разработке приложений для Android, и способы их решения.

Статический контекст Проблема: Я хотел бы иметь возможность вызывать некоторые методы контекста из статического контекста (простите за каламбур).

Решение: Я использовал решение с переполнение стека , который состоит из создания статического класса приложения.

Здесь нужно быть осторожным – и использовать его с умом.

Например, для получения ресурсов – переводов, картинок, стилей.

Где его нельзя использовать: для работы с элементами GUI или, например, с LayoutInflator (будет выдано исключение).

На практике это будет выглядеть так:

  
  
  
  
  
  
  
   

public class ApplicationContext extends android.app.Application { @NotNull private static ApplicationContext instance; public ApplicationContext() { instance = this; } @NotNull public static ApplicationContext getInstance() { return instance; } }

И AndroidManifest.xml:

<manifest xmlns:a="http://schemas.android.com/apk/res/android "> <application a:name=".

ApplicationContext"> // .

</application> </manifest>

Использование API Android более высокого уровня в приложении более низкого уровня Проблема: Я хочу использовать функции, доступные в API более высокого уровня (например, элементы графического интерфейса — представления).

Решение: Android — открытая платформа, поэтому исходники доступны.

Давайте возьмем и перенесем недоступные классы в нашу библиотеку.

Естественно, у такого подхода есть и минусы: нужно проверять работоспособность переданных классов и редактировать зависимости, которые не поддерживаются на этом уровне API (тут как повезет).

Пример: НомерПиккер Доступен только с 11 уровня, но я перенес его в свой проект и использую с 4 уровнем: посмотри на гитхабе Использование XML API Проблема: Часто бывает необходимо преобразовать объект Java в представление XML (например, для передачи объекта между сервисами или для сохранения его в состоянии персистентности).

Обычно в таких случаях используется JAXB, но на платформе Android JAXB недоступен.

Решение: используя другую библиотеку.

Например, я использовал Simple (сериализация XML).

simple.sourceforge.net Как использовать? Для начала подключим библиотеку к проекту:

<dependency> <groupId>org.simpleframework</groupId> <artifactId>simple-xml</artifactId> <version>2.6.1</version> <exclusions> <exclusion> <artifactId>stax-api</artifactId> <groupId>stax</groupId> </exclusion> </exclusions> </dependency>

Обратите внимание: для stax-api установлено исключение — иначе проект не соберётся (Android api не поддерживается) Отмечаем объекты необходимыми аннотациями (@Root, Переходный процесс , Элемент ):

@Root public class Var implements IConstant { @Transient private Integer id; @Element @NotNull private String name; @Element(required = false) @Nullable private String value; //.

private Var() { } }

Сохраняем объект в xml:

final StringWriter sw = new StringWriter(); final Serializer serializer = new Persister(); try { serializer.write(vars, sw); } catch (Exception e) { throw new RuntimeException(e); }

Получаем объект из xml:

final String value = getVarString(); final Serializer serializer = new Persister(); try { final Vars vars = serializer.read(Vars.class, value); // .

} catch (Exception e) { throw new RuntimeException(e); }

Хранение переводов (избегая зависимости от класса R) Проблема: В Android есть механизм получения переводов по идентификатору поля класса R, и где бы вы ни захотели использовать данный перевод, у вас должна быть зависимость от этого класса.

Решение: кэш переводов на уровне приложения, в котором хранятся переводы по имени и языку.

Перевод взят из статического контекста.

Пример кода:

public enum TranslationsCache { instance; // first map: key: language id, value: map of captions and translations // second mal: key: caption id, value: translation private final Map<String, Map<String, String>> captions = new HashMap<String, Map<String, String>>(); private Class<?> resourceClass; private Context context; /** * Method load captions for default locale using android R class * @param context STATIC CONTEXT * @param resourceClass class of captions in android (SUBCLASS of R class) */ public void initCaptions(@NotNull Context context, @NotNull Class<?> resourceClass) { initCaptions(context, resourceClass, Locale.getDefault()); } /** * Method load captions for specified locale using android R class * @param context STATIC CONTEXT * @param resourceClass class of captions in android (SUBCLASS of R class) * @param locale language to be used for translation */ public void initCaptions(@NotNull Context context, @NotNull Class<?> resourceClass, @NotNull Locale locale) { assert this.resourceClass == null || this.resourceClass.equals(resourceClass); this.context = context; this.resourceClass = resourceClass; if (!initialized(locale)) { final Map<String, String> captionsByLanguage = new HashMap<String, String>(); for (Field field : resourceClass.getDeclaredFields()) { int modifiers = field.getModifiers(); if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) { try { int captionId = field.getInt(resourceClass); captionsByLanguage.put(field.getName(), context.getString(captionId)); } catch (IllegalAccessException e) { Log.e(ResourceCache.class.getName(), e.getMessage()); } } } captions.put(locale.getLanguage(), captionsByLanguage); } } private boolean initialized(@NotNull Locale locale) { return captions.containsKey(locale.getLanguage()); } /** * @param captionId id of caption to be translated * @return translation by caption id in default language, null if no translation in default language present */ @Nullable public String getCaption(@NotNull String captionId) { return getCaption(captionId, Locale.getDefault()); } /** * @param captionId id of caption to be translated * @param locale language to be used for translation * @return translation by caption id in specified language, null if no translation in specified language present */ @Nullable public String getCaption(@NotNull String captionId, @NotNull final Locale locale) { Map<String, String> captionsByLanguage = captions.get(locale.getLanguage()); if (captionsByLanguage != null) { return captionsByLanguage.get(captionId); } else { assert resourceClass != null && context != null; initCaptions(context, resourceClass, locale); captionsByLanguage = captions.get(locale.getLanguage()); if (captionsByLanguage != null) { return captionsByLanguage.get(captionId); } } return null; } }

Затем вы можете использовать его, например, так:

try{ //.

} catch ( SomeException e ) { TranslationsCache.instance.getCaption(e.getMesageId()); }

Заключение Все описанное выше было реализовано на практике: Исходный код доступен по адресу github.com .

Рабочее приложение на Android Market .

Спасибо за внимание! Теги: #Android #разработка #Android #разработка #xml #java #java #ммм кофе #Разработка Android

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.