goo blog サービス終了のお知らせ 

marunomaruno-memo

marunomaruno-memo

[Android] データの取り扱い - データベース(SQLite)

2012年02月20日 | Android
[Android] データの取り扱い - データベース(SQLite)
================================================================================

データベース(SQLite)を使って、データの照会・保存・変更・削除を行う。

データ(列)は、つぎの 2 つ。
    ・名前
    ・コメント

なお、データベースのテーブルを使うにあたり、このデータを区別するための主キーとし
て、ID 列をつける。なお、SQLite では、この「PRIMARY KEY AUTOINCREMENT」の属性を
持った列は、「_id」という列名にする。こうしておくことで、CursorAdapter クラスを
使って ListView にデータを表示させることができる。
※ただし、CursorAdapter を使うのは、V3.x 以降では推奨されていないようだ。

データベースのテーブル生成文は以下のとおり。
        CREATE TABLE item (
            _id INTEGER PRIMARY KEY AUTOINCREMENT
            , name TEXT
            , comment TEXT
        )

このサンプル・アプリケーションではつぎのことができる。

・照会
    「名前」欄に記述されたものと一致するものをすべて取得するが、表示するのは最初
    に取得したものだけ。

・保存
    「名前」「コメント」欄に記述された内容をデータベースのテーブルに保存する。

・変更
    「名前」欄に記述されたものと一致するものすべての「コメント」を、すべて変更す
    る。

・削除
    「名前」欄に記述されたものと一致するものすべてを削除する。


データベースを扱うクラスとして、DatabaseHelper クラスを作る。これは、
SQLiteOpenHelper クラス(抽象クラス)を継承して作る。
次のメソッドのオーバーライドが必要。
abstract void     onCreate(SQLiteDatabase db)
abstract void     onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)


今回のクラス
---
Database01Activity  アクティビティ
DatabaseHelper      データベース操作
Item                エンティティ
---


▲ アクティビティ

データベースに関する操作はすべて DatabaseHelper オブジェクトで行っている。

□ Database01Activity.java
---
package jp.marunomaruno.android.database;

import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class Database01Activity extends Activity {
    private EditText name = null;
    private EditText comment = null;
    private DatabaseHelper dbHelper = null;    // (1)
    private int TOAST_DURATION = Toast.LENGTH_SHORT;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        name = (EditText) findViewById(R.id.name);
        comment = (EditText) findViewById(R.id.comment);
        dbHelper = new DatabaseHelper(this);    // (2)
    }

    @Override
    public void onPause() {
        super.onPause();
        if (dbHelper != null) {
            // dbHelper.close();    // 呼ばないほうがよい    // (3)
        }
    }

    public void onFindButtonClick(View view) {
        List<Item> itemList = dbHelper.select(name.getText());    // (4)
        if (itemList.size() <= 0) {
            Toast.makeText(this, getString(R.string.notFoundMessage),
                    TOAST_DURATION).show();
            return;
        }

        name.setText(itemList.get(0).getName());
        comment.setText(itemList.get(0).getComment());
        Toast.makeText(
                this,
                (itemList.size() == 1 ? String
                        .format(getString(R.string.findMessage)) : String
                        .format(getString(R.string.findMultipleMessage),
                                itemList.size())), TOAST_DURATION).show();
    }

    public void onSaveButtonClick(View view) {

        long id = dbHelper.insert(name.getText(), comment.getText());    // (5)

        name.setText("");
        comment.setText("");
        if (id > 0) {
            Toast.makeText(this,
                    String.format(getString(R.string.saveMessage), id),
                    TOAST_DURATION).show();

        } else {
            Toast.makeText(this, getString(R.string.notSaveMessage),
                    TOAST_DURATION).show();

        }
    }

    public void onUpdateButtonClick(View view) {
        int count = dbHelper.update(name.getText(), comment.getText()); // (6)

        if (count > 0) {
            Toast.makeText(this,
                    String.format(getString(R.string.updateMessage), count),
                    TOAST_DURATION).show();

        } else {
            Toast.makeText(this, getString(R.string.notUpdateMessage),
                    TOAST_DURATION).show();
        }
    }

    public void onRemoveButtonClick(View view) {
        int count = dbHelper.delete(name.getText());    // (7)

        name.setText("");
        comment.setText("");
        if (count > 0) {
            Toast.makeText(this,
                    String.format(getString(R.string.removeMessage), count),
                    TOAST_DURATION).show();

        } else {
            Toast.makeText(this, getString(R.string.notRemoveMessage),
                    TOAST_DURATION).show();
        }
    }
}
---

(1)(2) データベースにアクセスするオブジェクト

    private DatabaseHelper dbHelper = null;    // (1)

DatabaseHelper オブジェクトで、データベースを取得しようとしたときに、データベー
スがない場合、onCreate() メソッドが動く。
また、データベースのバージョンが変わったときは、onUpgrade() メソッドが動く。
データベースのバージョンは、SQLiteOpenHelper のコンストラクターの引数 
int version で指定する。この値が、現在のバージョンが変わったら、このonUpgrade()
 メソッドが動くことになる。

    dbHelper = new DatabaseHelper(this);    // (2)


(3) データベースを閉じる

ただし、これは自分では閉じない方がよいらしい。

    // dbHelper.close();    // 呼ばないほうがよい    // (3)

参考
「SQLiteDatabase.closeは明示で呼ぶな、Cursor.closeは明示で呼べ」
SQLiteを使う場合の注意点
http://d.hatena.ne.jp/ukiki999/20100524/p1


(4) name で指定されたデータを取得(照会)する

結果は、List オブジェクトで戻る。

    List<Item> itemList = dbHelper.select(name.getText());    // (4)


(5) name, comment データを挿入する

結果は、主キーの値が戻る。挿入できなかったときは、-1.

    long id = dbHelper.insert(name.getText(), comment.getText());    // (5)


(6) name で指定されたデータを更新する

結果は、更新した行数。

    int count = dbHelper.update(name.getText(), comment.getText());    // (6)


(7) name で指定されたデータを削除する

結果は、削除した行数。

    int count = dbHelper.delete(name.getText());    // (7)


▲ データベース関係

データベースを操作するためのクラス。

SQLiteOpenHelper クラスを継承して、その抽象メソッドであるつぎのメソッドをオー
バーライドする。そして、必要に応じて CRUD メソッドを記しておく。
     onCreate(SQLiteDatabase db)
     onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

データベースの CRUD 操作は、getReadableDatabase() メソッド、
getWritableDatabase() メソッドによって、SQLiteDatabase オブジェクトが取得できる
ので、このオブジェクトの中のメソッドによる。

□ DatabaseHelper.java
---
package jp.marunomaruno.android.database;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.Editable;

/**
 * データベースを扱うためのヘルパー・クラス。
 * 
 * @author marunomaruno
 */
public class DatabaseHelper extends SQLiteOpenHelper {    // (1)
    private Context context;
    private static final String DATABASE_NAME = "item.db";
    private static final int DATABASE_VERSION = 1;    // (2)
    public static final String TABLE_NAME = "item";
    public static final String ID = "_id";
    public static final String NAME = "name";
    public static final String COMMENT = "comment";
    public static final String[] COLUMN_NAMES = { ID, NAME, COMMENT, };

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);    // (3)
        this.context = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {    // (4)
        final String SQL = String.format(context
                .getString(R.string.createTableFormat), TABLE_NAME, ID, NAME,
                COMMENT);    // (5)
        System.out.println("DatabaseHelper.onCreate() SQL = " + SQL);
        db.execSQL(SQL);    // (6)
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  // (7)
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);    // (8)
        onCreate(db);
    }

    /**
     * 指定されたデータをデータベースに挿入する。
     * 
     * @param name
     *            名前
     * @param comment
     *            コメント
     * @return 主キーの値
     */
    public long insert(String name, String comment) {
        String nullColumnHack = null; 
                        // NOT NULL列に値が指定されていない場合のデフォルト値
        ContentValues values = new ContentValues(); // 挿入する列名と値 // (9)
        values.put(NAME, name);    // (10)
        values.put(COMMENT, comment);
        return getWritableDatabase().insert(TABLE_NAME, nullColumnHack, values); // (11)
    }

    /**
     * 指定されたデータをデータベースに挿入する。
     * 
     * @param name
     *            名前
     * @param comment
     *            コメント
     * @return 主キーの値
     */
    public long insert(Editable name, Editable comment) {
        return insert(name.toString(), comment.toString());
    }

    /**
     * 名前で指定されたデータを変更する。
     * 
     * @param name
     *            名前
     * @param comment
     *            コメント
     * @return 変更した行数
     */
    public int update(String name, String comment) {
        ContentValues values = new ContentValues();    // 更新する列名と値
        values.put(COMMENT, comment);
        String whereClause = NAME + " = ?";    // 選択条件    // (12)
        String[] whereArgs = new String[] { name }; // パラメーター・マーカーの値 // (13)
        return getWritableDatabase().update(TABLE_NAME, values, whereClause,
                whereArgs);    // (14)
    }

    /**
     * 名前で指定されたデータを変更する。
     * 
     * @param name
     *            名前
     * @param comment
     *            コメント
     * @return 変更した行数
     */
    public int update(Editable name, Editable comment) {
        return update(name.toString(), comment.toString());
    }

    /**
     * 名前で指定されたデータを削除する。
     * 
     * @param name
     *            名前
     * @return 削除した行数
     */
    public int delete(String name) {
        String whereClause = NAME + " = ?";    // 選択条件
        String[] whereArgs = new String[] { name };  // パラメーター・マーカーの
値
        return getWritableDatabase().delete(TABLE_NAME, whereClause, whereArgs);
 // (15)
    }

    /**
     * 名前で指定されたデータを削除する。
     * 
     * @param name
     *            名前
     * @return 削除した行数
     */
    public int delete(Editable name) {
        return delete(name.toString());
    }

    /**
     * 名前で指定されたデータを照会する。
     * 
     * @param name
     *            名前
     * @return 照会したデータのリスト
     */
    public List<Item> select(String name) {
        String selection = NAME + " = ?";    // 選択条件
        String[] selectionArgs = { name };    // パラメーター・マーカーの値
        String groupBy = null;    // GROUP BY 句
        String having = null;     // HAVING 句
        String orderBy = null;    // ORDER BY 句
        Cursor cursor = getReadableDatabase().query(TABLE_NAME, COLUMN_NAMES,
                selection, selectionArgs, groupBy, having, orderBy);    // (16)

        List<Item> itemList = new ArrayList<Item>();

        if (!cursor.moveToFirst()) {    // 最初の行をさす    // (17)
            cursor.close();
            return itemList;
        }

        do {
            itemList.add(new Item(cursor.getLong(cursor.getColumnIndex(ID)),
                    cursor.getString(cursor.getColumnIndex(NAME)), cursor
                            .getString(cursor.getColumnIndex(COMMENT)))); // (18
)
        } while (cursor.moveToNext());    // (19)

        cursor.close();    // (20)
        return itemList;
    }

    /**
     * 名前で指定されたデータを照会する。
     * 
     * @param name
     *            名前
     * @return 照会したデータのリスト
     */
    public List<Item> select(Editable name) {
        return select(name.toString());
    }
}
---

(1) データベースにアクセスするクラス

SQLiteOpenHelper クラスを継承する。

    public class DatabaseHelper extends SQLiteOpenHelper {    // (1)


・SQLiteOpenHelper クラス

データベースと接続するためのクラス。
SQLite では、JDBC と違い、Connection オブジェクトを作るわけではなく、データベー
ス自体の管理は、この SQLiteOpenHelper オブジェクトを通して、生成・バージョンアッ
プ・接続などを行う。

java.lang.Object
   -   android.database.sqlite.SQLiteOpenHelper

・コンストラクター
---
SQLiteOpenHelper(Context context, String name, 
                    SQLiteDatabase.CursorFactory factory, int version)
SQLiteOpenHelper(Context context, String name, 
                    SQLiteDatabase.CursorFactory factory, int version, 
                    DatabaseErrorHandler errorHandler)
---

name はデータベース名。データベースは、「/data/data/パッケージ名/database/」に構
築される。
factory は、独自カーソルを定義した場合に使う。標準でよければ null。
version は、データベースのバージョン。既存のデータベースのバージョンと違う場合、
旧バージョンとの値の差によって、
    onDowngrade()
    onUpgrade()
メソッドが動く。なお、onUpgrade() メソッドは抽象メソッドなので、オーバーライドが
必要であるが、onDowngrade() メソッドは具象メソッドなので、必要なときにオーバーラ
イドすればよい。


・メソッド
---
synchronized void close()
String            getDatabaseName()
synchronized SQLiteDatabase     getReadableDatabase()
synchronized SQLiteDatabase     getWritableDatabase()
abstract void     onCreate(SQLiteDatabase db)
void              onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)
void              onOpen(SQLiteDatabase db)
abstract void     onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
---

データベースへの接続は、getReadableDatabase() メソッド、getWritableDatabase() メ
ソッドで行う。


(2)(3) このデータベースのバージョン

今回は、バージョン 1 にしておく。データベースの構成が変わったときは、2 以上にし
て、データベースを作り直す。

    private static final int DATABASE_VERSION = 1;    // (2)

バージョンの指定は、スーパークラス SQLiteOpenHelper のコンストラクターの引数で指
定する。

    super(context, DATABASE_NAME, null, DATABASE_VERSION);    // (3)


(4) データベースがなかったときの処理

データベースに接続するときに、データベースがなかったときにこのメソッドが呼ばれる。
これは、SQLiteOpenHelper クラスの抽象メソッド。

    public void onCreate(SQLiteDatabase db) {    // (4)


(5)(6) データベースとテーブルを生成する

CREATE TABLE 文を記している。文の形式はリソースとして定義している。

    final String SQL = String.format(context
            .getString(R.string.createTableFormat), TABLE_NAME, ID, NAME,
            COMMENT);    // (5)

実際の文は以下のとおり。
    CREATE TABLE item (
        _id INTEGER PRIMARY KEY AUTOINCREMENT
        , name TEXT
        , comment TEXT
    )

SQL 文を実行する。

    db.execSQL(SQL);    // (6)


(7) データベースのバージョンがあがったときの処理

これは、SQLiteOpenHelper クラスの抽象メソッド。

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // (7)

(8) テーブルがあれば削除して作り直す

    db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);    // (8)
    onCreate(db);


(9)(10) 挿入する列名と値を設定する

テーブルに挿入や更新する場合、列名と値のペアで管理する。名前と値のペアというと、
Map オブジェクトがあるが、SQLite では、ContentValues オブジェクトを使う。使い方
は Map と同じで、put() メソッドを使って値を設定。get() メソッドで、値を取得する。
なお、値の型によって、getAsXxx() メソッドもある。

    ContentValues values = new ContentValues();    // 挿入する列名と値    // (9)
    values.put(NAME, name);    // (10)


□ ContentValues クラス

SQLite の DML を使いやすくするのに適した形のマップ(Map)。

・android.content.ContentValues

・取得・設定関係のメソッド
---
Object   get(String key)
Boolean  getAsBoolean(String key)
Byte     getAsByte(String key)
byte[]   getAsByteArray(String key)
Double   getAsDouble(String key)
Float    getAsFloat(String key)
Integer  getAsInteger(String key)
Long     getAsLong(String key)
Short    getAsShort(String key)
String   getAsString(String key)

void     put(String key, Byte value)
void     put(String key, Integer value)
void     put(String key, Float value)
void     put(String key, Short value)
void     put(String key, byte[] value)
void     put(String key, String value)
void     put(String key, Double value)
void     put(String key, Long value)
void     put(String key, Boolean value)
void     putAll(ContentValues other)
void     putNull(String key)
---


・その他のメソッド
---
void                        clear()
boolean                     containsKey(String key)
boolean                     equals(Object object)
int                         hashCode()
Set<String>                 keySet()
void                        remove(String key)
int                         size()
String                      toString()
Set<Entry<String, Object>>  valueSet()
---


(11) name, comment データを挿入する

データを挿入するので、getWritableDatabase() メソッドを使って、書き込みができる
モードで、データベースを開く。このメソッドの結果は、SQLiteDatabase オブジェクト。
SQLiteDatabase クラスには、CRUD 系のメソッドが用意されているので、それらを使って
テーブルを操作する。

    return getWritableDatabase().insert(TABLE_NAME, nullColumnHack, values); // (11)

---
long  insert(String table, String nullColumnHack, ContentValues values)
---
戻り値は、挿入したときの rowID。INTEGER 型の主キー制約列が定義されていればその値
(のはず)。挿入エラーのときは -1.
String table            テーブル名
String nullColumnHack   NOT NULL 列に値が指定されていない場合のデフォルト値。
ContentValues values    列名と値がマッピングされたオブジェクト


(12)(13)(14) name で指定されたデータを更新する

選択条件には、JDBC と同じように、パラメーター・マーカー「?」が使える。
パラメーター・マーカー「?」に対する値は、String 配列値として別に用意する。

    String whereClause = NAME + " = ?";    // 選択条件    // (12)
    String[] whereArgs = new String[] { name }; // パラメーター・マーカーの値 // (13)

テーブルの更新なので、getWritableDatabase() メソッドを使う。

    return getWritableDatabase().update(TABLE_NAME, values, whereClause,
            whereArgs);    // (14)

---
int   update(String table, ContentValues values, String whereClause, 
                                                    String[] whereArgs)
---
戻り値は、更新した行数


(15) name で指定されたデータを削除する

update() メソッドと同じように、選択条件にはパラメーター・マーカー「?」が使える。

    return getWritableDatabase().delete(TABLE_NAME, whereClause, whereArgs); // (15)

---
int   delete(String table, String whereClause, String[] whereArgs)
---
戻り値は、削除した行数


(16) name で指定されたデータを取得(照会)する

ここでは、照会だけなので、読み取り専用で、getReadableDatabase() メソッドを使えば
よい。戻り値は Cursor オブジェクト。

    Cursor cursor = getReadableDatabase().query(TABLE_NAME, COLUMN_NAMES,
            selection, selectionArgs, groupBy, having, orderBy);    // (16)

---
Cursor  query(String table, String[] columns, String selection, 
            String[] selectionArgs, String groupBy, String having, 
            String orderBy, String limit)

Cursor  query(String table, String[] columns, String selection, 
            String[] selectionArgs, String groupBy, String having, 
            String orderBy)

Cursor  query(boolean distinct, String table, String[] columns, String selection,
            String[] selectionArgs, String groupBy, String having, 
            String orderBy, String limit)

Cursor  rawQuery(String sql, String[] selectionArgs)

引数
    boolean distinct        DISTINCT(true)かALL(false)か
    String table            テーブル名
    String[] columns        射影される列名(nullのとき、すべての列)
    String selection        WHERE句(パラメーターマーカー(?)の指定も可能)
    String[] selectionArgs  パラメーターマーカー(?)を置き換える文字列
    String groupBy          GROUP BY句
    String having           HAVING句
    String orderBy          ORDER BY句
    String limit            LIMIT句
    String sql              SQL文(パラメーターマーカー含む)
---


(17) 取得したテーブルの最初の行をさす

カーソルを使って取得したテーブルを処理する。
まずは、最初の行にカーソルを移動する。

    if (!cursor.moveToFirst()) {    // 最初の行をさす    // (17)

JDBC と違って、単純に next() メソッドを使うだけでできるわけではないので注意が必
要。moveToFirst() メソッドで、先頭行に移動し、moveToNext() メソッドで、つぎの行
に移動する、というパターン。全体としては、つぎのような感じでロジックを組む。

---
    if (!cursor.moveToFirst()) {    // 最初の行をさす
        cursor.close();
        return ...;
    }

    do {
        // 行の処理
    } while (cursor.moveToNext());    // つぎの行に移動する

    cursor.close();
---

・行の移動関係のメソッド
---
boolean move(int offset) 
boolean moveToFirst() 
boolean moveToLast() 
boolean moveToNext() 
boolean moveToPosition(int position) 
boolean moveToPrevious()  
---


(18) 行のデータから Item オブジェクトを生成する

    itemList.add(new Item(cursor.getLong(cursor.getColumnIndex(ID)),
            cursor.getString(cursor.getColumnIndex(NAME)), cursor
                    .getString(cursor.getColumnIndex(COMMENT))));    // (18)

・ データ取得関係のメソッド
---
byte[]  getBlob(int columnIndex) 
double  getDouble(int columnIndex)
float   getFloat(int columnIndex) 
int     getInt(int columnIndex) 
long    getLong(int columnIndex) 
short   getShort(int columnIndex) 
String  getString(int columnIndex) 
---

引数としては列番号だけなので、列名から取得したいときは、
    getColumnIndex(String columnName)
と組み合わせる必要がある。


(19) つぎの行に移動する

    } while (cursor.moveToNext());    // (19)


(20) カーソルを閉じる

使い終わったカーソルは閉じる。

    cursor.close();    // (20)

閉じていない場合は、つぎのエラーが出る。
    E/Cursor(14725): Finalizing a Cursor that has not been deactivated or closed.


▲エンティティ

単純に、id、name、comment を持っているだけのクラス。
JavaBeans の要件は満たすようにしている。

□ Item.java
---
package jp.marunomaruno.android.database;

import java.io.Serializable;

/**
 * データベースの項目を管理するエンティティ・クラス。
 * 
 * @author marunomaruno
 */
public class Item implements Serializable {
    private static final long serialVersionUID = 1L;

    public static final int NONE_ID = -1;
    private long id;
    private String name;
    private String comment;

    public Item(long id, String name, String comment) {
        this.id = id;
        this.name = name;
        this.comment = comment;
    }

    public Item(String name, String comment) {
        this(NONE_ID, name, comment);
    }

    public Item() {
        assert true;    // 何もしない
    }
    
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    @Override
    public String toString() {
        return String.format("[%d, %s, %s]", id, name, comment);
    }
}
---


▲レイアウト


□ res/layout/main.xml
---
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="1" >

    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/nameHint" >

        <requestFocus >
        </requestFocus>
    </EditText>

    <EditText
        android:id="@+id/comment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/commentHint"
        android:inputType="textMultiLine" >
    </EditText>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/findButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onFindButtonClick"
            android:text="@string/findButton" >
        </Button>

        <Button
            android:id="@+id/saveButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onSaveButtonClick"
            android:text="@string/saveButton" >
        </Button>

        <Button
            android:id="@+id/updateButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onUpdateButtonClick"
            android:text="@string/updateButton" >
        </Button>

        <Button
            android:id="@+id/removeButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onRemoveButtonClick"
            android:text="@string/removeButton" >
        </Button>
    </LinearLayout>

</LinearLayout>
---


▲ 文字列

---
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Database01</string>
    <string name="nameHint">名前</string>
    <string name="commentHint">コメント</string>
    <string name="saveButton">保存</string>
    <string name="findButton">検索</string>
    <string name="removeButton">削除</string>
    <string name="updateButton">変更</string>
    <string name="saveMessage">ID %d で保存しました</string>
    <string name="findMessage">データがありました。</string>
    <string name="findMultipleMessage">
                %d 件のデータがありました。最初の1件を表示します</string>
    <string name="removeMessage">%d 件のデータを削除しました</string>
    <string name="updateMessage">%d 件のデータを変更しました</string>
    <string name="notSaveMessage">データを保存できませんでした</string>
    <string name="notFoundMessage">データはありませんでした</string>
    <string name="notRemoveMessage">データを削除できませんでした</string>
    <string name="notUpdateMessage">データを変更できませんでした</string>
    <string name="createTableFormat">
        CREATE TABLE %1$s (
            %2$s INTEGER PRIMARY KEY AUTOINCREMENT
            , %3$s TEXT
            , %4$s TEXT
        )
    </string>    <!-- (1) -->

</resources>
---

(1) テーブルを生成する SQL 文のフォーマット

    <string name="createTableFormat">
        CREATE TABLE %1$s (
            %2$s INTEGER PRIMARY KEY AUTOINCREMENT
            , %3$s TEXT
            , %4$s TEXT
        )
    </string>    <!-- (1) -->

※ この部分は、国際化とは意味が違うので、別の XML ファイルにした方がよいかもしれ
ない。

                                                                            以上



最新の画像もっと見る

コメントを投稿