クラス図

クラス関係

矢印でクラス同士を結ぶ事ができる。 この際、その関係の種類によって矢印の形が異なる。

関係 意味 備考
Extension 継承 f:id:yossan2:20210826224743p:plain
Aggregation (集約) has-a 授業(親)と生徒(子)といった関係を表す。また授業を消したからと言って、生徒は消えない。 f:id:yossan2:20210826224737p:plain
Composition part-of 家(親)と部屋(子)といった関係を表す。部屋は家と切り離して存在しない f:id:yossan2:20210826224740p:plain

Note: Aggregation vs Composition

  • 親を消したら子も消えるのかどうか
    • 消える → Composition
    • 消えない → Aggregation

参照

https://www.ogis-ri.co.jp/otc/swec/process/am-res/am/artifacts/classDiagram.html#CompositionAssociations

https://www.visual-paradigm.com/guide/uml-unified-modeling-language/uml-aggregation-vs-composition/

https://www.itsenka.com/contents/development/uml/class.html

https://plantuml.com/class-diagram

カスタムコルーチンスコープの作成

kotlin.github.io

CoroutineScopeは実装することが出来る。

interface CoroutineScope

CoroutineScope概要

launchasyncといった全てのコルーチンビルダーはCoroutineScopeを拡張し、全ての要素とキャンセルを自動的に伝播するために、そのcoroutineContextを継承する。

単独のスコープインスタンスを取得する方法は、CoroutineScope()もしくはMainScope()ファクトリ関数である。 これらが必要なくなった際は、スコープのキャンセルに対して注意を取り計らう。

追加的なcontext要素は、[plus](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/plus.html)演算子を使うことで追加することが出来る。

カスタムコルーチンの作成

import kotlinx.coroutines.*
import kotlin.coroutines.*

class CustomScope : CoroutineScope {
    // ルートjob
    val job = Job() 
    override val coroutineContext: CoroutineContext get() = job // + Dispatchers.IO Dispacherを指定しなかった場合は、Dispachers.Defaultが使用される

    fun <T> delayRun(f: ()->T): Job {
        // launchメソッドが自動導出される
        return launch {
            delay(1000)
            f()
        }
    }
}
  • launchメソッドなどが自動導出される

Android KTXを

developer.android.com

Android KTXとは

Android JetpackのKotlin拡張をまとめたライブラリ。

以下のKotlinの機能を用いた拡張が用意されている

  • Extension functions
  • Extension properties
  • Lambdas
  • Named parameters
  • Parameter default values
  • Coroutines

サンプル SharedPreference

KTXを用いなかった場合

sharedPreferences
    .edit()
    .putBoolean("key", value)
    .apply()

KTXを用いた場合

sharedPreferences.edit { putBoolean("key", value) }

編集と同時にコミットも出来る

// Commit a new value sychronously
sharedpreferences.edit(commit = true) { putBoolean("key", value) }

ViewModelの生成と初期化方法

ViewModel

import androidx.lifecycle.ViewModel

class UserViewModel(name: String, age: Int, gender: Int) : ViewModel() {
    val name = name
    val age = age
    val gender = gender
}

ViewModelProviderを使う

val viewModel = ViewModelProvider(this, object : ViewModelProvider.NewInstanceFactory() {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return UserViewModel("Tanaka", 27, 1) as T
    }
}).get(UserViewModel::class.java)

Log.d("MainActivity", "${viewModel.name}, ${viewModel.age}, ${viewModel.gender}")

Android KTXを使う

Android KTXでは、Delegated propertiesを使って、ViewModelの生成と初期化、またActivityのViewModelの共有を行うことが出来る。

dependencyの追加

Core KTX

dependencies {
    implementation "androidx.core:core-ktx:1.6.0"
}

Fragment KTX

dependencies {
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02"
}

viewModels

viewModels

val viewModel: UserViewModel by viewModels<UserViewModel>() {
    object : ViewModelProvider.NewInstanceFactory() {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            return UserViewModel("Tanaka", 27, 1) as T
        }
    }
}

参照

ViewModelProvider

https://developer.android.com/reference/android/arch/lifecycle/ViewModelProvider#viewmodelprovider_2

Android KTX

https://developer.android.com/kotlin/ktx

How to instantiate ViewModel in AndroidX

https://stackoverflow.com/questions/54313453/how-to-instantiate-viewmodel-in-androidx

コルーチン Coroutin

コルーチン

使うにあたって

dependencyの追加

https://github.com/Kotlin/kotlinx.coroutines#using-in-your-projects

Gradleの場合

dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'
}

import

App.kt

import kotlinx.coroutines.*

About コルーチン in Kotlin

非同期関数

asyncに相当する関数を生成する。

//  launch内部は非同期で実行される
launch { 
    println("Hello World")
}

生成と実行

コルーチンスコープ内部で生成することが出来る

// コルーチンスコープの生成
runBlocking { // this: CoroutineScope
    // コルーチンの生成 (launchは、CoroutineScopeのメソッド)
    launch { 
    }
}

Job

CoroutineScope.launch()によって生成されるコルーチンはJobとしてその参照を返す。

fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job

カレントスレッドをブロックしないで、新しいコルーチンを起動し、Jobとしてコルーチンの参照を渡す。 このjobがキャンセルされたとき、コルーチンがキャンセルされる。

サスペンド関数

コルーチンの実行を中断する関数await に相当する関数。

suspend修飾子を関数につける。

App.kt

import kotlinx.coroutines.*

// サスペンド関数 (コルーチンを中断する)
suspend fun doWorld() {
    delay(1000L)
    println("World")
}

fun main() {
    runBlocking {
        doWorld() // 完了まで中断する
        println("Hello")
    }
}

/* 出力
World
Hello
*/

コルーチンコンテキスト

インデックスされたElementの集合インスタンスを表す。 コンテキスト同士を結合して新たなコルーチンコンテキストを作ることも出来る

open operator fun plus(
    context: CoroutineContext
): CoroutineContext
(source)
class MyActivity : Activity(), CoroutineScope {

    private val job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

Job

Elementの一種。 コルーチンへの参照を表すコルーチンコンテキスト。

f:id:yossan2:20210627162655p:plain
Job

CoroutineDispatcher

Elementの一種。 コルーチンを実行するスレッドを表すコルーチンコンテキスト。

f:id:yossan2:20210627162722p:plain
CoroutineDispatcher

CoroutineDispatcherとして用意されている。

  • Dispatchers.Default - タスクは、適切なバックグラウンドスレッドに読み込まれるように設計されたCorountineDispatcher。
  • Dispatchers.IO - IOタスクをブロックするスレッドの共有プールに、予め読み込んでおくために設計されたCorountineDispatcher。
  • Dispatchers.Main - メインスレッド上で動作することが保証されたCorountineDispatcher。
  • Dispatchers.Unconfined

コルーチンスコープ

  • コルーチンコンテキストを持つ
  • コルーチンを起動するメソッドを持つ
    • launc
    • async
    • promise
    • ...

生成方法

両者の違いは、CorountineDispatcherが異なる。

  • CoroutineScope() - Dispatchers.Default
  • MainScope() - Dispatcher.Main

まとめ

  • コルーチンコンテキストはElementの集合を表す
  • Jobは、コルーチンへの参照を表すElementであり、コルーチンコンテキスト
  • CorutinDispatherは、タスクを実行するスレッドを表すElementであり、コルーチンコンテキスト
  • コルーチンスコープはコルーチンコンテキストを持つ