Android, Androidstudio, Kotlin, PC, Realm, Windows, 紹介
以前の記事で、Realmに入ったデータを取得する方法について解説しました。
その時の説明では、既にデータを用意しているという前提で話を進めていましたが、実際にアプリを開発するとなると、こちらからデータを取得するだけでなく、データを保存できるようにしたいという場合もあると思います。
なので、今回はKotlinでRealmを使う方法と、Realmにデータを保存、Realmに保存したデータを表示する方法について例を交えながら解説していきたいと思います。
今回は例として使っているRealmのバージョンは 10.11.0 ですので、ご注意ください。
目次
今回の解説で使用するサンプルアプリはこちらになります。
入力したテキストをRealmに保存し、保存した内容を画面に表示するという機能を持っています。
今回はこのサンプルをもとに解説をしていきたいと思います。
まずはサンプルのアプリを作るためのプロジェクトを作成します。最初に選ぶプロジェクトは何でも大丈夫ですが、今回は Empty Activity を選択しました。名前は「Sample-realm」としています。
プロジェクトの作成が完了したら、Realmを導入して使えるようにします。
まずは、”build.gradle(アプリ名)” を開いてください。
既に数行記載がありますが、一番上に以下のコードを記述します。
// build.gradle(Sample-realm) // Top-level build file where you can add configuration options common to all sub-projects/modules. // 以下のbuildscriptを記述 buildscript { repositories { mavenCentral() } dependencies { classpath "io.realm:realm-gradle-plugin:10.11.0" } }
これでRealmのプラグインを追加しています。バージョンはその時によって変わるので、適宜確認してください。
続いては、”build.gradle(:app)” と書かれたファイルを開いてください。その一番上にpluginsと書かれた箇所があると思います。そこに以下のコードを記述します。
// build.gradle(:app) plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' // 以下のコードを記述 id 'org.jetbrains.kotlin.kapt' } //以下のコードを記述 apply plugin: "realm-android"
すると画面の上部にSync nowという表示が出てくると思いますので、そちらを押してください。
Realmの導入は完了しましたので、続いてはRealmの初期化を行っていきます。
まずは、Applicationクラスを追加したいので、MainActivityと同じ階層に○○Application(サンプルはSampleApplication)というクラスを作成します。作成したら、中身を編集していきます。
まずは、Realmを使えるように以下のコードを記述してください
// SampleApplication.kt package jp.co.chrono.sample_realm import android.app.Application import io.realm.Realm class SampleApplication: Application() { override fun onCreate() { super.onCreate() Realm.init(this) //Realmの初期化 } }
ここではRealmが使えるようにimportと、onCreate()の中でRealmを初期化しています。
Applicationの作成が完了したら、それを “AndroidManifest.xml” に追加します。
applicationタグの中に android:name=”Application名” を記述してください
<application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:name="jp.co.chrono.sample_realm.SampleApplication" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Samplerealm" tools:targetApi="31">
この記述でアプリのApplicationクラスがSampleApplicationになります。
これでRealmの初期化も完了です。
続いては、画面に表示するレイアウトの実装をしていきます。ただ、今回の趣旨とは少し離れるので、細かい解説等は省略します。
リストの作り方については、以前のブログでも紹介していますので、気になった方はそちらも参考にしてください。
今回は、表示する内容がリストになっているので、RecycleViewを使いたいと思います。
まずは、 “build.gradle(:app)” を開いて、dependenciesの中に以下のコードを記述してください。
dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' //この一行を追加 implementation 'androidx.recyclerview:recyclerview:1.2.1' }
ここでSync Nowが表示されたら、そちらも押してください。
つづいては、画面のレイアウトを設定するので、activity_mainを開き、以下の通りにコードを記述します。細かい設定に関しては自由に決めてしまっても問題ありません。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="jp.co.chrono.sample_realm.MainActivity"> <EditText android:id="@+id/sample_edit_text" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="テキスト入力" android:textColor="#000000" app:layout_constraintEnd_toStartOf="@id/add_button" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/add_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存" android:textColor="#000000" android:textSize="20sp" app:iconTint="#000000" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/sample_list" android:layout_width="0dp" android:layout_height="0dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/sample_edit_text" /> </androidx.constraintlayout.widget.ConstraintLayout>
続いて、リストを表示する新しいファイル(サンプルはitem_sample.xml)を作成し、以下のコードを記述してください。
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/sample_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:textSize="20sp" />
これでレイアウトの実装は完了です。
続いて、Adapterの実装をするため、Adapterのクラス(サンプルではSampleListAdapter.kt)を作成してください。
作成できたら、以下のコードを記述します。
package jp.co.chrono.sample_realm import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.example.sample_realm.R class SampleListAdapter: RecyclerView.Adapter<SampleListAdapter.SampleViewHolder>() { private val sampleList = mutableListOf<String>() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SampleViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_sample, parent, false) return SampleViewHolder(view) } override fun onBindViewHolder(holder: SampleViewHolder, position: Int) { holder.bind(sampleList[position]) } override fun getItemCount(): Int = sampleList.size fun updateSampleList(sampleList: List<String>) { // 一度クリアしてから新しいメモに入れ替える this.sampleList.clear() this.sampleList.addAll(sampleList) // データに変更があったことをadapterに通知 notifyDataSetChanged() } class SampleViewHolder(view: View): RecyclerView.ViewHolder(view) { fun bind(sample: String) { val textView = itemView.findViewById<TextView>(R.id.sample_text_view) textView.text = sample } } }
この中では、onBindViewHolder()の中でSampleViewHolderのbind()を呼び出し、TextViewに文字列を入れています。
Adapterが作成できたので、これをRecyclerViewにセットします。
セットするには “MainActivity.kt” の中に以下のようにコードを記述します。
package jp.co.chrono.sample_realm import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.EditText import androidx.recyclerview.widget.RecyclerView import com.example.sample_realm.R import io.realm.Realm class MainActivity : AppCompatActivity() { private lateinit var adapter: SampleListAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val recyclerView = findViewById<RecyclerView>(R.id.sample_list) adapter = SampleListAdapter() recyclerView.adapter = adapter
SampleListAdapterのadapterを定義して、それをonCreate()の中で代入しています。
その後、findViewById()で sample_list を取得してadapterに代入しています。
これでレイアウトの設定も完了です。
それでは、今回の本題であるRealmとの連携方法について解説していきます。
まずは、テキストを保存するためのデータ形式を定義するための、クラス(サンプルではDataList.kt)を作成してください。
中身は以下のコードを記述して下さい。
package jp.co.chrono.sample_realm import io.realm.RealmObject open class DataList: RealmObject() { var name: String = "" }
今回は、保存する内容がテキストだけなので、nameのみの記述になっています。
そして、ここで重要な点が RealmObjectを継承している点と、open修飾子を付ける点になります。この二つはどちらもRealmライブラリの中で処理をするために必要な記述なので、Realmを使う際は忘れないようにしましょう。
データ形式の定義ができたら、文字列が入力された状態で保存ボタンを押すと画面に表示される機能を実装していきます。
MainActivity.ktをを開き、先ほどの記述の下に新しくコードを記述してください。
val editText = findViewById<EditText>(R.id.sample_edit_text) val addButton = findViewById<Button>(R.id.add_button) val realm = Realm.getDefaultInstance() addButton.setOnClickListener { val text = editText.text.toString() if (text.isEmpty()) { //テキストが空の場合には無視をする return@setOnClickListener } // Realmのトランザクション realm.executeTransactionAsync { //DataListのオブジェクト作成 val data = it.createObject(DataList::class.java) //nameに先ほど入力されたtextを入れる data.name = text //データの上書きをする it.copyFromRealm(data) } //テキスト入力欄を空にする editText.text.clear() }
内容について解説していきます。
まずは1,2行目では findViewById を使って EditText と Button のViewを取得しています。
4行目ではRealmのインスタンスを取得しています。この記述はRealmの操作を行うときには必ず記述しないといけないので、これも忘れないように注意しましょう。
6から24行目はボタンを押したときの処理を記述しています。
空のテキストを保存しないように、最初に文字列が入っているかのチェックをしています。文字列が入力されている時は次の realm.executeTransactionAsync() の処理に進みます。
そこではまず、DataListのオブジェクトを作成します。この時、同時にRealmのDBにも登録がされます。
その後、オブジェクトに入力された文字列を代入し、copyFromRealm() でデータを上書きしています。
これで、文字列をDBに登録することができます。
その後の editText.text.clear は次の内容を入力しやすいように、テキスト入力欄を空にしています。
以上の内容が記述できたら、その下にまた以下のコードを記述します。
// DBに変更があった時に通知が来る realm.addChangeListener { //変更があった時にリストをアップデートする val sampleList = it.where(DataList::class.java).findAll().map { it.name } //UIスレッドで更新する recyclerView.post { adapter.updateSampleList(sampleList) } } // 初回表示の時にメモ一覧を表示 realm.executeTransactionAsync { val sampleList = it.where(DataList::class.java).findAll().map { it.name } // UIスレッドで更新する recyclerView.post { adapter.updateSampleList(sampleList) } } } }
この記述は二つに分かれていますが、どちらもAdapterの updateSampleLIst() を呼び出しています。
一つ目は、DBに変更があった際に表示しているリストを更新しています。
しかし、それだけだとアプリを起動した時に何も表示されないので、初回表示の時にもDBの内容を表示するようにしています。
詳しい内容としては、where().findAll() を使って、DBに登録されているDataListを取得し、それを引数にして updateSampleList() を呼び出しています。
以上でサンプルアプリの作成は完了です。
実際に触ってみると、入力したテキストを保存できていることが確認できると思います。
いかがでしたでしょうか。今回は基本的な内容の解説になりましたが、今後もRealmを使う機会は増えてくると思いますので、入門としてぜひ参考にしてみてください
kotlinを使ってアプリ開発を行っていると、RxKotlinを使ってデータそれぞれに処理を行うことがあると思います。
その際、処理を行うデータがちゃんと渡っていなければ上手く実行することができない場合があります。なので、意図しないエラーを減らすためにも、実装時にはデータを確認するのがおすすめです。
今回は、doOnSuccessやdoOnErrorの処理をする時にちゃんとデータが渡っているか確認する方法について紹介しますので、ぜひ参考にしてみてください。
目次
このブログを見ている方はすでにご存じだとは思いますが、RxKotlinについて説明したいと思います。
ただ、説明のためにはまずRxを理解する必要があるので、こちらについても簡単に説明します。
Rxは Reactive Extention を略したもので、Microsoftが開発した概念になります。
データが生成されるたびに送信されるデータに対して、その都度処理を行って目的を達成するといった考え方のことで、リアクティブプログラミングとも呼ばれています。
そして、RxをJavaに導入したRxJavaというライブラリがあり、それをKotlinで使いやすくするための軽量ライブラリがRxKotlinになります。
では、実際にRxKotlinを使った際のデータの確認方法をお伝えします。
結論からお伝えすると、データを確認したい時は Log.d(“tag”, “出力内容”) を使ってログを出力すればOKです。
かなり簡略化している例ですが、実際に書くとこのような形になります。
dataList() //渡したいデータ .map { item -> Log.d("tag", item.toString()) //処理内容 } .doOnSuccess { res -> Log.d("tag", res.toString()) //処理内容 } .doOnError { e -> Log.d("tag", e.toString()) //処理内容 }
処理した後の結果を出力したい場合は、処理内容の後にログを入れれば大丈夫です。
これで、それぞれの処理が行われる際に、渡っているデータの内容がログに出力されるようになりますので、必要なデータに対して処理が行われているか確認することができます。
いかがでしたでしょうか。普段と違う書き方であったり、処理の仕方が違ってくると、動きが分かりにくくなってしまうこともあると思います。そのような時はいつも通りログを出力すると把握がしやすくなると思いますので、ぜひ確認してみてください。
Android, Androidstudio, PC, ツール, 紹介
現在、Androidアプリを開発する際にはAndroid Studioを使っている方が多いと思います。
AndroidStudioはGoogleからも推奨されている総合開発環境であり、これからAndroidアプリを開発したいと考えている方にもおすすめのIDEです。
しかし、使用されているのが英語のため、使うのに少し手間取ってしまうということがあるかもしれません。
英語に慣れるためにも、そのまま使った方が良いと思う方もいるとは思いますが、英語がやっぱり苦手で、日本語で使いたいと考えている方も少なからずいると思います。
そこで今回は、日本語で使いたいという方に向けて、Android Studioを日本語化する方法について解説したいと思います。
また、今回はAndroid Studio Dolphinの解説になりますので、ご注意ください。
目次
では早速、日本語化の手順を紹介していきたいと思いますが、まずは使っているAndroid Studioのバージョンを確認します。
バージョンを確認する場合はAndroid Studioを開き、画面上部の[Help]から[About]を選択します。
すると、画像のようにAndroid Studioのバージョン情報が表示されます。
この時に確認していただきたいのが、Build #AI-と書かれた箇所の次の数字です。今回は213…と続いています。
バージョンの確認ができましたら、日本語化するためのPluginをAndroid Studioに追加していきます。
Android StudioのPlugin MarketplaceにはDolphinに対応したPluginが存在しないため、JetBrains公式の言語パックのjarファイルをPluginとして追加します。
Pluginは以下のサイトから入手できます。
https://plugins.jetbrains.com/plugin/13964-japanese-language-pack——
サイトが表示されたらVersionsタブを選択します。
バージョン一覧が表示されたら、その中から自分が使っているAndroid Studioのバージョンと同じものを探します。今回は先ほど確認したようにバージョンが213…だったので、213系の中で最新のもの (213.370) を選択します。
選択すると細かい情報が出てきますので、問題なければダウンロードします。
日本語化のファイルをダウンロードしたら、Android Studioの最初の画面を開き、左側の「Plugin」を選択します。その後、右上の歯車マークから「Install Plugin from Disk…」を選択します。
インストールするファイルを選択する画面が出てきますので、先ほどダウンロードしたファイルを選択し、OKを押します。
選択したPluginが表示されますので、右上の「Restart IDE」を押して、Android Studioを再起動します。
これで日本語化が完了します。
画像のように、英語の表示が日本語に変わっているのが確認できると思います。
いかがでしたでしょうか。日本語で表示されるとより細かい設定も簡単にできるようになると思います。もし、英語表示で使いづらく感じるといったようなことがあれば、一度日本語表示にしてみて使ってみると良いかもしれません。
Androidアプリの開発ではActivityやFragmentを使ってアプリの画面を実装していくと思います。そして、その際に気を付けなければならないのが、それぞれのライフサイクルです。
ライフサイクルを理解していないままコーディングを行ってしまうと、画面の表示が意図しないものになってしまったり、メモリが増加してしまったり等、予期しない不具合が起こってしまうことがあります。
逆にライフサイクルを正しく理解していれば、アプリの状態に合わせて的確な処理が実装できるようにもなります。
そこで、今回はActivityとFragmentそれぞれのライフサイクルがどのようになっているのかをまとめてみました。
目次
まずはActivityから解説します。
Activity とは簡単に言えば、「Androidアプリで表示される画面」になります。
普段皆さんが使っているアプリも、起動するとアプリの画面が開いてから操作ができるようになると思います。その時に開く画面そのものがActivityになります。
アプリの中に複数の画面が用意されている場合は、Activityも複数使われます。
Activityのライフサイクルを理解するために、まずはこちらの画像をご覧ください。
出典:アクティビティのライフサイクルについて
この画像から分かるように、Activityのライフサイクルでは7つのコールバックが提供されています。
それぞれのコールバックについて説明します。
Activityが生成される際、最初に呼ばれます。
このタイミングでViewを作成したり、基本的な設定をする処理を行ったりします。
Activityが「開始」の状態になると呼び出されます。
このタイミングでonCreate()で取得したViewへのイベント登録や初期化を行います。
この時点でActivityはフォアグラウンドに移動しますが、まだ操作をすることはできません。
Activityがユーザーからの操作を受け付け始める際に呼び出されます。
このタイミングではデータベースからデータを取り出したり、必要な情報をセットしたりするなど、表示や操作ができるようになるために必要な処理が実行されます。
アプリがフォアグラウンドでなくなった時や、停止する前に呼び出されます。
この状態はActivityが一時停止している状態であり、続行しない操作を停止したり、続行する操作をバックグラウンドで動くように調整したりします。
アプリが完全にバックグラウンドに移動した時に呼び出されます。
この状態ではActivityは非表示になり、停止しています。
ユーザーからアプリが見えていない状態のため、不要なリソースの開放やアニメーションの一時停止といった処理を行います。
Activityが非表示の状態から再度表示される際に呼び出されます。
画像にあるように、この後はonStart()が呼び出されます。
アプリが終了するなどして、Activityが破棄される前に呼び出されます。
以前のコールバックで解放されていないリソースがここで解放されます。
続いてFragmentについて解説します。
FragmentとはアプリUIの部品になるビューです。Activityよりも細かい単位でのレイアウトを定義して管理することができ、Activityの子ビューとして構成されます。
Fragment自体はActivityに依存しているわけではないので、複数のActivityから呼び出すことが可能という性質もあります。
Fragmentのライフサイクルにおいても、まとめられた画像がありますのでご覧ください
出典:フラグメント
見てわかるように、Fragmentも複数のコールバックが提供されていますので、それぞれ説明します。
FragmentがActivityと関連付けられた時に呼び出されます。
Fragmentにおける最初のメソッドになります。
Fragmentが作成された時に呼び出されます。
この時点でFragmentの初期化が行われます。
Fragmentに関連付けられたViewを作成する際に呼び出されます。
Fargmentに描画したいViewを返すことで、任意のViewを表示できるようになります。
ActivityのonCreate()が完了した際に呼び出されます。
Fragmentがユーザーに見えるようになった時に呼び出されます。
Activityと同様に、この時点ではまだ操作することはできません。
Fragmentがユーザーの操作を受け付け始める時に呼び出されます。
このメソッドはActivityと同時に実行されます。
Fragmentがフォアグラウンドでなくなった時や、停止する前に呼び出されます。
この時点で保存しておくべき情報が保存されます。
Fragmentがバックグラウンドに移動し、ユーザーに表示がされなくなった時に呼び出されます。
この時点では表示はされていないものの、破棄するまでには至っていません。
Fargmentに関連付けられたViewが削除された時に呼び出されます。
Fragment自体が破棄される前に呼び出されます。
こちらはActivityのonDestroy()の前に呼び出されます。
FragmentとActivityの関連付けが解除された時に呼び出されます。
このメソッドもActivityのonDestroy()の前に呼び出されます。
いかがでしたでしょうか。一度にすべて覚えるというのは難しいかもしれませんが、ライフサイクルは重要な考え方の一つですので、流れだけでも覚えておくと役に立つと思います。
細かい部分が分からなくなってしまったという時は、今回の記事を見直して一つずつ確認してみてください。
Android, Androidstudio, PC, ツール, 紹介
前回の記事でAndroid Studioのデバッガーについて紹介しました。デバッガーによってアプリの中でどの機能が動いているか、どこに問題があるのかを効率的に探すことが可能になりました。
ただ、アプリにおいては機能以外に、レイアウトも重要な要素になってきます。
せっかく思った通りの動きをするようになっても、それが表示されなかったり、レイアウトが崩れていたりしたらリリースすることはできません。
そこで今回はAndroid Studioでレイアウトのデバッグをする方法について紹介します。
使用しているバージョンは “Android Studio Dolphin | 2021.3.1” です。
目次
Android Studioにはレイアウトをデバッグする機能として、「Layout Inspector」が備わっています。
Layout Inspectorを使うと、表示しているレイアウトとその構造を確認することができるようになります。エミュレータで実際にアプリを動かしながら確認することができるので、動的なレイアウトのデバッグをする際にとても便利な機能です。
では実際に使う方法を解説します。
Layout Inspectorを使うには、Android Studioの画面上部 [Tools]から[Layout Inspector]を選択します。
エミュレータでアプリを起動していた場合は、エミュレータで表示している画面がLayout Inspectorにも表示されます。
Layout Ispectorのウィンドウが開く際、他のウィンドウと一緒に表示すると画面が狭くなってしまうので、大きく表示したい場合は別ウィンドウで表示すると良いかもしれません。
画面にレイアウトが表示された後、確認したい箇所をクリックすると細かい情報が表示されます。
Layout Inspector でよく使われる機能を紹介します。
ウィンドウの左側に表示されているのが Component Tree です。
今選択しているレイアウトの階層を一目で確認することができます。また、Component Treeから確認したいレイアウトを選択することも可能です。
ウィンドウの右側に表示されているが Attributes です。
ここには、選択しているレイアウトの属性が細かく表示されます。
レイアウト表示の上、デバイスに青いサイクルのマークが表示されているボタンが Live updates になります。この機能がオンになっていると、繋がっているデバイスやエミュレータの画面が変わると同時に、Layout Inspectorでも画面が切り替わるようになります。
レイアウト表示の右下のボタンから、レイアウトを3Dで確認することができるようになります。
平面だけでは確認が難しいレイアウトの重なりなども、別角度から見ることができるので、視覚的にも構造が分かりやすくなります。
もう一度ボタンを押すと、平面の表示に戻ります。
レイアウトの確認が終わったら、表示しているプロセスの欄を選択し、[Stop Inspector] からLayout Inspectorを終了することができます。
いかがでしたでしょうか。画面のレイアウトはアプリの中でも重要な要素の一つです。Layout Inspector はレイアウトの情報を細かく確認することができる便利な機能ですので、レイアウトのデバッグをする際にぜひ活用してみてください。