静的コンテキスト
問題:静的コンテキストからいくつかのContextメソッドを呼び出せるようにしたい(しゃれはごめんなさい)。
解決策: stackoverflowを使用して、静的Applicationクラスを作成するというソリューションを利用しました。
ここでは、注意する必要があります-そしてそれを賢く使用してください。 たとえば、リソースを取得するには-翻訳、写真、スタイル。
使用できない場合: 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>
低レベルのアプリケーションで高レベルのAndroid APIを使用する
問題:高レベルAPIで使用可能な機能(GUI要素-ビューなど)を使用したい。
解決策: Androidはオープンプラットフォームであるため、ソースコードが利用可能です。 はい、利用できないクラスをライブラリに転送します。 当然、このアプローチには欠点があります。転送されたクラスの操作性を確認し、このレベルのAPIでサポートされていない依存関係を編集する必要があります(幸運です)。
例: NumberPickerはレベル11からのみ使用可能ですが、プロジェクトに転送してレベル4で使用します: githubを見てください
XML APIを使用する
問題: Javaオブジェクトをxml表現に変換することがしばしば必要です(たとえば、サービス間でオブジェクトを転送したり、永続化状態で保存したりするため)。
通常、このような場合はJAXBが使用されますが、AndroidプラットフォームではJAXBは使用できません。
解決策:別のライブラリーを使用してください。 たとえば、シンプル(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、 Transient 、 Element )でオブジェクトをマークします。
@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で動作するアプリケーション。
ご清聴ありがとうございました!