Kodiの種類と使用した感想

ラズパイ3をテレビに接続したく、Kodiの種類を色々と試してみた。

LibreELEC

ダウンロード

LibreELEC Downloads – LibreELEC https://libreelec.tv/downloads_new/

インストーラーを使うと便利

使用した感想

評判どおり動作は安定している。

UIをもうすこしイジれたらなぁ

OSMC

ダウンロード

Download - OSMC https://osmc.tv/download/

注意点

インストーラーが用意されているが、自分のMacではSDカードへのインストールが失敗する。 Disk Imagesからイメージファイルを直接ダウンロードして、BalenaEtcherあたりでSDに入れるといい。

使用した感想

デフォルトのUIがすごく見にくくて使いにくかった。

これを使うメリットは何だろか

XBian

ダウンロード

https://xbian.org/getxbian/

使用した感想

XBianというものを初めて知った。
起動した見た目はほぼLibreELECと変わらない。

XBianのダウンロードイメージは以下があった。

Raspberry Pi Raspberry Pi 2 / Raspberry Pi 3 Raspberry Pi 3B+ CuBox-i / Hummingboard

総評

LibreELECが安定している。

XBianもカスタマイズ性が高く、もう少し深く使ってみたい。

ラズパイ3で稼働させているが、ラズパイzeroWに移行したい。

でもzeroWだとテレビに表示されない、PCモニターでは映るのに。
これはどうしたらいいんだろうか

このへんで解決できそう www.raspberrypi.org

Flutterを初めるために

最近、Flutterに注目している。

Android + iOSのアプリが両方作れる!かつ、自分の大好きなマテリアルデザインが使えるためだ。

実際にまだアプリは作っていないけど、Flutterを初めるために良さげな記事を見つけた。

ちょっと古いけど、こにふぁーさんの記事

konifar.hatenablog.com

自分なりにまとめると以下

Dartのキャッチアップ Language Tour | Dart https://www.dartlang.org/guides/language/language-tour

UIライブラリ FlutterはUIをWidgetというパーツを組み合わせて作る。 そして標準で用意されてるWidgetは豊富で、Material Design GuidelineにあるUIは全て用意されている。 実際に作るときにどんなWidgetがあるかを知っておくのがキモで、以下を読んでおくことをオススメ Widget catalog - Flutter https://flutter.dev/docs/development/ui/widgets

開発環境を整えるなら
Android Studio / IntelliJ - Flutter https://flutter.dev/docs/development/tools/android-studio

Flutterのセットアップ
Install - Flutter https://flutter.dev/docs/get-started/install

Code Lab
Building Beautiful UIs with Flutter https://codelabs.developers.google.com/codelabs/flutter/index.html#0

サンプル
flutter/examples at master · flutter/flutter https://github.com/flutter/flutter/tree/master/examples

公式にサポートされているplugins
plugins/packages at master · flutter/plugins https://github.com/flutter/plugins/tree/master/packages

ここらへんを見ておけばアプリを作れるようになるはず

MacでGooglePlayMusicをアプリで聴きたい

ブラウザで聴くのではなく、Macのアプリで聴きたい。

Chromeだとタブ選択したりするのが手間。

ちょっと探してみた。

Radiant Player

radiant-player.github.io

自分も昔から使っていてオススメ

ただし、Mojaveだと起動した瞬間にエラーで落ちる。
解決策は、設定>セキュリティとプライバシー>プライバシー のアクセシビリティにRadiant Playerをドラッグして追加する。
これでMojaveでも起動できるようになる。

GitHubのissueにも話題になってた

Crashes upon open in Mac OS Mojave · Issue #668 · radiant-player/radiant-player-mac · GitHub

Google Play Music Desktop Player

www.googleplaymusicdesktopplayer.com

Radiant Playerがエラーで起動できない時期に見つけたアプリ

こいつはMojaveでもエラーにならず起動できる。

ただ、メモリ使用量が多いという情報もあった。

まぁ聴ければいいという人には問題ないかも

STAMP

freeyourmusic.com

GoogleMusic以外にもいろいろなサービスの音楽が聞ける。
SpotifyとかAppleMusicとかAmazonMusicとか。

ただ、GooglePlayMusicを聴くためのGoogleにログインに失敗して、GoogleMusicは聴けず。。。

なので使ってない。

結論

自分はRadiant Playerがオススメだが、エラーで開けない問題が解決できなければ Google Play Music Desktop Player でいいんじゃね

BotkitがMicrosoftに買収された

自分はBotkitを2017年頃から気に入って使っている。
久々にBotkitのHPをみるとこんな文字が目に入ってきた。

f:id:banbara:20190220120847p:plain

We've reached an agreement to be acquired by Microsoft. More details can be found here.

マイクロソフトが買収することに合意しました。詳細はこちらをご覧ください。

え、MSに買収?

here の先のリンクはこちら

blog.howdy.ai

XOXCOって初めて聞いたな。 Botkitを開発してる会社なんだろうか?

ちょっと調べると、MSに買収された日本語記事も見つけた。

japan.cnet.com

Botkit Studioはどうなるんだろう、と思いHPを見てみると

Please note: Botkit Studio will cease operation on Feb 14, 2019. The features below are now available through Botkit CMS
ご注意ください:Botkit Studioは2019年2月14日に動作を停止します。以下の機能は現在Botkit CMSを通じて利用可能です

botkit.ai

あらら、、、

幸いにBotkit Studioは利用してないのでダメージはないが、ちょっと残念。

MSがBotkitを将来どうするのか心配だな... MSのサービスに統合されて使えなくなる、とならなきゃいいけど。

Raspberry Piに最適なディスプレイ選び

ラズパイで画面を表示するとき、ディスプレイ選びに困ることが多々ある。 とくに、PC用のディスプレイではなく、小型なディスプレイを選ぶ場合だ。 色々調べているうちに、Hacksterで良い記事を見つけたため、日本語訳してみる。

Best Raspberry Pi Displays for Your Project – Part 1 - Hackster.io https://www.hackster.io/francesco_vannini/best-raspberry-pi-displays-for-your-project-part-1-dabc29

ストーリー

Raspberry Piプロジェクトで使用できる最高のディスプレイは何ですか?その質問に答えるためにあなたは実際に前にいくつかの小さな質問に答える必要があるでしょう、そして私はそれが通常の「それが依存する!」に帰結することを恐れます。

この記事は主にRaspberry Pi B +以上のレイアウトに適用されますが、上記の考慮事項の多くは他のモデルにも適しています。

大型または小型のディスプレイを選択し、タッチ機能を必要とするかどうかに関わらず、HDMIコネクタまたはGPIOピンを介して接続します。これらは、最終目標に応じて必要な決定の一部に過ぎません。最終的には、プロジェクトに必要なものと、ディスプレイを接続して駆動するためにプラットフォームに残されるものとのトレードオフになります。

ラズベリーパイは、さまざまな方法でディスプレイに接続できます。通常は、

  • HDMI
  • DSI
  • コンポジットビデオ

HDMI

HDMIはあなたに伝統的なコンピューターモニターとテレビの点でたくさんの選択肢を与えます。HDMI入力を持つものは何でもあなたのために最も確実に動作します。

いくつかのベンダはあなたがあなた自身のディスプレイを構築するためにスクリーン、コントローラと余分な小片を組み立てることを可能にするディスプレイキットを提供します。これらは、カスタムデザインケースまたはフレームにスクリーンを取り付ける必要があるプロジェクトに特に適しています。

Adafruitあなたは画面を取得決議1280から800×480の抵抗タッチスクリーンおよび/または追加の制御ボタン800×およびいくつかのケースでは、「10まで」4から。

https://www.adafruit.com/category/506

Adafruitは他に、HDMI入力だけでなくVGAとビデオコンポジットも提供するコントローラと一緒に標準のラップトップのようなLCDスクリーンを備えたキットを提供しています。これらのコントローラの中には他のLVDSスクリーンをサポートできるものもありますが、9/10は実際の可能性よりも神話です。近いうちにあなたの古いラップトップのLCDを再利用することに頼りません。それでも、これは興味深い可能性であり、プロジェクトに優れた柔軟性を提供します。

例えば、WaveshareのこれらのLCDディスプレイは、さまざまなサイズ(2.8 インチから13.3インチまで)で提供されており、Raspberry Pi、BB Black、およびその他のプラットフォーム用の取り付け穴があります。480×320からHDまでの優れた解像度を提供します。

https://www.waveshare.com/product/mini-pc/raspberry-pi/displays.htm

私はこの記事のために周りの閲覧たので、私も発見されUctronics ディスプレイの独自のラインを提供するように見える、Osoyooはあまりにも非常に同様の表示を販売しています。どちらの場合も、ディスプレイはHDMI入力からの音声を別のアナログ3.5 mmジャックとして提供し、Raspberry PiのGPIOに接続して、ディスプレイをサポートする方法とSPI タッチスクリーンの接続性の両方を提供できるようです。両方の3.5インチディスプレイは60 fpsで480×320の解像度を提供し、480×320と1920×1080の間の何でもの入力を受け入れることができます。2つのディスプレイは不気味に似ています…

Uctronics https://www.uctronics.com/index.php/display.html

Osoyoo http://osoyoo.com/2016/11/20/raspberry-pi-3-5inch-hdmi-touchscreen/

いくつかの他の人は代わりに中国からどこかに来るXPT2046と呼ばれるディスプレイのクローン化または再ブランド化されたバージョンを使用します。それは5インチのディスプレイで、800×480の解像度、抵抗膜方式のタッチスクリーンを持ち、少なくともRaspbianでサポートされているようです。あなたはElecrowのWiki を通してより多くの詳細を見つけることができます。

ElecrowのWiki https://www.elecrow.com/wiki/index.php?title=HDMI_Interface_5_Inch_800x480_TFT_Display

ベンダーによって紹介されている製品のいくつかはクローン製品かリブランドされた製品のどちらかなので、注意して買い物をすることをお勧めします。

コネクタとアダプタ

HDMIコネクタは一般的にかなり面倒で、上記のように特定のアセンブリ用にカスタムHDMIコネクタを作らない限り、場合によってはAdafruit DIY HDMIケーブル部品と一緒にまとめることができるもののようなリボンケーブルの使用を検討したいかもしれません。

Adafruit DIY HDMIケーブル部品 https://www.adafruit.com/?q=DIY%20HDMI%20Cable%20Parts

しかし、あなたが伝統的なモニターを使うつもりなら、それはそれがHDMIよりむしろ他の規格をサポートするのは起こるかもしれません。HDMIもDVIおよびVGAモニタに非常に簡単に接続できることを多くの人が認識していません。これらのディスプレイの1つが座っている場合は、DVI用のアダプタまたはVGA用のコンバータを使用できます。どちらの場合も、オーディオ用にRPiの3.5mmジャックを使用するか、専用のオーディオカード(HAT、pHATなど)を使用する必要があるかもしれませんが、アダプタ/コンバータによっては専用のオーディオジャックをそのまま使用できるものもあります。 HDMIポートの。

代わりにDisplayportを使用したい場合は、HDMIからDisplayportへのアダプタを簡単に見つけることができます。規格は実質的にまったく同じなので、ここでも問題はありません。

DSI

私が知っている限りでは、このポートに接続することができる利用可能な唯一のディスプレイは公式Raspberry Piディスプレイだけです。

発売日にRaspberry Pi財団が発表したこの記事で強調されているように、この7インチディスプレイは以下を提供します。

・RGB 800×480ディスプレイ(60fps) ・24ビットカラー ・FT5406 10ポイント静電容量式タッチスクリーン ・70度の視野角 ・Pi用の取り付け穴付きメタルバックディスプレイ

The Eagerly Awaited Raspberry Pi Display - Raspberry Pi https://www.raspberrypi.org/blog/the-eagerly-awaited-raspberry-pi-display/

ディスプレイ、RPiとHAT、または追加のハードウェアをきちんと組み立てることができるケースがいくつかあります。Pimoroni - Flotillaフレーム、ModMyPiケース、スタンド、oneNineDesignケース、その他似たようなデザイン

Coupé Red Pibow Touchscreen Frame – Pimoroni https://shop.pimoroni.com/products/raspberry-pi-7-touchscreen-display-frame

ModMyPi LTD | ModMyPi - 7" Touchscreen Case and Stand https://www.modmypi.com/raspberry-pi/screens-and-displays/screen-cases/raspberry-pi-7-touchscreen-case--plus-stand

Case for Raspberry Pi Official 7" Touchscreen | The Pi Hut https://thepihut.com/products/raspberry-pi-official-7-touchscreen-case?ref=avgman&variant=15155531396

iQuadIO ボード用のM2Pのような、よりカスタマイズされたソリューション。 Raspberry Pi 7'' Touch Display Bundle with Soundcard and Max2Play (limited edition) | shop.max2play.com https://shop.max2play.com/en/raspberry-pi-bundle-7-display-iqaudio.html

あなたがツールと適性を持っていれば、ThingiverseにもたくさんのDIYソリューションがあります。

Search Thingiverse - Thingiverse https://www.thingiverse.com/search?q=raspberry+pi+display+case&dwh=305c49aa69c0268

私のお気に入りはSmartiPiのケースです。それはLEGOスタッドの有無にかかわらず来て、最近HATとアドオンハードウェアへの保護を提供する裏表紙を加えました。全体的にそれは最高のデザインを持ち、あなたが必要とするであろう機能のほとんどを提供します。

SmartiPi Touch for the Official Raspberry Pi Display https://smarticase.com/collections/all/products/smartipi-touch

あなたがラズベリーパイの公式ディスプレイケースについてもっと知りたいならば読む価値があるそこに市販されているほとんどすべてのケースをカバーする素晴らしい記事フォームAverage Makerがあります。

Raspberry Pi Touchscreen Display Case Options | Average Maker https://averagemaker.com/2016/05/touchscreen-display-case-options.html

コンポジットビデオ

そもそもなぜコンポジットビデオオプションがこれまで提供されてきたのか不思議に思うかもしれません。大成功を収めたにもかかわらず、ラズベリーパイは控え目な起源を持ち、その中心には安価であるように設計されていました。80年代の最初のパーソナルコンピュータの場合のように、コンポジットビデオを提供することで、まだ古いテレビでRaspberry Piを使用することを許可されていない多くの国では、専用モニタを購入する必要がないと考えられていました。

それでは、古いCRTテレビやプロジェクターなどを使うことができること以外に、このタイプの出力に他に何がありますか?

Adafruit は、1.5 インチから7 インチまでの非常に優れた、きれいで小型のNTSC / PALディスプレイを販売しています。彼らは、タッチスクリーンのない安くて陽気なディスプレイか、それ以外の多くのものですが、結局それほど安くはないけれども、彼らは予算を低く抑えるのに良いです。

ビデオコンポジットを使用することのマイナス面は、解像度(NTSC 720×480 60Hzインターレース - PAL 720×576 50Hzインターレース)であり、一般に低品質の画像です。あなたが住んでいる場所に応じて、あなたはNTSCまたはPALの制限に縛られ、そして今日これらの解像度はいくつかのアプリケーションにとってかなり小さいです。

古い26ピンRPiでは、より現代的なものにはRCAケーブルが必要でしたが、以前はオーディオ用に使用されていたA / Vポートに接続するための3.5 mmジャックが必要です。

興味があれば、Raspberry Pi Spyからコネクタについての素晴らしい記事があります。

Raspberry Pi Model B+ 3.5mm Audio/Video Jack - Raspberry Pi Spy https://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-model-b-3-5mm-audiovideo-jack/

どのケーブルを使用するかは、おそらくあなたが必要とするものでしょう。こちらから入手できます。

ModMyPi LTD | A/V Composite Cable - 3.5mm to 3 x RCA - 3m https://www.modmypi.com/raspberry-pi/accessories-198/audio-cables/av-composite-cable-3.5mm-to-3-x-rca-3m

ビデオコンポジットによるスクリーンキャプチャ

画面をキャプチャするためのソフトウェアベースの方法がほとんどありますが、ハードウェアソリューションが最適に機能する場合もあります。HDMIキャプチャキットは安価になってきていますが、Video Composite出力の良い用途の1つは、確かに安価なキャプチャキットを使用してRPiで何をしても録画できることでしょう。

これは教育、ビデオチュートリアルの作成、画面のスナップショットのキャプチャなどに役立ちます。

これらのカードには文字通りたくさんのUSBがありますが、実際にはRasbperry Piと互換性があり、RPiをレコーディングステーションとして使うことができます。それで、あなたはPiを奇妙なPiで録音することになるかもしれません!

TR Computers Video-2-Pi. USB composite video capture grabber for Raspberry Pi. Comes with timelapse video building scripts. Watch CCTV camera on your Pi's desktop. OpenCV3 library compatible.: Amazon.co.uk: Computers & Accessories https://www.amazon.co.uk/Video-2-Pi-microscopes-telescopes-camcorders-compatible/dp/B072Q4MNKM

Kotlin Coroutinesパターン&アンチパターン

Kotlin Coroutinesパターン&アンチパターン

Coroutineを理解するため、以下のサイトを日本語訳しました。 https://proandroiddev.com/kotlin-coroutines-patterns-anti-patterns-f9d12984c68e

目次

  • 非同期呼び出しをcoroutineScopeでラップするか、SupervisorJobを使用して例外を処理します。
  • ルートコルーチンのメインディスパッチャを優先する
  • 不要なasync / awaitの使用を避ける
  • スコープジョブをキャンセルしない
  • 暗黙のディスパッチャを使って中断関数を書かないようにする
  • グローバルスコープの使用を避ける

非同期呼び出しをcoroutineScopeでラップするか、SupervisorJobを使用して例外を処理します

非同期ブロックが例外をスローする可能性がある場合は、try / catchブロックでラップすることに頼らないでください。

val job: Job = Job()
val scope = CoroutineScope(Dispatchers.Default + job)
// may throw Exception
fun doWork(): Deferred<String> = scope.async { ... }   // (1)
fun loadData() = scope.launch {
    try {
        doWork().await()                               // (2)
    } catch (e: Exception) { ... }
}

記の例では、doWork関数はnew coroutine(1)を起動し、これが未処理の例外を投げます。 doWorkをtry / catchブロック(2)でラップしようとしても、まだクラッシュします。

クラッシュを回避する方法の1つは、SupervisorJob(1)を使用することです。

子の失敗またはキャンセルは、SupervisorJの仕事を失敗させることはなく、他の子にも影響しません。

val job = SupervisorJob()
val scope = CoroutineScope(Dispatchders.Default + job)
// 例外をスローする可能性があります
fun doWork(): Defferd<String> = scope.async { ... }

fun loadData() = scope.launch {
    try {
        doWork().await()
    } catch (e: Exception){ ... }
}

ノート:SupervisorJobを使用してCoroutineScopeで非同期を明示的に実行した場合にのみ機能します。 そのため、以下のコードはasyncがparent coroutine(1) の範囲内で起動されるため、アプリケーションをクラッシュさせます。

val job = SupervisorJob()
val scope = CoroutineScope(Dispatchers.Default job)

fun loadData() = scope.launch {
    try {
        async { // (1)
            // 例外をスローする可能性があります
        }
    } catch (e: Exception) { ... }
}

クラッシュを避けるためのもう1つの方法は、coroutineScope(1)を使ってasyncをラップすることです。 async内部で例外が発生すると、外部スコープに触れることなく、このスコープ内に作成された他のすべてのコルーチンをキャンセルします。 (2)

val job = SupervisorJob()
val scope = CoroutineScope(Dispatchers.Default + job)

// 例外をスローする可能性あり
fun doWork(): Deferred<String> = coroutineScope {   // (1)
    async { .... }
}

fun loadData() = scope.launch {                     // (2)
    try {
        doWork().await()
    } catch (e: Exception) { ... }
}

あるいは、非同期ブロック内で例外を処理することもできます。

ルートコルーチンのメインディスパッチャを優先する

バックグラウンドで作業を行い、ルートコルーチン内でUIを更新する必要がある場合は、メイン以外のディスパッチャを使用して起動しないでください。

val scope = CoroutineScope(Dispatchers.Default)          // (1)

fun login() = scope.launch {
    withContext(Dispatcher.Main) { view.showLoading() }  // (2)  
    networkClient.login(...)
    withContext(Dispatcher.Main) { view.hideLoading() }  // (2)
}

記の例では、Default dispatcher(1)のスコープを使用してルートコルーチンを起動します。 このアプローチでは、ユーザーインターフェイスに触れる必要があるたびに、コンテキストを切り替える必要があります(2)。

ほとんどの場合、メインディスパッチャを使用してスコープを作成することをお勧めします。これにより、コードが単純になり、コンテキストの切り替えが明確になります。

val scope = CoroutineScope(Dispatchers.Main)

fun login() = scope.launch {
    view.showLoading()    
    withContext(Dispatcher.IO) { networkClient.login(...) }
    view.hideLoading()
}

不要なasync / awaitの使用を避ける

async機能を使用していてすぐに待つのであれば、これをやめるべきです

launch {
    val data = async(Dispatchers.Default) { /* code */ }.await()
}

コルーチンコンテキストを切り替えてすぐに親コルーチンを中断したい場合はwithContextを使うのが望ましい方法です。

launch {
    val data = withContext(Dispatchers.Default) { /* code */ }
}

パフォーマンス面では大きな問題ではありませんが(asyncが新しいコルーチンを作成して作業を行うと考えられていても)、意味的にasyncはバックグラウンドでいくつかのコルーチンを起動して待機することを意味します。

スコープジョブをキャンセルしない

コルーチンをキャンセルする必要がある場合は、最初にスコープジョブをキャンセルしないでください。

class WorkManager {
    val job = SupervisorJob()
    val scope = CoroutineScope(Dispatchers.Default + job)
    
    fun doWork1() {
        scope.launch { /* do work */ }
    }
    
    fun doWork2() {
        scope.launch { /* do work */ }
    }
    
    fun cancelAllWork() {
        job.cancel()
    }
}

fun main() {
    val workManager = WorkManager()
    
    workManager.doWork1()
    workManager.doWork2()
    workManager.cancelAllWork()
    workManager.doWork1() // (1)
}

上記のコードの問題は、jobをキャンセルすると、完了状態になることです。完了したジョブの範囲内で起動されたコルーチンは実行されません(1)。

特定のスコープのすべてのコルーチンをキャンセルしたい場合は、cancelChildren関数を使用できます。 また、個々の仕事をキャンセルする可能性を提供するのは良い習慣です(2)。

class WorkManager {
    val job = SupervisorJob()
    val scope = CoroutineScope(Dispatchers.Default + job)
    
    fun doWork1(): Job = scope.launch { /* do work */ } // (2)
    
    fun doWork2(): Job = scope.launch { /* do work */ } // (2)
    
    fun cancelAllWork() {
        scope.coroutineContext.cancelChildren()         // (1)                             
    }
}
fun main() {
    val workManager = WorkManager()
    
    workManager.doWork1()
    workManager.doWork2()
    workManager.cancelAllWork()
    workManager.doWork1()
}

暗黙のディスパッチャを使って中断関数を書かないようにする

特定のコルーチンディスパッチャからの実行に依存するサスペンド機能を書かないでください。

suspend fun login(): {
    view.showLoading()
    
    val result = withContext(Dispacher.IO) {
        someBlocikngCall()
    }
    view.hideLoading()
    
    return result
}

上記の例では、login関数はサスペンド関数で、メイン以外のディスパッチャを使用するコルーチンから実行するとクラッシュします。

launch(Dispatcher.Main) {     // (1) no crash
    val loginResult = login()
    ...
}

launch(Dispatcher.Default) {  // (2) cause crash
    val loginResult = login()
    ...
}

CalledFromWrongThreadException:そのビューに触れることができるのは、ビュー階層を作成した元のスレッドだけです。

任意のコルーチンディスパッチャから実行できるように中断関数を設計します。

suspend fun login(): Result = withContext(Dispatcher.Main) {
    view.showLoading()
    
    val result = withContext(Dispatcher.IO) {  
        someBlockingCall() 
    }
    
    view.hideLoading()
    return result
}

これで、どのディスパッチャからもログイン関数を呼び出すことができます。

launch(Dispatcher.Main) {     // (1) no crash
    val loginResult = login()
    ...
}

launch(Dispatcher.Default) {  // (2) no crash ether
    val loginResult = login()
    ...
}

グローバルスコープの使用を避ける

Androidアプリのいたる所でGlobalScopeを使っているのなら、これをやめるべきです。

GlobalScope.launch {
    // code
}

グローバルスコープは、アプリケーションの有効期間全体にわたって動作し、時期尚早にキャンセルされない最上位レベルのコルーチンを起動するために使用されます。

アプリケーションコードは通常、アプリケーション定義のCoroutineScopeを使用する必要があります。GlobalScopeのインスタンスで非同期または起動を使用することは強くお勧めできません。

Androidでは、コルーチンはActivity、Fragment、ViewまたはViewModelライフサイクルに簡単にスコープ設定できます。

class MainActivity : AppCompatActivity(), CoroutineScope {
    
    private val job = SupervisorJob()
    
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job
    
    override fun onDestroy() {
        super.onDestroy()
        coroutineContext.cancelChildren()
    }
    
    fun loadData() = launch {
        // code
    }
}

オランダは残業をしない

会社の同僚のオランダ人からこの動画を紹介された。

www.facebook.com

52秒ほどの短い動画だが、オランダの労働環境の良さについて紹介されている。

その中で出てくる言葉を書き出して日本語訳してみた。

Only 1% of Dutch men work more than 50 hours a week
週50時間以上仕事をしているオランダ人男性はわずか1%です

And the number of women working very long hours is too small to measure
そして、非常に長い時間働く女性の数は測定できないほど少ない

The Dutch spend almost 16 hours a week on leisure and personal care
オランダ人は、レジャーとパーソナルケア(体の手入れ)に週に16時間を費やしています。

Just 0.5% of Dutch people spend longer at work than they should
オランダの人々のうち、定期的に非常に長い時間を働くのはわずか0.5%

The average in OECD countries is 13%
OECD諸国の長い時間働く平均は13%です
※OECD:経済協力開発機構、先進国35か国が参加(日本も加盟)

Working long hours is damaging to health and wellbeing
長時間労働は健康と幸福に害を与えます

More leisure time can improve physical and mental health
余暇時間を長くすると、肉体的および精神的健康が向上する

The fact the Dutch spend time looking after themselves may account for the longer life expectancy
オランダ人が自分たちの世話をするのに時間を費やすという事実は、より長い平均余命を説明するかもしれない

The average Dutch person lives 82 years
オランダの平均寿命は82歳

That's years longer than the OECD average of 80
OECD諸国の平均は80歳です

Could you be healthier by going Dutch?
あなたはオランダ語に行くことによって健康になりますか?

すごいな、オランダ

日本とはえらい違いだ。

いったいどうやったらこんな事が可能なんだろうか。

ちょっと調べてみるか