2.7. メイン画面のリスト表示

サンプルアプリである「メモアプリ」の、メイン画面のリストに保存したメモの内容を表示する処理ににいて説明します。
前回、編集画面で入力された内容をファイル保存する処理を作成したので、 メイン画面では画面表示するタイミングで、保存したファイルの内容をリストに一覧表示する処理を行います。
(このタイミングでアプリ起動時、編集画面からメイン画面に戻るときに処理を行うことができます。)

メイン画面でのリスト表示イメージ
ここで必要になる処理としては、以下の3つとなります。
・ メイン画面が表示されるタイミングでのイベント処理
・ ファイル読み込み処理
・ ListView へのデータ設定処理

それぞれについて説明していきます。

メイン画面が表示されるタイミングでのイベント処理

メモアプリのメイン画面で、保存されたファイルの内容をリストに一覧を表示(更新)する処理は、 アプリ起動時と編集画面からメイン画面に戻るタイミングで行う必要があります。
Android アプリの画面 (Activity) が表示(再表示)されるタイミングで処理を行うには、Activity クラスの onResume メソッドで行います。
このイベントを処理す部分は以下のようになります。

@Override
protected void onResume() {
    super.onResume();

    // ここでファイルを読み込み、リスト表示処理を行う
}

この onResume メソッドをオーバーライドすることで、画面が表示されるタイミングで処理を行うことができます。
これについて詳しく知りたい方は、Activity のライフサイクルについて を参照してみてくだい。

ここにファイル読み込み処理を追加していきます。

ファイル読み込み処理

Android アプリでファイル読み込みを行う処理を追加していきます。
編集画面で、アプリ専用のデータ保存フォルダにファイル保存したので、このフォルダかのファイル読み込み処理を行います。

まず、フォルダにあるファイル一覧を取得し、そのファイルを順次読み込んでいきます。
アプリ専用のデータ保存フォルダを取得するには、Activity クラスの getFilesDir メソッドを使用します。
そして、このフォルダにあるファイル読み込みは、 Activity クラスの openFileInput メソッドを使用します。

onResume メソッド内で行う、ファイル読み込み処理は以下のようになります。

@Override
protected void onResume() {
    super.onResume();

    // アプリの保存フォルダ内のファイル一覧を取得
        String savePath = this.getFilesDir().getPath().toString();
        File[] files = new File(savePath).listFiles();
        // ファイル名の降順でソート
        Arrays.sort (files, Collections.reverseOrder());
        // テキストファイル(*.txt)を取得し、ListView用アダプタのリストにセット
        for (int i=0; i<files.length; i++) {
            String fileName = files[i].getName();
            if (files[i].isFile() && fileName.endsWith(".txt")) {
                String title = null;
                String content = null;
                // ファイルを読み込み
                try {
                    // ファイルオープン
                    InputStream in = this.openFileInput(fileName);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
                    char[] buf = new char[(int)files[i].length()];
                    // タイトル(1行目)を読み込み
                    title = reader.readLine();
                    // 内容(2行目以降)を読み込み
                    int num = reader.read(buf);
                    content = new String(buf, 0, num);
                    // ファイルクローズ
                    reader.close();
                    in.close();
                } catch (Exception e) {
                    Toast.makeText(this, "File read error!", Toast.LENGTH_LONG).show();
                }
                
                // TODO : ListView用のアダプタにデータをセット
            }
        }
}

まず、getFileDir メソッドで、保存フォルダを取得します。
そして、File クラスを使用して保存フォルダにあるファイルの一覧を取得し、ファイル毎に処理を行っていきます。
ファイルの読み込みには、InputStream と BufferdReader を使用します。
Activity クラスの openFileInput メソッドを使用して、アプリの保存フォルダにあるファイルを開きます。
あとは、BUfferdReader クラスを使用してファイルの内容を読み込みます。
1行目にタイトル、それ以降に内容、というルールで保存しているので、この通りに読み込みを行います。

次に、ここで読み込んだ内容を、ListView に設定し、画面表示する処理を追加します。

ListView へのデータ設定処理

先ほど読み込んだファイルの内容を、ListView に設定して表示する処理を追加します。
ListView にデータを設定するには、アダプタ(adapter) を使用する必要があります。
メモアプリでは、ListView にタイトルと内容の2つのテキストを表示したいので、アダプタは以下のようになります。
(mList, mAdapter は、クラスのメンバ変数に追加しておきます。)

// ListView 用アダプタのリストを生成
mlist = new ArrayList<Map<String, String>>();

// ListView 用アダプタを生成
mAdapter = new SimpleAdapter(
        this,
        mlist,
        android.R.layout.simple_list_item_2,
        new String [] {"title", "content"},
        new int[] {android.R.id.text1, android.R.id.text2}
        );

// ListView にアダプターをセット
ListView list = (ListView)findViewById(R.id.listView);
list.setAdapter(mAdapter);

まず、実際にメモの内容を保存する ArrayList を生成します。 ArrayListのデータは Map とし、入力されたタイトルと内容をマップ(キー:title, content)に格納するものとします。
次に、ListView に設定するアダプタを生成します。
このアプリで使用する ListView のアダプタには、SimpleAdapter というものを使用します。
第1引数にはメイン画面、第2引数にはこのアダプタに設定するデータを格納する List を設定します。
第3引数には、ListView に表示するレイアウトを指定します。2行表示のレイアウトは、Android で標準で用意されている android.R.layout.simple_list_item_2 がありますので、これを設定します。
第4引数には、ListView に表示するマップのキーを設定します。1 行目のテキストのキーは title、2 行目のテキストのキーは content とします。
第5引数には、各項目のレイアウトの id を設定します。 レイアウトに android.R.layout.simple_list_item_2 を設定したので、この中で定義されている id の text1、text2 を設定します。

最後に、作成したアダプタを ListView に設定します。

上記設定を行うことで、ListView へのデータ表示ができるようになります。
後は、上記で作成した mList にデータを追加していきけば、ListView にデータが表示されます。
(データ追加後に、ListView を更新するために、アダプタの notifyDataSetChanged メソッドを呼ぶことで表示更新されます。)

ここまでで説明した内容の追加部分は、以下のようになります。
(import、メニュー処理、ファイル読み込み部分は省略します。)

public class MainActivity extends Activity {
    // ListView 用アダプタ
    SimpleAdapter mAdapter = null;
    // ListView に設定するデータ
    List<Map<String, String>> mList = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // ListView 用アダプタのリストを生成
        mList = new ArrayList<Map<String, String>>();
        
        // ListView 用アダプタを生成
        mAdapter = new SimpleAdapter(
                this,
                mList,
                android.R.layout.simple_list_item_2,
                new String [] {"title", "content"},
                new int[] {android.R.id.text1, android.R.id.text2}
                );
        
        // ListView にアダプターをセット
        ListView list = (ListView)findViewById(R.id.listView);
        list.setAdapter(mAdapter);
    }
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // ListView 用アダプタのリストを生成
        mList = new ArrayList<Map<String, String>>();
        
        // ListView 用アダプタを生成
        mAdapter = new SimpleAdapter(
                this,
                mList,
                android.R.layout.simple_list_item_2,
                new String [] {"title", "content"},
                new int[] {android.R.id.text1, android.R.id.text2}
                );
        
        // ListView にアダプターをセット
        ListView list = (ListView)findViewById(R.id.listView);
        list.setAdapter(mAdapter);
        
        // ListView のアイテム選択イベント
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(
                    AdapterView<?> parent, View view, int pos, long id) {
                // 編集画面に渡すデータをセットし、表示
                Intent intent = new Intent(MainActivity.this, EditActivity.class);
                intent.putExtra("NAME", mList.get(pos).get("filename"));
                intent.putExtra("TITLE", mList.get(pos).get("title"));
                intent.putExtra("CONTENT", mList.get(pos).get("content"));
                startActivity(intent);
            }
        });
        
        // ListView をコンテキストメニューに登録
        registerForContextMenu(list);
    }
}

まず、メイン画面が生成されるタイミングで呼び出される onCreate メソッドで、アダプタを生成し、ListView に設定します。

次に、メイン画面が表示されるタイミングで呼び出される onResume メソッドで、アダプタのデータである mList に、 ファイルから読み込んだタイトルと内容をそれぞれ設定したキー title と content を使用して、map.put(キー、値) でマップに設定し、 マップをリストに追加していきます。
(マップに追加した filename は後で使用しますのでここで追加しておきます。ListView に表示されるデータは、SimpleAdapter生成時に指定した、 "title" と "content" になりますので、このデータはリストに追加されますが表示はされません。)

全ファイルのデータを mList に追加し終わったら、アダプタの notifyDataSetChanged メソッドを呼び出して ListView の表示を更新します。

これで、ファイルから読み込み、データを表示する処理の追加は完了です。

この状態でアプリを実行すると、メイン画面には保存したメモが一覧表示されます。
メイン画面のアクションバーで [追加] を選択し、編集画面でメモのタイトルと内容を入力後、戻るボタンを押下してメイン画面に戻ると、 その内容がメイン画面に表示されると思いますので、動作させてみてください。

これで、ListView へのデータ設定、表示の処理は完了です。



次は・・・
ListView の選択で編集画面を表示する処理と、長押しで削除メニューを表示し削除する処理を作成します。
2.8. ListView の選択操作(編集、削除)