Help us understand the problem. What is going on with this article?

View・通信の処理を簡単実装できるAndroid-Queryの使い方をまとめた

More than 5 years have passed since last update.

AndroidでView周りの処理もう少し簡単に書けるようになるやつないかなと探していたらAndroid-QueryというViewと通信周りのライブラリを見つけて、試しに使ってみたら色々できそうだったので紹介してみる

感想として、個人アプリではガンガン使っていけそうな感じなので積極的に使っていきたい

特徴

  • Android 2.1以上に対応?
  • Viewの記述をシンプルにできる
  • HTTP通信が簡単に行える
    • レスポンスの型を自由に変更できるので、結果を好きに扱いやすい
    • ローカルキャッシュに対応しているので、通信処理を高速化できる
    • 非同期で処理してくれるので、自分でAsyncTask等を使う必要がない(同期処理もできるっぽい)
  • Oauth認証もできるらしい(ほとんど試してない)
  • 面倒なURLからの画像読み込みにも対応
    • ローカル・メモリの画像キャッシュに対応しているので読み込みを高速化できる

導入

どちらか好きな方で入れる

jarの場合

  1. Android-Queryのダウンロードページから最新バージョンのjarをダウンロードしてくる
  2. Androidのlibsフォルダにダウンロードしてきたjarを置く

Mavenの場合

pom.xmlにあるdependenciesの項目内に以下を追加する

pom.xml
<dependency>
    <groupId>com.googlecode.android-query</groupId>
    <artifactId>android-query</artifactId>
    <version>0.24.3</version>
</dependency>

パーミッションを追加

AndroidManifestにパーミッションを追加
場合によってはさらに増やす必要もあるけど、最低限必要になってくるのは2つ

AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Viewの簡略化

AQueryクラスを使ってViewの操作ができる
キャストする必要がなかったり、一行で複数のViewの指定ができたり便利

各クラスのAQueryの使い分け

ActivityでViewの操作をする

PhotoDetailActivity.java
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // setContetnViewでレイアウトをセットしておく
    setContentView(R.layout.activity_main);
    aQuery = new AQuery(this);
    // 色・文字サイズ・テキストの内容をTextViewセットする
    aQuery.id(R.id.activity_main_text).textColor(Color.RED).textSize(20).text("リス");
    // Buttonが押された時に実行するメソッド名を指定する
    aQuery.id(R.id.activity_main_button).clicked(this, "onButtonClicked");
}

public void onButtonClicked() {
    //ボタンが押された時にTextViewの内容が変更される
    aQuery.id(R.id.activity_main_text).text("押されたリス");
}

FragmentやAdapterで操作をする

rootになるViewをコンストラクタで渡してあげればOK

PhotoDetailFragment.java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_detail, container, false);
    aQuery = new AQuery(getActivity(), view);
    aQuery.id(R.id.fragment_detail_text).text("Fragment内でも使える");
    return view;
}

View.OnClickListenerを利用する

文字列でイベントの呼び出し制御するのやだなあと思っていたので調べてみると、ちゃんとリスナーでもいけるっぽい

http://android-query.googlecode.com/svn/trunk/javadoc/com/androidquery/AbstractAQuery.html#clicked(OnClickListener)

aQuery.id(R.id.activity_main_button).clicked(new View.OnClickListener() {
    @Override
    public void onClick() {
         aQuery.id(R.id.activity_main_text).text("押されたリス");
    }
});

画像表示

AQuery#imageで画像の読み込みができる
URL以外にもリソース・Drawable・Bitmapからの読み込みももちろん可能だが、特にこれといって特徴はないのでURLからの読み込みに絞って紹介

URL

// hoge.comのfuga.jpgを読み込んできてImageViewにセットする
aQuery.id(R.id.activity_main_image).image("http://hoge.com/images/huga.jpg");

キャッシュを利用する

AQueryのimageメソッドにbooleanを渡すだけでOK

//  image(対象のURL, メモリキャッシュ, ローカルキャッシュ)
aQuery.id(R.id.activity_main_image).image("http://hoge.com/images/huga.jpg", true, true);

読み込むサイズを指定する

画像をそのまま読み込むとOutOfMemoryで落ちる可能性があるので縮小してから読み込む必要があるけど、Android-Queryには画像を縮小して読み込む機能があるので自分で実装する必要はなし

注意点

  • 拡大不可
    • inSampleSizeによる縮小なので、指定された幅に近い値で縮小される

幅200pxで読み込む場合はこんな感じ

//  image(対象のURL, メモリキャッシュ, ローカルキャッシュ, 読み込む幅, 読み込み失敗時に表示するリソース)
aQuery.id(R.id.activity_main_image).image("http://hoge.com/images/huga.jpg", true, true, 200, 0);

高さの指定もできるようにしたい

幅と高さどちらか大きい方に適用したい場合もありそうなので何か方法はないかと思い、ソースコードを読んでみた。

わかったこと

試してないけどこんな感じで高さを最大値としたリサイズができそう
ポイントはgetResizedImageにfalseを渡している部分

ただこの記述だと読み込み失敗時の画像の差し替えができないので必要な場合はgetResizedImageがnullを返した場合に失敗時の画像に差し替える処理を加える必要がある
実際に使うなら読み込む幅のサイズやbooleanを渡す部分は、別のところで計算して渡すようにする

aQuery.id(R.id.activity_main_image).image("http://hoge.com/images/huga.jpg", true, true, 200, 0, new AbstractBitmapAjaxCallback() {
    @Override
    public Bitmap transform(String url, byte[] data, AjaxStatus status) {
        final File file = status.getFile();
        final String path = file != null ? file.getAbsolutePath() : null;
        return getResizedImage(path, data, 200, false, 0);
    }
});

ローカルキャッシュ先を変えることはできるか

気になったのでソースコード読んでみるとAQUtility#setCacheDirを使うことで自由に変更ができるっぽい
https://github.com/androidquery/androidquery/blob/master/src/com/androidquery/util/AQUtility.java#L516

ちなみにセットしたキャッシュディレクトリはここで使われてる
https://github.com/androidquery/androidquery/blob/master/src/com/androidquery/callback/AbstractAjaxCallback.java#L961

画像読み込みの感想

正直なところ、画像読み込みに関しては前に紹介したUniversal Image Loader for Androidの方が多機能でそんなに手を加える必要性もないため便利に感じた

HTTP通信

AQuery#ajaxでHTTP通信を使った処理ができる
通信は非同期で行われるため、自分でAsyncTask等を用いて実装するする必要はない

基本的には対象のURLとレスポンスの型とコールバックを指定すればOK

aQuery.ajax("http://hoge.com/api/v1/huga/animal/list.php?page=1&limit=20", String.class, new AjaxCallback<String>() {
    @Override
    public void callback(String url, String result, AjaxStatus status) {
        // APIのレスポンスが文字列で返ってくる
    }
});

レスポンスの型はなんでも指定できるが、変換に失敗した場合はnullが返ってくる

特に手を加えなくても返せる型はここ参照
https://code.google.com/p/android-query/wiki/AsyncAPI?tm=6

自分の好きな型で返したい場合はTransformerを実装したクラスをAQuery#transformerで指定してあげれば良い

Profile.java
public class Profile{
    public String id;
    public String name;             
}
GsonTransformer.java
public class GsonTransformer implements Transformer{
    public <T> T transform(String url, Class<T> type, String encoding, byte[] data, AjaxStatus status) {                    
        Gson gson = new Gson();
        return gson.fromJson(new String(data), type);
    }
}
example.java
GsonTransformer t = new GsonTransformer();
aq.transformer(t).ajax("http://hoge.com/api/v1/huga/user/detail.php?id=1", Profile.class, new AjaxCallback<Profile>(){
    public void callback(String url, Profile profile, AjaxStatus status) {
        Gson gson = new Gson();
        showResult("GSON Object:" + gson.toJson(profile), status);
    }
});

post通信がしたい

引数にパラメータを渡すだけでいける

Map<String, Object> params = new HashMap<String, Object>();
params.put("name", "dog");
aQuery.ajax("http://hoge.com/api/v1/huga/animal/add.php", params, String.class, new AjaxCallback<String>() {
    @Override
    public void callback(String url, String result, AjaxStatus status) {
        // APIのレスポンスが文字列で返ってくる
    }
});

結果をキャッシュしたい

// 15分間キャッシュする
long expire = 15 * 60 * 1000;
aQuery.ajax("http://hoge.com/api/v1/huga/animal/list.php?page=1&limit=20", String.class, expire, new AjaxCallback<String>() {
    @Override
    public void callback(String url, String result, AjaxStatus status) {
        // APIのレスポンスが文字列で返ってくる
    }
});

キャッシュを更新したい場合はexpireに-1を渡す

long expire = -1;
aQuery.ajax("http://hoge.com/api/v1/huga/animal/list.php?page=1&limit=20", String.class, expire, new AjaxCallback<String>() {
    @Override
    public void callback(String url, String result, AjaxStatus status) {
        // APIのレスポンスが文字列で返ってくる
    }
});

同期処理させたい

同期で処理したい場合はAQuery#syncを使えば良い

AjaxCallback<JSONObject> callback = new AjaxCallback<JSONObject>();           
callback.url("http://www.google.com/uds/GnewsSearch?q=Obama&v=1.0").type(JSONObject.class);
aQuery.sync(callback);
JSONObject result = callback.getResult();
AjaxStatus status = callback.getStatus();

headerに色々付けてリクエストしたい

AjaxCallback#headerにセットしてあげればOK
複数ある場合はその度にheaderを呼ぶことで追加できる

AjaxCallback<String> callback = new AjaxCallback<String>();        
callback.url("http://www.google.com").type(String.class);
callback.header("Referer", "http://code.google.com/p/android-query/");
callback.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");
aQuery.ajax(callback);

Cookieを使いたい

AjaxCallback#cookieで追加できる
複数ある場合はその度にcookieを呼ぶことで追加できる

AjaxCallback<JSONObject> callback = new AjaxCallback<JSONObject>();           
callback.url("http://www.androidquery.com/p/doNothing").type(JSONObject.class);
callback.cookie("hello", "world").cookie("foo", "bar");
aQuery.ajax(callback);

通信処理をまとめてキャンセルさせたい

キャンセルしたい場合はAQuery#ajaxCancel()を使う

このメソッドを呼ぶと裏で動いているajaxで呼ばれた処理をすべてをキャンセルすることができる
なのでActivityが破棄される時にこの処理を呼ぶと良い

通信処理を個別にキャンセルしたい

何かボタンを押されたときに特定の処理だけ止めることはできないのだろうかと思ったので調べてみたところ、AbstractAjaxCallback#abortを呼べばいけそうな気がする

chuross
AndroidとWeb開発いろいろ
https://github.com/chuross
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした