WEBサーバーから取得したJSONデータを複数表示 手順3

Android開発

手順3、TextViewで文字列を表示してみる

ViewHolderを利用するとViewを使い回せてメモリの消費量が押さえ
・・えぇい やかましい!
今は表示出来るようになる、という所に重点を。

複数のデータを決まったフォーマットで縦に並べてくれる「ListView」に「ArrayAdapter」で「add」した項目を「ViewHolder」を用いてview形式を保持しながら表示させると、スクロールバーも自動ででるしメモリ対策にもなるので便利。。ということで当初はそのように開発してみたものの、後々にうまく出来ないところが他出しダメでした。

ListViewは単純に3項目くらいのテキストの表示項目をリスト表示するのにはとても便利かもしれませんが、今回のように1記事あたりに複数のテキストデータと複数の画像を表示しなければならない場合は、子ビュー(サブビュー)を記事テンプレートとしてメインビューにaddviewで下部に追加していく方法で実装してみようと思います。

子ビューの作成

1記事毎のレイアウトファイルを新規作成します。

layout/hogehoge_sub.xml というファイル名にしよっと。

 

<?xml version=“1.0” encoding=“utf-8”?>
<LinearLayout
    xmlns:android=“http://schemas.android.com/apk/res/android”
    android:orientation=“vertical”
    android:layout_width=“wrap_content”
    android:layout_height=“fill_parent”
    >
    <TextView
        android:id=“@+id/itemId”
        android:layout_width=“fill_parent”
        android:layout_height=“wrap_content”
    />
    <TextView
        android:id=“@+id/itemTitle”
        android:layout_width=“fill_parent”
        android:layout_height=“wrap_content”
    />
    <TextView
        android:id=“@+id/itemDetail”
        android:layout_width=“fill_parent”
        android:layout_height=“wrap_content”
    />
    <TextView
        android:id=“@+id/itemIcon”
        android:layout_width=“fill_parent”
        android:layout_height=“wrap_content”
    />
    <TextView
        android:id=“@+id/itemImage”
        android:layout_width=“fill_parent”
        android:layout_height=“wrap_content”
    />
</LinearLayout>
 
 
 

手順1の記事データを画面に表示してみます。

HogehogeActivityを修正

では先ほど作った子ビューを使い画面に表示する処理をHogehogeActivity.javaに追加していきます。
赤字の部分が追加したコードです。
 
 
package jp.example.hello;
 
import java.io.IOException;
 
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
 
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
 
public class HogehogeActivity extends Activity {
 
    private static final String LogTag = “HogehogeLog”;
    private ProgressDialog dialog;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hogehoge);
 
        // jsonを取得して解析する
        LoadTask();
    }
 
    private String makeApiUrl(){
        return “http://akamako.com/blogger/sample.php”;
    }
 
    private void LoadTask(){
        // ProgressDialogを作成
        dialog = new ProgressDialog(this);
        dialog.setMessage(“Connect to Server.”);
        dialog.setCancelable(true);
        dialog.show();
 
        try{
            String apiUrl = makeApiUrl();
 
            // コンソールログに出力
            Log.d(LogTag+” apiUrl”,apiUrl);
 
            HttpGet get = new HttpGet(apiUrl);
            HttpClient DefaultHttpClient = new DefaultHttpClient();
            HttpResponse response = DefaultHttpClient.execute(get);
 
            // ステータスコード
            int status = response.getStatusLine().getStatusCode();
            Log.d(LogTag+” status”,String.valueOf(status));
            if (status != HttpStatus.SC_OK) {
                throw new Exception(“Error!”);
            }
 
            // 結果を取得
            String source =    EntityUtils.toString(response.getEntity());
 
            Log.d(LogTag+” source”,source);
 
            // JSONObject という型があるんだって
            JSONObject json = new JSONObject(source);
 
                if (json.get(“items”) == JSONObject.NULL){
                    throw new Exception(“Error!”);
                }
                if (json.get(“count”) == JSONObject.NULL){
                    throw new Exception(“Error!”);
                }
 
            // 記事データ
            JSONArray items = json.getJSONArray(“items”);
 
            // 記事の数
            String count = json.getString(“count”);
 
            if(count.equals(“0”) == true){
                // 記事データが無かったお
            }
 
            // items の中身の数
            int maxI = items.length();
 
            LinearLayout layout = (LinearLayout) findViewById(R.id.hogehoge_layout);
 
            for(int i = 0; i < maxI; i++) {
                // 1つ取り出す
                JSONObject item = items.getJSONObject(i);
                // 表示項目を初期化
                String itemId = “”;
                String itemTitle=“”;
                String itemDetail=“”;
                String itemIconUrl=“”;
                String itemImageUrl=“”;
                if(item.has(“id”)) {
                    itemId = item.getString(“id”);
                }
                if(item.has(“title”)) {
                    itemTitle = item.getString(“title”);
                }
                if(item.has(“detail”)) {
                    itemDetail = item.getString(“detail”);
                }
                if(item.has(“icon”)) {
                    itemIconUrl = item.getString(“icon”);
                }
                if(item.has(“image”)) {
                    itemImageUrl = item.getString(“image”);
                }
                Log.d(LogTag + ” itemId”, itemId);
                Log.d(LogTag + ” itemTitle”, itemTitle);
                Log.d(LogTag + ” itemDetail”, itemDetail);
                Log.d(LogTag + ” itemIconUrl”, itemIconUrl);
                Log.d(LogTag + ” itemImageUrl”, itemImageUrl);
 
                // layout/hogehoge_list.xml が1記事のテンプレートです
                View view = getLayoutInflater().inflate(R.layout.hogehoge_sub, null);
                layout.addView(view);
 
                // 各表示項目のスキーマ(?)を取り出す
                TextView itemId_v = (TextView) view.findViewById(R.id.itemId);
                TextView itemTitle_v = (TextView) view.findViewById(R.id.itemTitle);
                TextView itemDetail_v = (TextView) view.findViewById(R.id.itemDetail);
                TextView itemIcon_v = (TextView) view.findViewById(R.id.itemIcon);
                TextView itemImage_v = (TextView) view.findViewById(R.id.itemImage);
 
                // 該当の表示個所に当て込む
                itemId_v.setText(itemId);
                itemTitle_v.setText(itemTitle);
                itemDetail_v.setText(itemDetail);
                itemIcon_v.setText(itemIconUrl);
                itemImage_v.setText(itemImageUrl);
            }
            // 接続を解除する
            DefaultHttpClient.getConnectionManager().shutdown();
        }
        catch (ClientProtocolException e){
             Log.d(LogTag + ” ClientProtocolException”, e.getMessage());
        }
        catch (IOException e){
            Log.d(LogTag + ” IOException”, e.getMessage());
        }
        catch(Exception e){
            Log.d(LogTag + ” Exception”, e.getMessage());
        }
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

・動作確認3

なぜかプログレスダイアログが表示されませんが、

記事のデータが画面に出力されました! わーい!

サーバーに通信してから画面表示するまでの数秒間、プログレスダイアログ(グルグル回るダイアログ)を表示したいのですが、表示されないのはUIスレッドでメインの処理を行っているからだそうです。

本当は、というか推奨としては、UIスレッドではHTTP通信を行うべきではないらしいので、追々直して行こう。
まずは表示できて嬉しいね。

補足)
強制終了してしまう場合はLogCatでエラーログを確認してみると

E/AndroidRuntime(  372): java.lang.NullPointerException

こんなエラーを頻繁に見かけます。
これは略してヌルポと呼ばれるエラーで、定義されていないオブジェクトを代入しようとしたりするとエラーになるようです。
ループ処理の中のjsonデータが空だったり、オブジェクトが生成されていない等が考えられます。
どこでそのエラーが起きているか?を調べるには
Log.d(“test abc”,”abc”);
というデバッグログ1行をソースコードに記述し、ログが出力されるかどうかを調べます。
該当のアクティビティを実行したときにLogCat上に
D/test abc(  768): abc
というデバッグログが出力されればていればその場所は通過しているという事になります。
少しずつ後の方に記述を持って行き、デバッグログが出力されなくなったら、その直前の処理に何か問題があるということになります。
あとはGoogle先生に聞いてエラーを潰します。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です