この記事は Android スマホ用のアプリ開発の中で、
今後の開発で再使用性が高いと思われるコーディングをまとめたものです。
Java での開発経験、XML 構文規則、Android のアプリ開発経験がある方を対象としています。
Android のアプリ開発でお役にたててれば、嬉しいです。
(これから Android のアプリ開発や Java での開発を始めたい方への案内は、記事の最後で紹介します)
Roomは、オープンソースデータベースのSQLiteを抽象化レイヤとして提供するライブラリです。
AndoridアプリでSQLiteを使用する場合のベストプラクティスといっても過言ではありません。
Roomを使用することで、データベースの操作や定義、SQLの実行など、SQLiteを最大限に活用することが可能です。
Roomの導入から基本的な使用方法にフォーカスを当てて、開発したアプリのソースを参考に説明したいと思います。
使用するための準備
Roomを使用するには、モジュールのbuild.gradleファイルに定義の追加が必要です。
◎build.gradle(モジュール)
2023年3月現在の最新バージョンは2.6.1です。
dependencies {
:
implementation 'androidx.room:room-runtime:2.6.1'
implementation 'androidx.room:room-rxjava2:2.6.1'
implementation 'androidx.room:room-guava:2.6.1'
testImplementation 'androidx.room:room-testing:2.6.1'
annotationProcessor 'androidx.room:room-compiler:2.6.1'
}
基本構成
Roomの基本構成は、データベースを操作するデータベースクラス、テーブルを定義するエンティティ、テーブルを操作するデータアクセスオブジェクトです。
データベース
データベースを操作するデータベースクラスには、データベース構成を定義するRoomDatabaseを拡張する抽象クラス、データベースのインスタンスを作成するクラス、データベースのテーブルを操作するクラスがあります。
Database
データベース構成を定義するRoomDatabaseを拡張する抽象クラスです。
@Databaseアノテーションを付けて、データベースに関連付けられたエンティティをentities配列に含めます。
データベースに関連付けられたDaoクラスのインスタンスを返す抽象メソッドを定義します。
@Database(entities = {Movie.class,
Chapter.class,
History.class }, version = 1, exportSchema = false)
public abstract class DuelDatabase extends RoomDatabase {
public abstract MovieDao movieDao();
public abstract ChapterDao chapterDao();
public abstract HistoryDao historyDao();
}
versionはデータベースのバージョンを定義し、エンティティの追加や変更があった場合にカウントアップします。
スキーマ(エンティティ構造)を出力しない場合は、exportSchema = falseを指定します。
exportSchema = falseを指定した場合、
アプリリリース後のエンティティ変更やautoMigrationが使用できません。
◎スキーマを出力する場合
スキーマを出力する場合、exportSchemaの出力先フォルダ(プロジェクトフォルダ配下にschemasというフォルダ)を作成し、モジュールのbuild.gradleファイルに出力先フォルダの定義を追加します。
android {
:
defaultConfig {
:
javaCompileOptions {
annotationProcessorOptions {
arguments += ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
exportSchema = falseを削除します。
@Database(entities = {Movie.class,
Chapter.class,
History.class }, version = 1)
public abstract class DuelDatabase extends RoomDatabase {
public abstract MovieDao movieDao();
public abstract ChapterDao chapterDao();
public abstract HistoryDao historyDao();
}
DatabaseSingleton
データベースのインスタンスを作成するクラスです。
Databaseオブジェクトのインスタンス化は、シングルトン(デザインパターン)で実装します。
public class DuelDatabaseSingleton {
private static DuelDatabase instance = null;
public static DuelDatabase getInstance(Context context) {
if (instance != null) { return instance; }
instance = Room.databaseBuilder(context, DuelDatabase.class, context.getString(R.string.db_name)).build();
return instance;
}
}
DatabaseHelper
データベースのテーブルを操作するクラスです。
各テーブルのデータ検索、更新や削除などの処理を実装します。
public class DuelDatabaseHelper {
private final Handler handler = new Handler(Looper.getMainLooper());
private final MovieDao movieDao;
private final ChapterDao chapterDao;
private final HistoryDao historyDao;
private List<Movie> movieList = new ArrayList<>();
:
// コンストラクタ //
public DuelDatabaseHelper() {
DuelDatabase duelDatabase = DuelDatabaseSingleton.getInstance(context);
movieDao = duelDatabase.movieDao();
chapterDao= duelDatabase.chapterDao();
historyDao = duelDatabase.historyDao();
}
:
// データ検索 //
public void selectMovie(MainActivity mainActivity) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(() -> {
try {
movieList = movieDao.selectAll();
} catch (Exception e) {
e.printStackTrace();
}
handler.post(() -> {
// SELECT結果の返却
mainActivity.updateMovieView(movieList);
:
});
});
}
:
// データ更新 //
public void updateMovie(Movie movie) {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
try {
if (movie.movie == null) {
movieSequence = movieDao.insert(movie);
movie.movie = (int)movieSequence;
} else {
movieDao.update(movie);
}
} catch (Exception e) {
e.printStackTrace();
}
handler.post(() -> {
// 更新後の処理
:
});
});
}
:
// データ削除 //
public void truncateMovie() {
if (DEBUG) Log.d(TAG, "truncateMovie");
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
try {
movieDao.deleteAll();
movieDao.resetSequence();
} catch (Exception e) {
e.printStackTrace();
}
handler.post(() -> {
// 削除後の処理
:
});
});
}
:
コンストラクタでデータベースのインスタンス化と、データアクセスオブジェクト(Dao)をインスタンス化します。
テーブルの操作は、ExecutorServiceのnewSingleThreadExecutorで使用して、シングルスレッドで実行します。
テーブルを操作するSQLは、後述のDaoに定義します。
エンティティ
エンティティには@Entityを付けて、テーブル名、インデックスや制約には@Indexを付けて定義します。
項目毎にプライマリキーには@PrimaryKey、項目名には @ColumnInfoを付けます。
@Entity(tableName = "Movie", indices = {@Index(value = {"source"}, unique = true)})
public class Movie {
@PrimaryKey(autoGenerate = true)
public Integer movie;// シーケンス
@ColumnInfo(name = "source")
public String source;// 動画ファイル(xxx.mp4)
@ColumnInfo(name = "title")
public String title; // タイトル(表示用)
@ColumnInfo(name = "point1")
public Long point1; // 再生位置1
@ColumnInfo(name = "point2")
public Long point2; // 再生位置2
@ColumnInfo(name = "point3")
public Long point3; // 再生位置3
@ColumnInfo(name = "point4")
public Long point4; // 再生位置4
@ColumnInfo(name = "point5")
public Long point5; // 再生位置5
@ColumnInfo(name = "archive")
public String archive; // ARCファイル(拡張)
public Movie(Integer movie,
String source,
String title,
Long point1,
Long point2,
Long point3,
Long point4,
Long point5,
String archive) {
this.movie = movie;
this.source = source;
this.title = title;
this.point1 = point1 != null ? point1 : 0;
this.point2 = point2 != null ? point2 : 0;
this.point3 = point3 != null ? point3 : 0;
this.point4 = point4 != null ? point4 : 0;
this.point5 = point5 != null ? point5 : 0;
this.archive = archive;
}
}
データアクセスオブジェクト(Dao)
データアクセスオブジェクト(Dao)では、SQLを記述する場合は@Queryを付けてます。
追加する場合は@Insert、更新する場合は@Update、削除する場合は@Deleteを付けて定義します。
@Query以外の引数はエンティティです。
@Dao
public interface MovieDao {
// 参照
@Query("SELECT * FROM Movie WHERE movie = :movie")
Movie select(Integer movie);
@Query("SELECT * FROM Movie WHERE source = :source ORDER BY movie DESC LIMIT 1")
Movie select(String source);
@Query("SELECT * FROM Movie ORDER BY movie")
List<Movie> selectAll();
// 追加
@Insert(onConflict = OnConflictStrategy.IGNORE)
long insert(Movie movie);
// 更新
@Update(onConflict = OnConflictStrategy.REPLACE)
void update(Movie movie);
// 削除
@Delete
void delete(Movie movie);
@Query("DELETE FROM Movie")
void deleteAll();
@Query("DELETE FROM sqlite_sequence WHERE name='Movie'")
void resetSequence();
}
追加では、プライマリキーの採番結果を取得しています。
プライマリキーの採番を初期化するために、sqlite_sequenceから該当テーブルのレコードを削除しています。
Room(SQLite)のINSERTで自動採番されたシーケンスを取得するはこちらです↓↓↓
データベースにアクセスする
アプリ(Activity)からデータベースにアクセスする場合、DatabaseHelperをインスタンス化します。
インスタンス化したDatabaseHelperのDaoを経由して、テーブルにアクセスします。
private DuelDatabaseHelper duelDatabaseHelper = null;
private ArrayList<Movie> movieList = new ArrayList<>();
:
public class MainActivity extends AppCompatActivity {
:
// データベース初期化
duelDatabaseHelper = new DuelDatabaseHelper();
:
// 検索
duelDatabaseHelper.selectMovie(this);
// 更新
duelDatabaseHelper.updateMovie(movie);
:
// 削除
duelDatabaseHelper.truncateMovie();
:
// SELECT結果の受け取り
public void updateMovieView(List<Movie> newMovieList) {
movieList = (ArrayList<Movie>) newMovieList;
:
}
:
SQLiteのデータベース管理ツール
SQLiteのデータベース管理ツールとして、DB Browser for SQLiteがあると便利です。
データベースの内容をテーブルごとにリスト表示、指定した条件に一致するレコードを抽出して表示、レコードの追加や削除、SQLの実行などできます。
Room(SQLite) データベースを実装している Androidアプリです。
今回は、ここまでです。
誤字脱字、意味不明でわかりづらい、
もっと詳しく知りたいなどのご意見は、
このページの最後にあるコメントか、
こちらから、お願いいたします♪
ポチッとして頂けると、
次のコンテンツを作成する励みになります♪
これからAndroidのアプリ開発やJavaでの開発を始めたい方へ
初めての Android のアプリ開発では、アプリケーション開発経験がない方や、
アプリケーション開発経験がある方でも、Java や C# などのオブジェクト指向言語が初めての方は、
書籍などによる独学ではアプリ開発できるようになるには、かなりの時間がかかります。
オンラインスクールでの習得をおススメします。
未経験者からシステムエンジニアを目指すのに最適かと、まずは無料相談から♪
未経験者からプログラマーを目指すのに最適かと、まずは無料カウンセリングから♪
カリキュラムとサポートがしっかりしています、お得なキャンペーンとかいろいろやっています♪
ゲーム系に強いスクール、UnityやUnrealEngineを習得するのに最適かと、まずは無料オンライン相談から♪
参考になったら、💛をポッチとしてね♪
コメント欄