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

Android開発 〜そんなところ自分で作る必要ないよ〜

More than 5 years have passed since last update.

マニュアルに目を通さないで、適当なブログを適当にググッて実装すると陥りやすい、「自分で書く必要のないところまで自分で実装して疲れたりバグったり」というケース。経験したものをずらずらと。

  • コードはうろ覚え
  • 会社のプレゼンの資料で作ったので精査できてない(TODO 後で整理する)

概要

  • RosourcesTypes
  • Loader
  • DataProvider

これらを使って楽をしようという話のケーススタディー的なものです

画像リソースのdpiごとの伸縮

単純に拡大縮小するだけなのに、いろんな解像度分の画像を用意して配置するやつ

Before

猫のアイコン icon_neko.pngを以下のように配置

ディレクトリツリー
res/
    drawable-mdpi/
        icon_neko.png (16x16)
    drawable-hdpi/
        icon_neko.png (24x24)
    drawable-xhdpi/
        icon_neko.png (32x32)
    drawable-xxhdpi/
        icon_neko.png (48x48)
    drawable-xxxhdpi/
        icon_neko.png (64x64)

ほんとうに必要なのか。


それ、AndroidのPreScaleでやってくれるよ。

After

ディレクトリツリー
res/
    drawable-xxxhdpi/
        icon_neko.png (64x64)
  • 一番近いdpiのリソースを自動伸縮して表示してくれる
  • pre処理なので更新のたびに毎回伸縮しているわけではないので軽い

注意点

以下の場合は頑張ったほうがいい

  • Androidの拡大縮小のアルゴリズムが気に入らない
  • 単純な拡大縮小では駄目なケース(例えば, 1pxの線は縮小されても1pxであってほしいとき)
  • ドキュメントにこの内容そのものが書いてあったわけではなく、Prescalingの説明と実動作を見た私感にすぎないので程々に疑って下さい(むしろ解像度ごとのリソースを用意することを推奨している)

参考

画面幅に応じた画面切り替え

  • 画面が狭い端末だと表示しきれないので、狭い用のlayoutをプログラムで分岐して表示させるケース
  • タブレットでは2ペイン、スマートフォンでは普通のデザインでやりたいケース

Before

HogeActivity.java
public class HogeActivity extentds Activity {

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 画面の横幅が360dp以上かどうかで表示するlayoutを切り替える
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        if(metrics.widthPixels / metrics.density >= 360) {
            setContentView(R.layout.activity_hoge_w360);
        }else {
            setContentView(R.layout.activity_hoge);
        }
    }
}
ディレクトリツリー
res/
    layout/
        activity_hoge.xml (デフォルト)
        activity_hoge_w360.xml (横360以上用)

それ、AndroidのResourceTypeの指定で出来るよ。

After

HogeActivity.java
public class HogeActivity extentds Activity {

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hoge);
    }
}
ディレクトリツリー
res/
    layout/
        activity_hoge.xml (デフォルトのlayout)
    layout-w360dp/
        activity_hoge.xml (widthが360dp以上の時に適応してほしいlayout)
  • 縦幅横幅うち小さいほうがNdpi以上のとき reources-swNdp なども可能

注意点

  • Andorid3.2未満では resource-wNdp の指定が出来ない
    • 代わりにresource-lergeなどといった名前ベースの指定を利用するしかない。

参考

バージョンに応じた処理分岐

  • このlayout指定はAPInn以上じゃないと動かないから処理を分岐して頑張ったり、警告を無効化して考えるのを辞めたりするケース

Before

HogeActivity.java
public class HogeActivity extentds Activity {
    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // APIレベルが11以上かどうかで処理を分ける
        if(Build.VErSION.SDK_INT => 11) {
            setContentView(R.layout.activity_hoge_v11);
        } else {
            setContentView(R.layout.activity_hoge);
        }
    }
}
ディレクトリツリー
res/
    layout/
        activity_hoge.xml (デフォルト)
        activity_hoge_v11.xml (API level 11をサポートしているデバイス用)

それ、AndroidのResourceTypeの指定で出来るよ。

After

HogeActivity.java
public class HogeActivity extentds Activity {

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hoge);
    }
}
ディレクトリツリー
res/
    layout/
        activity_hoge.xml (デフォルト)
    layout-v11/
        activity_hoge.xml (API level 11をサポートしているデバイス用)

注意点

  • Androidのresourceだけでは済まないレベルの分岐は、ソースコードで頑張ってやるしか無い

参考

非同期通信と画面反映

WebAPIから情報を取ってきて画面に設定するだけなのに、
AsyncTaskを定義して、Activityベースのsyncronizedを書いてロックしてなどなど頑張るケース

Before

public class HogeActivity extentds Activity {
    // ロック用
    private AsyncTask<Void, Void, String> task;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hoge);

        final TextView text = (TextView) findViewById(R.id.text1);

        assignloadtask();
    }

    // なんかのリスナー
    public void onNankaListener() {
        assignloadtask();
    }

    // ロックされてなければロード
    private synchronized void assignLoadTask() {
        if(task == null) {
            task = new AsyncTask<Void, Void, String>() {
                @Override
                protected String doInBackground(Void... params) {
                    String result;
                    // 時間のかかる通信処理
                    return result;
                }

                @Override
                protected void onPostExecute(String result) {
                    super.onPostExecute(result);
                    if(result != null) {
                        text.setText(result);
                    }
                    task = null;
                }
            };
            task.execute();
        }
    }
}

それ、Loader使えば簡単にかけるよ。

あまり短くなってないけど、ライフサイクル管理とか、再参照の時のキャッシュとか、ロックとかちゃんと書けば書けるらしい!

After

public class HogeActivity extentds Activity implements LoaderCallback<String> {

    private static final int LOADER_ID = 0;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hoge);

        final TextView text = (TextView) findViewById(R.id.text1);

        getLoaderManager().initLoader(LOADER_ID, null, this);

    }

    // なんかのリスナー
    public void onNankaListener() {
        getloadermanager().restartLoader(LOADER_ID, null, this);
    }

    @Override
    public Loader<String> onCreateLoader(int arg0, Bundle arg1) {
        return new AsyncTaskLoader<String>(getActivity()) {
            @Override
            public String loadInBackground() {
                String result = null;;
                // 時間のかかる通信処理
                return result;
            }
        };
    }

    @Override
    public void onLoadFinished(Loader<String> arg0, String arg1) {
        if(result != null) {
            text.setText(result);
        }
    }

    @Override
    public void onLoaderReset(Loader<String> arg0) {
    }
}

注意点

  • Android3.0からなので2対応の場合はサポートライブラリを使いましょう

参考

データーの更新による他の画面の更新

一覧・詳細パターンで、詳細画面でデータを更新して、一覧画面に戻ってきたら更新内容を反映してなきゃいけないやつ

他のページに解説を譲ります

サンプルを書こうとしたら、思いの外長くなりそうだったので、参考サイトに説明を譲ります。

注意点

  • 結構難しい
  • 解説ページが少ない(というよりこれを使わないで頑張る記事が多い 気がする)
  • 解説ページがSQLITEDBに対するアクセスの例ばかり
    • 個人的にRestfulAPIに相性抜群と思っているので、後で書きます!

参考

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
ユーザーは見つかりませんでした