※ こので挙げる例は性差別の議論を呼ぶかもしれませんが,あくまで説明のための例であることをご理解いただければと思います.
やりたいこと
ユーザの属性によって,リソースを切り分けたい
例
ユーザが男性なら R.drawable.man_button
女性なら R.drawable.woman_button
を選択したいとき,愚直に書けば
java
1imageView.setImageResource(user.gender == Gender.MAN ? 2 R.drawable.man_button : R.drawable.woman_button);
となりますが,この指定の箇所もリソースも多くなってくるとコードの可動性が悪くなってしまいます.
試したアプローチ
三項演算子による分岐だけをユーティリティメソッドとして共通化
java
1static class Util { 2 public static int getRes(User user, int manRes, int womanRes) { 3 return user.gender == Gender.MAN ? manRes : wimanRes; 4 } 5} 6 7imageView.setImageResource(Util.getRes(user, R.drawable.man_button, R.drawable.woman_button));
- あんまり見通しよくはなってない
Resource.getIdentifier() を使う
java
1imageView.setImageResource(context.getResources().getIdentifier( 2 user.gender.name + "_button", "drawable", context.getPackageName()));
- 参照するリソースが無い場合に,コンパイルエラーで検知できない
- 参照するリソースが unused でlintに引っかかる
・リソースを整理したい時に,消していいリソースか判断に迷う
管理用クラスを作る
java
1public class UserResources { 2 public final User user; 3 4 public UserResources(User user) { 5 this.user = user; 6 } 7 8 public int getRes(Res res) { 9 return user.gender == Gender.MAN ? res.man : res.woman; 10 } 11 12 private enum Res { 13 BUTTON(R.drawable.man_button, R.drawable.woman_button), 14 LAYOUT(R.layout.man_layout, R.layout.woman_layout), 15 STRING(R.string.man_string, R.string.woman_string); 16 17 public final int man; 18 public final int woman; 19 20 Res(int man, int woman) { 21 this.man = man; 22 this.woman = woman; 23 } 24 } 25} 26UserResources res = new UserResource(user); 27imageView.setImageResource(res.getRes(Res.BUTTON));
- リソースを追加したら管理クラスに追加しないといけないのが面倒
- リソースがライブラリ下に入っていると,ライブラリの
UserResource
と アプリのUserResource
ができて,中々にカオス
所感
- 管理用クラスを作る
が一番現実的なんですかねぇ…?
他に何かいい方法(やライブラリ)があれば教えてください.
ちょっと考えたけどフワッとしてること
アノテーションプロセッシングで何かできないか
- Resource.getIdentifier() を使う
の弱点改良版.
man_
woman_
のprefixを外したコアテキスト( button
)と種類( drawable
) を渡すと,よしなに R.drawable.man_button
をコード生成してくれるとか.
コード生成されればリフレクションと違って直接参照されるので,unused警告やリソースがない場合にコンパイルエラー検出可能なはず…?
(これが実現可能&有用そう&既存の回避策がないならライブラリ作ってみようかしら)
Kotlinの拡張関数つかうと行ける?
?
判断基準
- リソースを使用する箇所はできるだけシンプルに記述できること
・使う箇所で条件分岐はしたくない
・使う箇所のステップ数を少なく
- リソースを選択する側の仕組みも極力シンプルになるように
・リソースを追加するたびに管理クラスに手を入れずに済む方法があればベスト
これでもまだふわっとしてるのは重々承知ですが,
- リソースを使う箇所はシンプルに書きたい
- リソースが無いことをコンパイルエラーで検知したい
- unused resources なlintは出されたくない
- リソースを追加しても管理クラスに手を入れたくない
というのが要件でしょうか.
1, 2, 3はMUST,4はSHULDですが,4もMUSTにできるならその方法が知りたい次第です.