fly1tkg blog

ResourcesのInject – AndroidAnnotations

@XXXResのアノテーションはresフォルダのリソースをメンバ変数にInjectすることが出来ます。

Injectされるリソースはアノテーションの後ろにidを書くことで指定できます。idの指定が無い場合はメンバ変数名を元に決定されます。

またメンバ変数はprivate修飾子をつけるとうまく動作しません。

@StringRes

指定したIDのStringリソースをメンバ変数にInjectします

@EActivity
public class MyActivity extends Activity {
 
  // R.string.helloがmyHelloStringにInjectされます
  @StringRes(R.string.hello)
  String myHelloString;
 
  // IDの指定が無い場合メンバ変数名のhelloを元に、R.string.helloがInjectされます
  @StringRes
  String hello;
 
}

  <li>
    @ColorRes
  </li>
  <li>
    @AnimationRes
  </li>
  <li>
    @DimentionRes
  </li>
  <li>
    @DimentionPixelOffsetRes
  </li>
  <li>
    @DimentionPixelSizeRes
  </li>
  <li>
    @BooleanRes
  </li>
  <li>
    @ColorStateListRes
  </li>
  <li>
    @DrawableRes
  </li>
  <li>
    @IntArrayRes
  </li>
  <li>
    @LayoutRes
  </li>
  <li>
    @MovieRes
  </li>
  <li>
    @TextRes
  </li>
  <li>
    @TextArrayRes
  </li>
  <li>
    @StringArrayRes
  </li>
</ul>

EViewGroupについて – AndroidAnnotations

@EViewGroupはViewModelのバインディングでコードを整理出来るのでとても気に入っています

まずはViewのレイアウトを作成します。

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >

    <ImageView
        android:id="@+id/image"
        android:layout_alignParentRight="true"
        android:layout_alignBottom="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/check" />

    <TextView
        android:id="@+id/title"
        android:layout_toLeftOf="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:textSize="12pt" />

    <TextView
        android:id="@+id/subtitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title"
        android:textColor="#FFdedede"
        android:textSize="10pt" />

</merge>

TitleWithSubtitle_クラスは先ほど書いたsetTextsメソッドで簡単に文字列を変更できます

public class Main extends Activity {
 
    @ViewById
    protected TitleWithSubtitle firstTitle, secondTitle, thirdTitle;
 
    @AfterViews
    protected void init() {
         
        firstTitle.setTexts("decouple your code",
                "Hide the component logic from the code using it.");
         
        secondTitle.setTexts("write once, reuse anywhere",
                "Declare you component in multiple " +
                "places, just as easily as you " +
                "would put a single basic View.");
         
        thirdTitle.setTexts("Let's get stated!",
                "Let's see how AndroidAnnotations can make it easier!");
    }
 
}

setTexts(String, String)のように複数の引数で渡してあけることも出来るし, setModel(Model)みたいに、モデルごと渡してあげることもできるので、コントローラー側のコードがスッキリしてよい

EViewについて – AndroidAnnotations

Viewの継承クラスに@EViewをつけるとAndroidAnnotationswを使い始めることが出来ます。

<pre class="brush: java; gutter: true">@EView

public class CustomButton extends Button {

@App MyApplication application;

@StringRes String someStringResource;

public CustomButton(Context context, AttributeSet attrs) {
    super(context, attrs);
}

}

<p>
  Layout XMLの中でも利用することが出来ます
</p>

<div>
  <div id="highlighter_847993">
    <pre class="brush: xml; gutter: true">&lt;?xml version="1.0" encoding="utf-8"?&gt;

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android

android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" &gt;

&lt;com.androidannotations.view.CustomButton_
    android:layout_width="match_parent"
    android:layout_height="wrap_content" /&gt;

</LinearLayout>

    <p>
      &nbsp;
    </p>
  </div>

  <p>
    &nbsp;
  </p>
</div>

<p>
  プログラム内で利用するには以下のようにします
</p>

<div>
  <div id="highlighter_920845">
    <pre class="brush: java; gutter: true">CustomButton button = CustomButton_.build(context);</pre>

EFragmentについて – AndroidAnnotations

fragmentでAndroidAnnotations(以下AA)を利用するには次のようにします

@EFragment
public class MyFragment extends Fragment {
 
}

fragmentもActivity同様に_のsuffixが入ります。なので利用する時はMyFragment_のようにアンダースコアを追加してください。

例えばXMLで利用する場合は次のようになります。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >
 
    <fragment
        android:id="@+id/myFragment"
        android:name="com.company.MyFragment_"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
 
</LinearLayout>

またJavaのコード上では次のように利用できます

<pre class="brush: java; gutter: true">MyFragment fragment = new MyFragment_();</pre>

JsonPullParserのJsonModelを取得するVolleyのRequestをつくってみた

JsonPullParserのJsonModelを取得するVolleyのRequestをつくってみました。

Volleyとは?

Google I/O 2013で発表されたすごいAndroidの通信ライブラリ。どうすごいかは以下のリンクが参考になります。

Google I/O 2013 – Volley: Easy, Fast Networking for Android

Y.A.Mの雑記帳: Google I/O 2013 – Volley: Easy, Fast Networking for Android

JsonPullParserとは?

JSONとPOJOを相互変換するライブラリです。APTの仕組みを利用しています。

https://github.com/vvakame/JsonPullParser

つくったもの

https://github.com/fly1tkg/volley-jpp-request

使い方

Volleyと上記のレポジトリのjarにパスをとおして、あとはこんな感じです。

mQueueRequest = Volley.newRequestQueue(this);
mQueueRequest.add(new JsonModelRequest<Sample, SampleGen>(JSON_URL, new Listener<Sample>() {
    @Override
    public void onResponse(Sample sample) {
        mJsonTextView.setText(sample.toString());
    }
}, new ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        error.printStackTrace();
    }
}));

パフォーマンスとか

このライブラリは内部でリフレクションを利用しているので、若干パフォーマンスが悪いです。(気になるレベルでは無いと思いますが)

リフレクションを利用した理由としてJPPでinterfaceのimplementやクラス継承が使われておらず、Genクラスのget(string json)メソッドを呼び出しつつ、ジェネリクスを利用した柔軟なクラスを作れなかったからです。JPPのアプローチから言うと、おそらくマーカーアノテーションで指定したJsonModelに対して、VolleyのRequestをAPTで生成するというアプローチがよいと思うのですが、、、、めんどくさかったんです、、、。

ジェネリクスからリフレクションを利用する方法として、黒魔術ですが、Java変態文法最速マスターの4を利用しました。

事前準備 AndroidAnnotations

AndroidAnnotations(以下AA)のライブラリをAndroidのプロジェクトに適用する方法を説明します。

公式のWikiにはMavenやAnt、Gradleといったビルドツールを用いた方法も書かれていますが、ここでは普通のビルドツールを使わない方法を説明します。

1. ダウンロード

以下のリンクから最新版をダウンロード出来ます

https://github.com/excilys/androidannotations/wiki/Download

2. Eclipseに設定する

事前にAndroidプロジェクトのJavaの設定がjava 1.6になっていることを確認してください。

確認方法はEclipseのPackage Exploreで確認したいAndroidプロジェクトで右クリックしてPropertiesをクリック、Java compilerの項目でCompiler compliance levelの部分が1.6になっていればOKです。

先ほどのダウンロードリンクからダウンロードしたファイルのうちandroidannotations-X.X.X-api.jarをlibsフォルダに置きます

またandroidannotations-X.X.X.jarはcompile-libsなどlibsフォルダとは違うフォルダを作成して、そのフォルダに置きます

Package Exploreで確認したいAndroidプロジェクトで右クリックしてPropertiesをクリックし、Propertiesを表示します。

Java Compiler –> Annotation Processingを選択しEnable annotation processingにチェックを入れます

Java Compiler –> Annotation Processing –> Factory PathでAdd jarsボタンをクリックし、androidannotations-X.X.X.jarのパスをを入力します

ADT16以前であればJava Build Path –> Librariesでandroidannotations-X.X.X-api.jarのパスを追加してください。ADTが最新であれば問題ありません。

準備完了

これで全ての準備が完了です。AAが使えるようになります。

基本的な使い方 AndroidAnnotations

AndroidAnnotations(以下AA)の基本的な使い方を説明します。

AAの設定がされていない場合は以下のリンクを参考に設定してください。

事前準備 AndroidAnnotations | b.fly1tkg.com

公式Wiki Get Started!

@EActivityをつける

AAをActivityで使用するにはクラスに@EActivityをつける必要があります。

@EActivity
public class MyActivity extends Activity {

そしてAndroidManifest.xmlへのActivityの登録は_のsuffixが必要になります。

<activity android:name=".MyActivity_" />

これは上記の例で言うとMyActivityを継承したMyActivity_というクラスがAAによって生成され、MyActivity_で色々と便利なコードが生成されるからです。

AAでHelloWorld

次のようなコードでAAを使ったHello Worldを作成することが出来ます。

詳しくはEActivityのエントリーで説明します。

MyActivity.java

@EActivity(R.layout.main)
public class MyActivity extends Activity {

    @ViewById(R.id.myInput)
    EditText myInput;

    @ViewById(R.id.myTextView)
    TextView textView;

    @Click
    void myButton() {
         String name = myInput.getText().toString();
         textView.setText("Hello "+name);
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <EditText 
        android:id="@+id/myInput"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />
    <Button 
        android:id="@+id/myButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Click me!"
        />       
    <TextView 
        android:id="@+id/myTextView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />   
</LinearLayout>

まず@EActivity(R.layout.main)でres/layout/main.xmlのレイアウトを適用出来ます。

また@ViewById(R.id.myTextView)でmain.xmlのidがmyTextViewのTextViewのインスタンスが自動的に代入されます。これでfindViewById(R.id.myTextView)といったコードを書かなくてもよいです。

@Clickはメソッド名と同じIDのViewがクリックされたときの処理を指定しています。ここではmyButtonがクリックされた時にmyTextViewにテキストを表示することをしています。@Click(R.id.myButton)のようにIDを指定することも出来ます。

EActivityについて – AndroidAnnotations

@EActivityのアノテーションをつけることでそのActivity内でAndroidAnnotations(以下AA)が使えるようになります。以下のようにActivityに@EActivityをつけます。

@EActivity(R.layout.main)
public class MyActivity extends Activity {

}

ListActivityなどレイアウトを指定しない場合はそのままつければOKです。

@EActivity
public class MyListActivity extends ListActivity {

}

@EActivityをつけると元のクラスを継承し、_のsuffixがついたコードが生成されます。そのためAndroidManifest.xmlに登録する際は最後に_をつけます。

<activity android:name="MyActivity_"/>

IntentBuilder

EActivityではAAが使える以外に特徴的なこととして、IntentBuiderというものが自動で生成されるということです。

例えば通常ActivityにIntentする時は以下のようなコードを書くと思います。

Intent i = new Intent(this, MyActivity.class);
startActivity(i);

このIntentBuilderを使うと次のような書き方が出来ます。

new MyActivity_.IntentBuilder_(this).start();

IntentBuilderよってIntentでの値の受け渡しは、@Extraがついたデフォルトのメンバ変数に対してsetterが準備されます。

以下のようなMainActivityに遷移使用とする時

@EActivity(R.layout.activity_main)
public class MainActivity extends Activity {
    @Extra String name;
    @Extra int id;
}

Intentするためのコードは以下のようになります。

new MainActivity_.IntentBuilder_(this)
        .name("answer")
    .id(42)
    .start();

IntentのFlagもセットすることも出来ます

new MainActivity_.IntentBuilder_(this)
        .flags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        .start();