CodeZine(コードジン)

特集ページ一覧

Androidアプリでトレンドのキーワードからツイートを検索する

Web APIで楽々Androidアプリ(11)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2014/08/01 14:00
目次

ツイートを検索するクラスの作成

 ツイートを検索するクラスを作成します。このクラスは、AsyncTaskLoaderを継承したクラスで、トレンドを元にツイートを検索します。AsyncTaskLoaderの詳細については、過去の記事を参照してください。

OsakaTrendAsyncLoaderクラス

 クラス全体のコードは、次のとおりです。

リスト1 OsakaTrendAsyncLoader.java
public class OsakaTrendAsyncLoader extends AsyncTaskLoader<List<Status>> {

    // Twitterオブジェクト
    private Twitter twitter;

    public OsakaTrendAsyncLoader(Context context, Twitter _twitter) {
        super(context);
        this.twitter = _twitter;
    }

    @Override
    public List<Status> loadInBackground() { // (1)

        try {
            // 大阪のWOEID (2)
            int osaka = 15015370;

            // トレンドを取得する(3)
            Trend[] trend = this.twitter.getPlaceTrends(osaka).getTrends();

            // 取得したトレンドから、ランダムで1つを選択する(4)
            Random rnd = new Random();
            String q = trend[rnd.nextInt(trend.length)].getQuery(); // (5)

            // 検索文字列を設定する(6)
            Query query = new Query(q);
            query.setLocale("ja");  // 日本語のtweetに限定する
            query.setCount(20);     // 最大20tweetにする(デフォルトは15)

            // 検索の実行(7)
            QueryResult result = this.twitter.search(query);

            return result.getTweets(); // (8)

        } catch (TwitterException e) {
            Log.d("twitter", e.getMessage());
        }
        return null;
    }
}

 loadInBackgroundメソッドが、非同期に呼び出される部分です。ここにメインの処理を追加します(1)

 まずトレンドを取得します。トレンドを取得するには、TwitterクラスのgetPlaceTrendsメソッドを利用します(3)。このメソッドは、WOEIDで指定した地域のトレンド情報の上位10件分を返します。戻り値は、トレンド情報になっていますが、ここでは利用しやすいように、getTrendsメソッドを使って配列に変換しています。

 なおWOEID(Where on Earth IDentifier)とは、全国の地域に割り当てられたIDコードで、Yahoo!が定めたものです。今回は、大阪のWOEID(15015370)を指定して、大阪のトレンド情報を取得します(2)

 次に、取得したトレンド情報の配列から、Randomクラスを使って、1つだけを選択しています(4)。getQueryメソッドは、トレンド情報から、トレンドのキーワードを取得するメソッドです(5)

 最後に、取得したキーワードを使って、ツイートを検索します(7)。検索は、searchメソッドを利用します。searchメソッドの引数には、検索の条件を設定するQueryオブジェクトを指定します。ここでは、ツイートの言語と、取得するツイート数を指定しています(6)

 検索の結果は、QueryResultというオブジェクトになっています。このオブジェクトには、検索結果のさまざまな情報が付加されていますが、このアプリでは、主にツイートのテキストしか利用しませんので、getTweetsメソッドで、ツイート情報のリストを取り出しています(8)

LoaderCallbacksインターフェースを実装する

 今度は、作成したOsakaTrendAsyncLoaderクラスを利用するコードを追加していきます。

 OsakaTrendAsyncLoaderクラスは、AsyncTaskLoaderの派生クラスです。AsyncTaskLoaderの派生クラスを利用するには、LoaderCallbacksインターフェースを実装します。インターフェースの実装先は、どのクラスでも可能ですが、今回はビューを保持しているFragmentクラスとしました。

リスト2 MainActivity.javaの一部
public static class PlaceholderFragment extends Fragment
                                     implements LoaderCallbacks<List<Status>> {

    @Override
    public Loader<List<Status>> onCreateLoader(int id, Bundle args) {

        OsakaTrendAsyncLoader loader = null;

        switch (id) {
            case 0:
                // ローダーの初期化(1)
                loader =
                    new OsakaTrendAsyncLoader(getActivity(), this.twitter);
                loader.forceLoad();
                break;
        }
        return loader;
    }

    @Override
    public void onLoadFinished(Loader<List<Status>> loader,
                                                       List<Status> data) {
        if (data != null) {

            // アダプターの初期化(2)
            ArrayAdapter<String> adapter =
                new ArrayAdapter<String>(
                    getActivity(),android.R.layout.simple_list_item_1);

            // アダプターにTweetをセットする(3)
            for (Status tweet : data) {
                adapter.add(tweet.getText());
            }

            // ListViewにアダプターをセットする(4)
            ((ListView) getView().findViewById(R.id.listView1)).
                setAdapter(adapter);
        }
    }
}

 LoaderCallbacksに定義されているメソッドに、処理を追加していきます。

 まず、onCreateLoaderです。このメソッドは、ローダーが新しく作成されたときに呼び出されますので、ここではOsakaTrendAsyncLoaderオブジェクトを生成して設定しています(1)。forceLoadメソッドで、キャッシュではなく毎回実際に通信を行うようにします。

 次に、通信が終了した際に呼び出されるonLoadFinishedメソッドに追加します。このサンプルでは、フラグメントのListViewに、取得したツイート内容をセットしています。

 ListViewにデータをセットするには、アダプターと呼ばれるデータセットクラスを利用します。今回は、Stringクラスの配列を使ったArrayAdapterを利用しています(2)。なお、android.R.layout.simple_list_item_1というのは、ListViewの行表示に使われているTextViewのIDです。

 Statusのリストから、ツイートのテキストを取り出してアダプターにセットした後(3)、ListViewにそのアダプターをセットします(4)

ローディング中を表示する処理を追加する

 ツイートを取得して、ListViewにセットする処理まで追加しましたので、次にローディング中を表示する処理を追加しましょう。インターネットからツイートを取得し、表示するまでには、多少時間がかかります。このような場合には、ちゃんとバックグラウンドで処理が進行していることが、わかるようにすべきです。このサンプルでは、標準で用意されているローディング中のダイアログを表示するようにしています。

リスト3 MainActivity.javaの一部
public static class PlaceholderFragment extends Fragment
                                     implements LoaderCallbacks<List<Status>> {

    // ローディング表示用ダイアログ
    private ProgressDialog progressDialog = null;

    // ローディングダイアログの消去
    private void dialogDismiss(){
        if (this.progressDialog != null) {
            this.progressDialog.dismiss();
            this.progressDialog = null;
        }
    }
    @Override
    public void onPause() {
        super.onPause();
        // ローディングダイアログの消去(3)
        dialogDismiss();
    }

    @Override
    public Loader<List<Status>> onCreateLoader(int id, Bundle args) {

        // ローディングダイアログの表示(1)
        this.progressDialog =
            ProgressDialog
                .show(getActivity(), "Please wait", "Loading data...");
        ~中略~
    }

    @Override
    public void onLoadFinished(Loader<List<Status>> loader,
                                                       List<Status> data) {
        ~中略~

        // ローディングダイアログの消去(2)
        dialogDismiss();
    }
}

 ローディングダイアログの表示は、とてもシンプルで、ProgressDialogというクラスのshowメソッドを実行するだけです(1)

 ただ注意が必要なのは、ローディングダイアログを消去するタイミングです。一つは、通信が終了したonLoadFinishedメソッドの最後で、ダイアログの消去とオブジェクトの破棄を行います(2)

 もう一つは、通信中に画面を回転した場合にも、ダイアログの消去とオブジェクトの破棄が必要です。通信中に画面を回転すると、Activityが再起動するのですが、自動でダイアログが破棄されないため、何もしないと例外が発生します。

 それを防ぐために、Fragmentが非表示になる直前に呼び出されるonPauseメソッドでも、ダイアログの消去とオブジェクトの破棄を行っています(3)

ボタンクリックでローダーを開始する

 最後に、検索ボタンをクリックしたときに、ローダーを開始するようにします。

リスト4 MainActivity.javaの一部
public static class PlaceholderFragment extends Fragment
                                     implements LoaderCallbacks<List<Status>> {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // 検索ボタンのイベントリスナーを設定する(1)
        ((Button)getActivity().findViewById(R.id.button1))
        .setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // ローダーの開始
                getLoaderManager()
                    .restartLoader(0, null, PlaceholderFragment.this);
            }
        });
        setRetainInstance(true);
    }
}

 ボタンのクリック時に処理を行うには、イベントリスナーを設定します。サンプルでは、Fragmentの作成時(onActivityCreatedメソッド)に、setOnClickListenerメソッドで設定しています(1)。イベントリスナー自体は、OnClickListenerインターフェースを実装した無名クラスとしています。

最後に

 今回は、非同期でTwitter APIを利用し、トレンドのキーワードからツイートを検索するアプリを作成しました。次回は、Instagramから画像を検索して、表示するアプリを作成する予定です。



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Web APIで楽々Androidアプリ

もっと読む

著者プロフィール

  • WINGSプロジェクト 高江 賢(タカエ ケン)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5