デジタルの力で仕事効率アップをサポート。お客様の業務を加速させる。

ブログ

Gitとは?基本的な使い方の紹介

Git, PC, Windows, ツール, 紹介

今やエンジニアにとって必須になったGitですが、今まで使ってこなかった人や、エンジニアとしての勉強を始めたばかりの人にとっては、「どういったものか分からない」、「なんとなく理解はできたけど、使い方がよく分かっていない」ということもあると思います。
そこで今回は、Gitの使い方に関して詳しく解説していきたいと思います。


Gitとは

まずGitとは何かについて説明する前に、「バージョン管理」について説明します。
バージョン管理とはソースコードを始めとしたファイルの変更履歴(バージョン)を管理することです。変更された情報を管理することで、過去の変更箇所の確認、特定時点の内容に戻すといったことが可能になります。

そしてそのバージョン管理を行うためのシステムの一つがGitになります。
バージョン管理システムは他にもありますが、Gitは「分散型」のバージョン管理システムであり、個々人のマシン上にリポジトリを作成して開発を行うことができるという特徴があります。


リポジトリとは

バージョン管理によって管理されるファイルと履歴情報を補完する領域を、リポジトリと呼びます。Gitでは、まず個々人のマシン上にあるリポジトリ(ローカルリポジトリ)上で作業を行い、その後に作業内容をサーバー上などのリポジトリ(リモートリポジトリ)に集約して開発を進めていきます。
今回の内容ではローカルリポジトリ上での操作を紹介しています。
Gitを使った開発ではこの区別が重要になるので、こちらもぜひ覚えておいてください。


Gitの使い方

現在ではGitをGUIツールを使って管理することもできますが、GUIツールがない場合やサーバーに入って作業する際など、そういったツールが使えない場合もあります。
そこで、今回は標準で使えるgitコマンドの使い方を紹介します。また、いきなりたくさんのコマンドを説明しても分かりづらくなってしまうので、基本的なコマンドをピックアップして紹介します。

Gitの初期設定

まずはGitをインストールし、その後以下のコマンドでGitの初期設定を行います。

$ git config --global user.name ユーザー名
$ git config --global user.email メールアドレス

git init

プロジェクトをGitで管理する場合は、まずそのプロジェクトのディレクトリに移動してgit initコマンドで初期化をします。

$ mkdir git-tutorial && cd git-tutorial
$ git init

今回は例として git-tutorial というフォルダを作成し、そこでgit initを使いローカルリポジトリの作成をしています。

git add

初期化しただけの状態では、どのファイルもGitの管理下にないので、まずはバージョン管理をしたいファイルをgit addを使ってインデックスに登録します。

$ git add Hello.txt

git commit

git addで登録した後は、git commitコマンドで変更内容をコミットします。
コミットとは、ファイルの変更内容をローカルリポジトリに残すことで、変更内容などを記述した「コミットメッセージ」を添えて実行する必要があります。

git commit -m "コミットメッセージ"

git commitのコマンドでは、その後に-m “文字列”という様にコミットメッセージを記述する必要があります。

git status

git statusコマンドではディレクトリやインデックスの状態を確認することができます。
実際の動きを確認するために、先ほどのHello.txt”を編集した状態でgit statusコマンドを打ちます。

$ echo "good morning" > Hello.txt

すると以下のようなメッセージが表示されます。

$ git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   Hello.txt

Changes not staged for commitと表示されていますが、これはGitの管理下にあるファイルで、差分があるが、git addされておらず、次回コミットの対象になっていないものがあると表示されます。

これをgit addすると、以下のように表示が変わります。

$ git add Hello.txt

$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   Hello.txt

Changes to be committed と表示され、変更後にaddされ、次回コミットの対象に含まれているファイルを表示してくれます。

このように、git status で現在の状態を確認することができます。

git diff

git status はディレクトリやインデックスの状態を確認することができますが、実際に変更などがあった場合に、どこが変更されたのかという差分を確認するには git diffコマンドを使用します。
先ほどの状態でgit diffを使うと以下のように表示されます

$ git diff --cached Hello.txt
diff --git a/Hello.txt b/Hello.txt
index b016251..b1eb873 100644
--- a/Hello.txt
+++ b/Hello.txt
@@ -1 +1 @@
-こんにちは
+good morning

Hello.txtの中の「こんにちは」という文字列が削除 (-) され、「good morning」という文字列が追加 (+) されたということが分かると思います。
ちなみに例のような git add 済みのファイルは git diff の後に –cached オプションが必要になります。

git log

コミットを行うとそのたびに、バージョンが更新されます。その時点までの記録したコミットログ(バージョン履歴)は git log で以下のように確認することができます。

$ git log
commit 9c4ae3ff92faa7e8818a04535d6ca97189495148 (HEAD -> main)
Author: ユーザー名 <メールアドレス>
Date:   Wed Dec 14 13:14:09 2022 +0900

    commitします

commit cf9f0b9fa21dd4d6c047d85a8c0b80624a6cd231
Author: ユーザー名 <メールアドレス>
Date:   Wed Dec 14 11:54:33 2022 +0900

    文字列の追加

commit f51f8800cd3c7d81de7a8e21858ba9e1670bc5d1
Author: ユーザー名 <メールアドレス>
Date:   Wed Dec 14 11:41:53 2022 +0900

    first commit

コミットを行った日時と、コミットメッセージが表示されます。
commit の後に続いて表示されているのが、コミットハッシュと呼ばれるもので、コミットを一意に識別するためのものになります。

checkout

履歴をさかのぼって、特定のバージョン時点の状態にするには、チェックアウト機能を使います。
先ほどの git log で出てきた表示に(HEAD -> main)と記載されているものがありましたが、HEADというのが、現在参照しているバージョンで、mainとあるのがブランチ名になります。

ここから特定のバージョンに移動する際には git checkout コマンドを使います。checkeout の後には該当のコミットハッシュを入力します。

$ git checkout f51f8800cd3c7d81de7a8e21858ba9e1670bc5d1

$ git log
commit f51f8800cd3c7d81de7a8e21858ba9e1670bc5d1 (HEAD)
Author: ユーザー名 <メールアドレス>
Date:   Wed Dec 14 11:41:53 2022 +0900

    first commit

checkout をした後にlogを確認すると該当のバージョンにHEADの表示が移っているのが分かると思います。

git reset

もし、Git のコマンドを間違えて実行してしまったという場合には、git resetコマンドでその作業をやり直すことができます。
例えば、間違えてgit addしてしまったファイルを取り消す際には “git reset HEAD ファイル名” または “git reset” で一括取り消しをすることができます。
間違えて行ったコミットを取り消す場合は “git reset HEAD” を使って行うことができます。

# addしたファイルの取り消し
$ git reset HEAD ファイル名

# addしたファイルの一括取り消し
$ git reset

# commitの取り消し
$ git reset HEAD

まとめ

いかがでしたでしょうか。Gitの使い方を覚えておくと、ソースコードの管理ができたり、チームでの開発も効率的に行うことができるようになります。
Gitの内容に限りませんが、知識として学ぶだけでなく実際に使ってみることで、より理解が深まると思いますので、今回の内容を参考にして皆さんも使ってみてください。




【Confluence】覚えておきたいエディターの使い方

BtoB, Confluence, PC, ツール, 紹介

前回、情報共有ツールであるConfluenceがどういったものなのか、どのような特徴があるのか解説しました。ただし、特徴が分かっていざ使ってみようとしても、使い方をよく分かっていないと、うまく活用できないということがあると思います。
そこで今回は、Confluenceの主な機能である、ページを編集する際に使うエディターの使い方について詳しく解説したいと思います。


ページの作成

エディターを使うにはまず、ページを作成する必要があるので、左のサイドバーからページを作成しましょう。


エディターの使い方

では早速エディターの使い方について説明していきます。
一般的な文章作成ツールでも使われるような機能も画面上部のバーに表示されていますので、そのような機能は感覚的に使うことができると思います。
なので、今回はそのバーに表示されている機能の中で重要なものについて解説していきたいと思います。

画面上部のツールバー

テキストスタイル

こちらの機能も一般的に使われている機能ではあると思いますが、Conflueceではテキストの大きさを、ノーマルテキストと見出し1~6に分けて設定することができます。
これによって内容が見やすくなるのはもちろん、後述の目次機能ではこれをもとに自動で目次を作成してくれます。

テキストの大きさを一覧から選択
見出しによって大きさも変わる

アクションアイテム

四角にチェックがついたマークの機能は、アクションアイテムと呼ばれる機能になります。
これは、例えばチーム内でタスクを割り当てるとき等に使う機能です。アクションアイテムでタスクを決めておいて、それが終了したらチェックを付けるという様にして、どういったタスクが残っているか等を分かりやすく確認することができるようになります。

終わったらチェックマークを付けることが可能

メンション

@の機能は、メンション機能になります。@の後に名前を続けて特定の人をメンションするという機能はConfluenceに限らず、様々なツールで活用されていると思いますが、Confluenceでは同じチームの人にメンションしたい時に使われます。
また、先述のアクションアイテムの画像にあったように、組み合わせて使うことで、このタスクが誰に割り振られたものなのかを分かりやすくするといったことができます。

四角の中に十字が入ったマークは、表(テーブル)を作成する機能です。
ボタン一つで表を作成することができ、列や行を増やしたり減らしたりといった基本的な操作も簡単に行うことができます。

ボタン一つでもこのような枠を作ることができる
セル右側のマークを押すことで、セルや列、行の操作ができる

レイアウト

黒い長方形が二つ並んだマークはレイアウトと呼ばれる機能になります。
これによって、ページを「セクション」というひとかたまりで管理できるようになり、ブログのようにレイアウトを調整することができるようになります。
セクションの形はレイアウトの下の表示から選択することができ、場合によって使い分けることも可能です。

レイアウトでセクション毎に内容を入力することが可能

+ボタン

画面の+ボタンからは、上のバーに表示しきれない、様々な機能を挿入することができます。
その機能の数は膨大で、拡張することによりさらに増えていくこともあります。
ただし、この機能すべてが頻繁に使われるものというわけではないので、この中から一部抜粋して紹介していきます。

+ボタンでその他の機能も使える

目次

目次はその名の通り、ページ内の見出しをもとに目次を作成してくれる機能になります。
見出しの大きさに合わせてインデントも調整してくれるので、わざわざ自分で調整する必要などがありません。
ただ、縦に並べるか横に並べるか、どこまでの見出しを目次で表示するか等の細かい調整も可能ですので、場合によって調整すると、より見やすい目次を作ることができます。
注意点として、編集画面では目次がどのように表示されるか確認できないので、まずはプレビューで表示を確認してから公開するようにしましょう。

見出しに合わせた目次が挿入される
目次の細かい設定も可能

情報パネル

情報パネルは、テキストに対してマークや色などを付けて、注意を引くことができる機能です。
画像のように、あらかじめマークが用意されており、テキストの内容に合わせて使うマークを選択することで、より確認しやすくなります。

内容によって、使い分けて表示することが可能

カレンダー

カレンダーはその名の通り、日付を入力することができる機能です。
カレンダーの表示が出てくるので、わざわざ入力しなくてもクリックするだけで日付を入力することができます。

日付をカレンダーから選択して挿入できる

スラッシュコマンド

最後にスラッシュコマンドについて説明します。
スラッシュコマンドとはショートカットキーのようなもので、「/」を入力することで、Confluenceの機能をすぐに挿入することのできる機能です。
これを使いこなせるようになれば、マウスで選択する手間が減り、作業効率が格段に上がります。

「/」を入力すると機能が表示される

また、機能の表示の右側にある記号は、「/」と組み合わせることで、その機能を挿入できるものになります。
例えば「/@」と入力することで、マウスで選択しなくてもメンション機能が挿入されます。
よく使う機能については、このショートカットはぜひ覚えておきましょう。


まとめ

いかがでしたでしょうか。エディターで可能なことはたくさんありますので、一度で覚えきるのは難しい思います。なので、まずは主要な使い方を覚えてから必要に応じて色々試してみると、使いやすい便利な機能が見つかったりすると思いますので、ぜひ今回の内容を参考にしてみてください。




Confluenceとは?その特徴を詳しく解説

BtoB, Confluence, PC, ツール, 紹介

社内の情報管理を適切に行うために、社内wikiやナレッジ管理ツールなどと呼ばれるツールを導入しようと考えている企業は多いと思います。
ただし、現在ではそれらのツールも多種多様であり、どのツールがどういった機能を持っているのかが気になっている方も多いのではないでしょうか
そこで今回は、その中でもAtlassian社が提供しているConfluenceについて、どういったツールなのかを詳しく解説していきたいと思います。


社内wiki、ナレッジ管理ツールとは

まずは、最初に出てきた社内wikiやナレッジ管理ツールという言葉について簡単に説明したいと思います。
情報共有ということだったら、社内チャットでやり取りをしたり、プロジェクト共有ツールを使って行っているという企業もあるかもしれません。
しかし、チャットでは気軽にやり取りできるという利点があるものの、情報がすぐ流れて行ってしまうため、長期的に利用される情報を共有することには向いておらず、プロジェクト共有ツールもプロジェクト毎の内容を管理するものになりますので、長期的、汎用的に利用される情報の共有をするには少し不便です。
そこで、そういった長期的に使われるマニュアルや議事録、業務ノウハウといった情報を管理するために使用されるのが、今回紹介するConfluenceのような社内wikiやナレッジ管理ツールと呼ばれるツールになります。


Confluenceとは

ConfluenceはオーストラリアのAtlassian社が提供する、チームのナレッジやノウハウの一元管理ができる情報共有ツールです。
また、情報管理だけでなく、マニュアルや議事録をドキュメント形式で作成することも可能です。


Confluenceの特徴

では、Confluenceの特徴について説明します。

簡単に記事を作成できる

Confluenceの特徴として、様々な種類の記事を簡単に作成できるという点があります。
一から記事を作っていくとなると、その内容によってフォーマットを変えたりする必要があると思いますが、Confluenceには会議向けの議事録、企画書、マーケティング、製品要件など豊富な種類のテンプレートが用意されています。

豊富なテンプレートの中から選ぶことができる

階層構造でコンテンツを管理できる

Confluenceでは、基本的にスペースという項目を作ってから、その中にページという単位でコンテンツを作成することができます。ページの下にさらにページを作るということも可能であり、トピック毎に見やすくまとめることができます。
メインメニューでそれぞれの階層構造を確認したり、作ったページを移動したりすることもできるため、簡単に管理ができるようになっています。

ページの階層構造

コメント機能が充実している

Confluenceで作成した記事にはコメントを入力することができます。それによって、記事の内容についてのやり取りをすることも可能です。記事全体ではなく、記事の一部にコメントを付ける「インラインコメント」という機能もあるため、より分かりやすくやり取りをすることもできます。
また、「いいね」機能を使ってリアクションのみをするということもできます。

ページに対してコメントを付けることが可能

「ウォッチ」で通知を受け取れる

気になるページがある場合は、「ウォッチ」という機能を使うことで、更新があった際にメールで通知を受け取ることができます。これによって、特定の内容について最新情報をすぐに確認することができるようになります。

ページの右上からウォッチの設定が可能

他アプリケーションと連携できる

Confluenceは同じAtlassian社の製品であるJiraやTrelloだけでなく、GoogleドライブやSlackなどと連携することが可能であり、用途の幅をさらに広げて使うことなども可能です。
その他にも、Confluenceの機能を拡張するマクロなども提供されていますので、Confluenceで使いたい機能を追加するということも可能です。


まとめ

いかがでしたでしょうか。Confluenceを使うことで、社内の情報は格段に管理しやすくなると思います。それによって、必要な書類を探す手間が省けたり、会社全体での情報共有が簡単にできるようになったりと、普段の業務が効率的に行えるようになると思いますので、ぜひ導入を検討してみてはいかがでしょうか。




【Android Kotlin】MVVM+DataBinding+LiveData+ Coroutine+Flow サンプル

Android, Androidstudio, Kotlin, PC, Realm, Windows, 紹介

前回、DataBindingについて解説させていただきましたが、その際にfindViewByIdよりもDataBindingが推奨されているという内容を記載しました。
それと同じように、使っていた技術よりも推奨されるものが出てきたり、新しい考え方であったり、アプリ開発をより効率的に行えるような、便利な機能がどんどん登場しています。
そこで今回は、以前作成したアプリを便利な機能を使って改良し、そこで使ったいくつかの機能について、それぞれ解説していきたいと思います。


アプリの変更点

今回は、前々回のブログで紹介したRealmにデータを保存してそれを表示するアプリに修正を加えたものを使って解説しますので、まずはどのよう変更点があるかコードを見ながら説明します。

修正前のアプリの詳しい内容についてはブログで紹介していますので、まだ見ていないという方はそちらもご覧ください。

https://ictdoctor.jp/%e3%80%90kotlin%e3%80%91realm%e3%81%ab%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e4%bf%9d%e5%ad%98%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95%e3%82%92%e8%a7%a3%e8%aa%ac%ef%bc%81%e3%80%90realm%e3%80%91/

機能の追加

アプリの機能自体は修正前とほとんど変わらず、データをrealmに保存して、保存した内容を表示するものですが、新しい機能として「保存」ボタンを押した後に入力したテキストを消去するかどうかの選択肢を表示するようにしました。

保存完了の表示と選択肢

MainActivity.kt

まずはMainActivityの変更点から紹介します。
大きく変わった点として、findViewByIdを使用していた箇所をDataBindingに変えてレイアウトと連携させています。
加えて、今回新しく追加した「保存」ボタンを押した後の表示といった各種イベントの登録を行っています。

package com.example.sample_realm

import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.example.sample_realm.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private val viewModel: SampleViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // レイアウトファイルへ
        // viewModel(this@MainActivity.viewModel)と
        // lifecycleOwner(this@MainActivity)を
        // (binding = it)連携させる
        ActivityMainBinding.inflate(layoutInflater).apply {
            viewModel = this@MainActivity.viewModel
            lifecycleOwner = this@MainActivity
        }.let {
            binding = it
            viewModel.binding = it
            setContentView(it.root)
            // アダプターインスタンス作成
            viewModel.sampleAdapter = SampleListAdapter(
                inflater = layoutInflater
            )
            // レイアウトファイルのid/sampleListへ連携させる
            it.sampleList.adapter = viewModel.sampleAdapter
        }

        // Realのイベント設定
        viewModel.setRealmEvents()

        // layoutファイル 各種イベント登録
        collectFlow()
    }

    // layoutファイル 各種イベント登録
    private fun collectFlow() {
        viewModel.apply {
            lifecycleScope.launchWhenStarted {
                clickWriteFlow.collect {
                    AlertDialog.Builder(this@MainActivity)
                        .setCancelable(false)
                        .setMessage("正しく保存できました\n入力欄を初期化しますか?")
                        .setNegativeButton("しない") { _, _ ->
                            // No処理
                        }
                        .setPositiveButton("する") { _, _ ->
                            // Yes処理
                            liveDataTextLd.value = ""
                        }
                        .show()
                }
            }
        }
    }

}

SampleListAdapter.kt

ListAdapterで大きな変更点は特にありませんが、以前はこの中にあったViewHolderがなくなって、新しくViewHolderのクラスを作って独立させています。

package com.example.sample_realm

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.sample_realm.databinding.ItemSampleBinding

class SampleListAdapter(
    private val inflater: LayoutInflater
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private val sampleList = mutableListOf<String>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SampleViewHolder =
        SampleViewHolder.create(inflater, parent, false)

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        (holder as SampleViewHolder).bind(sampleList[position])
    }

    override fun getItemCount(): Int = sampleList.size

    fun updateSampleList(sampleList: List<String>) {
        // 一度クリアしてから新しいメモに入れ替える
        this.sampleList.clear()
        this.sampleList.addAll(sampleList)
        // データに変更があったことをadapterに通知
        notifyDataSetChanged()
    }
    
}

SampleViewHolder.kt

ViewHolderは先述の通り、ListAdapterの中に含めていたものを新しいクラスとして作成しています。
記述してある処理自体は大きく変わっていませんが、DataBindingに合わせて記述の仕方が変わっています。

package com.example.sample_realm

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.sample_realm.databinding.ItemSampleBinding

class SampleViewHolder private constructor(
    private val binding: ItemSampleBinding
) : RecyclerView.ViewHolder(binding.root) {

    companion object {
        fun create(
            inflater: LayoutInflater,
            parent: ViewGroup,
            attachToRoot: Boolean
        ) = SampleViewHolder(
            ItemSampleBinding.inflate(
                inflater,
                parent,
                attachToRoot
            )
        )
    }

    fun bind(
        sample: String
    ) {
        binding.sampleTextView.text = sample
    }

}

SampleViewModel.kt

修正にあたって、新しく作成されたクラスになります。後述するMVVMの設計モデルに則ってRealm関係の処理やクリックした際の処理を記述しています。また、Coroutineとしての処理を記載し、API通信などを追加できるようにしたり、変数に値をセットしたりしています。

package com.example.sample_realm

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.sample_realm.databinding.ActivityMainBinding
import io.realm.Realm
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch

class SampleViewModel: ViewModel() {

    lateinit var binding: ActivityMainBinding
    lateinit var sampleAdapter: SampleListAdapter
    private val realm = Realm.getDefaultInstance()

    // LdプレフィックスでLiveDataと分かるように記載
    val liveDataTextLd = MutableLiveData<String>()

    // FlowプレフィックスでSharedFlowと分かるように記載
    val clickWriteFlow = MutableSharedFlow<Unit>()

    // イニシャライズ
    init {
        initInputInfoData()
    }

    private fun initInputInfoData() {
        // コルーチンとして処理開始
        viewModelScope.launch {
            runCatching {
                // API 通信などここでTry
            }.onSuccess {
                // set data
                liveDataTextLd.value = ""
            }.onFailure {
                // エラー
            }.also {
                // 後処理
            }
        }
    }

    // 書込みボタンクリックイベント
    fun onClickWrite() {
        val text = liveDataTextLd.value.toString()
        //テキストが空の場合には無視をする
//        if (value.isEmpty()) return
        if (text.isEmpty()) return
        viewModelScope.launch {
//            putData(liveDataTextLd.value.toString())
            putData(text)
            clickWriteFlow.emit(value = Unit)
        }
    }

    private fun putData(value: String) {
        //テキストが空の場合には無視をする
//        if (value.isEmpty()) return

        // Realmのトランザクション
        realm.executeTransactionAsync {
            //DataListのオブジェクト作成
            val data = it.createObject(DataList::class.java)
            //nameに先ほど入力されたtextを入れる
            data.name = value
            //データの上書きをする
            it.copyFromRealm(data)
        }
    }

    fun setRealmEvents() {
        // DBに変更があった時に通知が来る
        realm.addChangeListener { it ->
            //変更があった時にリストをアップデートする
            val list = it.where(DataList::class.java).findAll().map { it.name }
            //UIスレッドで更新する
            binding.sampleList.post {
                sampleAdapter.updateSampleList(list)
            }
        }

        // 初回表示の時にメモ一覧を表示
        realm.executeTransactionAsync {
            val list = it.where(DataList::class.java).findAll().map { it.name }
            // UIスレッドで更新する
            binding.sampleList.post {
                sampleAdapter.updateSampleList(list)
            }
        }
    }

}

activity_main.xml

DataBindingをつかってViewModelと結びついています。これによって、EditTextに入力されたデータがViewModelのLiveDataでも使用可能になったり、ViewModelのメソッドにアクセスできるようになっています。

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>

        <variable
            name="viewModel"
            type="com.example.sample_realm.SampleViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <EditText
            android:id="@+id/sample_edit_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:hint="テキストを入力してください"
            android:text="@={viewModel.liveDataTextLd}"
            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:onClick="@{() -> viewModel.onClickWrite()}"
            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/sampleList"
            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>
</layout>

使った機能や設計モデルの紹介

コードを見ながらどのような変更があったのか、というのを簡単に説明しましたので、続いてはそこで使った機能や設計モデルについて詳しく紹介していきたいと思います。

MVVM

ViewModelの説明にあったように、MVVMの設計モデルを使った形に変えています。
MVVMはModel, View, ViewModelの頭文字をとったもので、MVCから派生した設計モデルになります。
MVCと同じ部分もありますが、MVVMのそれぞれについて解説していきます。

Model

Modelに関しては、MVCと同じくシステムの中のビジネスロジックを担当している部分になります。データの処理を行って、データの変更をViewに通知したりします。

View

ViewもMVCと同じ役割で、Modelが扱っているデータを取り出して、UIへの出力などを行っています。

View Model

ViewModelはViewとModel間の伝達や、状態の保持を担当します。

今回のサンプルでは、新しくViewModelのクラスを作成し、それぞれとデータのやり取りを行っています。

DataBinding, LiveData

DataBindingは前回のブログで紹介しましたが、その際は外部からViewの表示を変えることができるという単方向のみの説明でした。しかし、DataBindingには双方向でのデータのやり取りをする機能もあります。
双方向の場合は例にあるように “@={viewModel.liveDataTextLd}” という様に@の次に “=” を入力する必要があります。これによって、Viewからもデータを送るということが可能になります。
また、その際に LiveData というデータを監視するクラスを使用することで、テキスト入力欄に変更があるたびに、自動でデータの更新を行ってくれます。

Coroutine

Coroutineは非同期処理を簡略化することができるデザインパターンのことです。
今回の例では、非同期処理をする必要がほとんどありませんでしたが、コードを紹介していた時にも触れたように、メインの機能と合わせて、API通信をする時等に使用すると非常に役立つものになっています。

Flow

Flowは先ほど紹介した Coroutine の一種であり、サンプルでは MutableSharedFlow として実装されていたものになります。今まで使われていたRxと同じような動きをすることが可能で、複数の値を順次出力できるため、データベースからリアルタイムで更新情報を受け取る際などに便利な機能です。
サンプルではクリックされた際に、MainActivityのイベント登録処理にデータを渡しています。


まとめ

いかがでしたでしょうか。説明を読んだだけでは理解が難しい部分もあると思いますが、自分でそれぞれの機能を使ってみるとより理解が深まりますので、アプリ開発の際にはぜひ活用してみてください。




【Kotlin】
DataBindingを
利用しよう!

Android, Androidstudio, Kotlin, PC, Windows, 紹介

今までKotlinを使ったアプリ開発において、レイアウトとコードを結びつけるときには findViewById が使われてきました。
もちろん、今でもそれを使うことは可能ですが、現在では Data Binding を使うことが推奨されています。機能としても、 Data Binding の方が優れている点が多いため、使い方を理解しておくと、これからのアプリ開発にも必ず役に立つと思います。

そこで今回は、それの使い方について、例を交えながら解説していきたいと思います。


DataBindingとは

まずは、DataBindingが何かについて簡単に説明します。

DataBindingはGoogleが提供しているJetPackのコンポーネントであり、モデルオブジェクトとレイアウトを結びつける仕組みになります。
これによって、Viewに対する操作をView上で記述できるようになります。

これを使うメリットとしては、Nullセーフである点や型安全という点、findViewByIdの記述をより簡潔に書くことができるので、コードが読みやすくなるといった点があります。


DataBindingの使用方法

では実際に簡単なアプリを作成して、DataBindingの使い方を解説していきたいと思います。

サンプルアプリの紹介

今回ア例として作成するアプリがこちらになります。
内容としては、画面に文字列を表示するだけの簡単なアプリです。

画面にHello!と表示する

サンプルアプリの作成

プロジェクトの作成

まずはプロジェクトを作成します。
今回は画面に文字を表示するだけなので、Empty Activityを選択して、「Sample DataBinding」という名前で作成しました。

Databindingの有効化

まずは、DataBindingを有効化して使えるようにします。
build.gradle(:app)を開いて、以下のようにコードを記述してください。

android {
    namespace 'com.example.sampledatabinding'
    compileSdk 32

    // 以下のコードを記述
    buildFeatures {
        dataBinding true
    }

これでDataBindingのセットアップは完了です。

データオブジェクトの準備

続いて、データオブジェクトを用意します。
今回は文字列を表示するだけのアプリなので、textだけを定義したDataクラスを作成しています。

android {
    namespace 'com.example.sampledatabinding'
    compileSdk 32

    // 以下のコードを記述
    buildFeatures {
        dataBinding true
    }

レイアウトの変更

続いて、DataBindingを使用するには、レイアウトの構造自体を変える必要があるので、activity_main.xmlファイルを開いて、以下のようにコードを書き換えてください。

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <variable
            name="data"
            type="jp.co.chrono.sampledatabinding.Data" />

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="jp.co.chrono.sampledatabinding.MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{data.text}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Android Studioを使用している方は、上から2行目の<android.constraintlayout…>と書かれているところをクリックすると、DataBindgingに適した形に変更するかの選択肢が出てくるので、それを選択すると、自動でレイアウトの構造を変更してくれます。

ここで、重要なのが<data>タグで囲まれた記述と、<TextView>タグの21行目 android:text=”@{data.text}” と書かれている箇所になります。

まず、<data>タグで囲まれた部分ですが、ここではDataBindingしたい変数の定義を行っています。
「name」には変数名を、「type」には変数の型を指定することができます。
変数名は今回 “data” とし、型は先ほど作成したDataクラスを指定しています。これによって、Viewの中から “data” というメンバーのデータにアクセスできるようになります。

続いて android:text=”@{data.text}” と書かれた箇所ですが、これで、dataの中のtext変数に入っている文字列をTextViewのTextとして表示できるようになります。

MainActivityの実装

モデルとレイアウトの準備ができたので、最後にMainActivityに追加で記述していきます。ファイルを開いて以下のコードを記述してください。

package jp.co.chrono.sampledatabinding

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.sampledatabinding.R
import com.example.sampledatabinding.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        val data = Data("Hello!")
        binding.data = data
    }
}

MainActivityでDataBindingを使用するには、 setContentView() の代わりにDataBindingUtilsetContentView を使います。
これによって、ActivityMainBinding というクラスのオブジェクトを取得することができます。
このBindingオブジェクトはレイアウトファイルそのものをオブジェクト化したようなものであり、先ほどレイアウトファイルで定義した変数を使用することができます。
よって、例のように binding.data に文字列を代入することが可能になります。

実行結果

実際にアプリを起動すると、最初に示した例のように、MainActivityで代入した文字列を画面に表示できているのが確認できると思います。
findViewByIdを使っていた場合と違って、レイアウトファイルで表示する文字を指定しなくても、任意の文字列を表示できるということが分かったと思います。


まとめ

いかがでしたでしょうか。今回紹介したDataBindingの使い方はかなり初歩的なものにはなりますが、実際に作成してみることで、DataBindingの考え方の理解が深まると思いますので、ぜひ参考にしてみてください。




1 2 3 4 5 6 19