ツイートで振り返る2021年
まめに振り返りを記録するタイプではないのでツイートを見返しながらザーッと1年を振り返る。 もうちょっとまとめたのは気が向いたらきっとたぶん別途書くぞ📝
1月
今年の目標は、思考の解像度を上げるです。とても解像度の低い目標です。今年で30歳になります。がんばります!
— まきやま (@_rmakiyama) 2021年1月2日
解像度が低かったので達成度は謎である。反省。来年は解像度の高い目標をたてるぞ!
突然だけど30歳までにバンジージャンプを経験したいなと思ったので突然だけどバンジージャンプしにいきたい
— まきやま (@_rmakiyama) 2021年1月2日
忘れてたし達成してない、これ本当にしたいのでメモ 📝
今週はテストをたくさん書いて自己肯定感を高めたとチームに共有してさらに自己肯定感を高めたので2021元気にやっていけそう!
— まきやま (@_rmakiyama) 2021年1月8日
今年は1年を通してテストに入門した1年だった、年始からやっとるな?
あまり時間とれないけど幅を広げるためにちょっと副業してみたいというわがままを思ってる
— まきやま (@_rmakiyama) 2021年1月12日
夏に伏線を回収した 👍🏻
Dagger Hiltがどういうコードを生成してどうやってDIをしているか気になったので基本の部分を紐解いてみました🕵️🏻
— まきやま (@_rmakiyama) 2021年1月23日
Hilt完全に理解した!https://t.co/RVZvvAdYH7
Hiltの記事書いた。Daggerと仲良くなった。
2月
Radiotalkではそれぞれが得意を活かしつつサービスを前に進むることを全部やる気概でやっています!🙌🏻 https://t.co/KRq5TIton0
— まきやま (@_rmakiyama) 2021年2月5日
DroidKaigiでも同じようなこと言ったし、思想としてずっと変わってないな。
🚀 / たった今、@Kickstarter_JP で Moon Adventure, In a Grove and Dokojong | 月面探険・藪の中・ドコジャン のバッカーになりました https://t.co/MV5cDHVl1y
— まきやま (@_rmakiyama) 2021年2月22日
オインクが好きですぐバッカーになったやつ。どれもよかた!
3月
今日のMDG勉強会ではMaterial FoundationのEnvironmentの項について話したんですが、Elevationを使って高さ・奥行きを表現していることについてデザイナーさんが、影で平面に立体を生む手法としては美術と同じで全てに通ずる感じがあると言っていて、すごくいい話が聞けて最高です!
— まきやま (@_rmakiyama) 2021年3月11日
グループ会社の人も巻き込んでMDG勉強会を始めだしたのがこのころ。たくさん話聞けて言い出しっぺの自分が1番楽しんだ気がする 😂
スーパーエンジニアですこんにちは😂
— まきやま (@_rmakiyama) 2021年3月18日
同僚が似顔絵アイコンにしたいと言っていたのでダイレクトなソリューションを提供しました!!w今年から始めた趣味が活きて嬉しい!!🥳 https://t.co/VuMu71LX53
2月3月あたりはiPadでイラスト(写真のトレースメイン)にハマってて楽しかったのでまた再開したい!
4月
ストレングスファインダーでの資質トップが"ポジティブ"だったので前向きな気持ちになった!!!やるぞ!!!
— まきやま (@_rmakiyama) 2021年4月2日
ストレングスファインダーやったのはなんかよかった!
イスだけ持って川辺でNo密でビールで優勝させてもらっているわね…チェアリング最高💃🏻 pic.twitter.com/nUYFE4AP7e
— まきやま (@_rmakiyama) 2021年4月25日
チェアリングに入門した、このビールうまかった 🍺
今日の発表資料です!! #ラジテクhttps://t.co/Cld76Yt5GE
— まきやま (@_rmakiyama) 2021年4月28日
今年の年末層大掃除でだいぶこのモジュール構成に近づいてきた。
5月
30歳になりました!🥳おめでとうございます!ありがとうございます!ネクストステージ感あるけど変わらず楽しくやっていくぞ!🦸🏻
— まきやま (@_rmakiyama) 2021年5月8日
🎉
昨日アプデした個人アプリ、ライブラリ使わずグラフを作ってみたい駆動な機能を追加しました!99%できてたけど3ヶ月ほど寝かせてしまってたのでえいやあでリリース😂Canvas周りと戯れられていい感じだった! https://t.co/DuSQ2TjplO
— まきやま (@_rmakiyama) 2021年5月9日
個人アプリのアプデ、ここで止まっているので来年は手を加えたい気持ちがある。
ニコニコしてます!私です!🥳
— まきやま (@_rmakiyama) 2021年5月21日
Radiotalk Androidエンジニアの牧山の「More Talk!」https://t.co/6zTUWeQyAs
わたしです!たのしそう。
6月
だいたい1年たったけど自分の資料に助けられたので作っててよかった✌🏻https://t.co/PkyXXBco5G
— まきやま (@_rmakiyama) 2021年6月1日
定期的に自分で見返してるのでお気に入り。Compose時代には必要ないんだけれどもw
長らく積読してたけどやっと読破、とってもよかった!
— まきやま (@_rmakiyama) 2021年6月2日
ストーリーマッピングをはじめよう https://t.co/xii5cI5ISs
この本よかったけど振り返り何も書いてないな〜もったいない!
わくわくわくわく😊 / たった今、@Kickstarter_JP で Oink Games + のバッカーになりました https://t.co/O6rMhWeoIz
— まきやま (@_rmakiyama) 2021年6月4日
すぐバッカーになったやつパート2。最近発売されましたね!最高です!!
Jetpack ComposeでTODOアプリを作ってみたけど知らないことだらけの扉が開いてしまった楽しい🦭やっぱりとりあえず手を動かしてみるのは自分にあってるな、いい書き方どんどん模索していきたい👨🏻💻https://t.co/IGSVVoWzP8
— まきやま (@_rmakiyama) 2021年6月5日
Composeの雰囲気をつかめたやつ。やっぱり手を動かすのが好きみたい。
本日の資料です! #potatotipshttps://t.co/mNB7Uj9h2q
— まきやま (@_rmakiyama) 2021年6月23日
ComposeのCanvasも楽しかった!
7月
👏🏻👏🏻 "私自身は、組織を良くするのもあくまでより大きな価値をより早く提供するためというスタンスを持っていますが、同時に健全なプロダクトは健全な組織からしか生まれないという信念も持っています。" https://t.co/D5SkCRTPvx
— まきやま (@_rmakiyama) 2021年7月26日
いい記事そう、また見返そう 📝
DroidKaigiのCfS1つ出したので寝れる…あした出せたらもうひとつ書いてみよ。意外とない気がする、Androidエンジニア1人での開発的なサムシンを…中身は未定…( ˘ω˘)スヤァ
— まきやま (@_rmakiyama) 2021年7月27日
まさか翌日に出したCfSが通るとはこのときの私は知らなかったのであった 👏🏻
小さい組織で自律的な振る舞いが求められる場合においても大事そうだし自然と鍛えられる気がしている。言語化されるとより納得感があって良い👏🏻
— まきやま (@_rmakiyama) 2021年7月28日
抽象的な期待を自分ですり合わせるスキル - Konifar's ZATSU https://t.co/95Hgeo9fjj
今でも様々なところで大事だなと感じるので良い話!
8月
脳内を言語化していきたいねということで妻氏とそんなラジオを始めました!🧠📻#Radiotalk #1LDKラジオ https://t.co/eVdArJwPFf
— まきやま (@_rmakiyama) 2021年8月16日
何回かとったけど更新が止まっちゃったけど楽しかったのでふとしたときにまた話すのも良さそうだな〜
#DroidKaigi 初採択、!🥳
— まきやま (@_rmakiyama) 2021年8月18日
やっていきます!!よろしくお願いします!!!意外とある、組織にAndroidエンジニアが1人という状況での学習方法、そして特有の不安とどう向き合うかについて話します!楽しくエンジニアリングしよう!🙌🏻 pic.twitter.com/7NRUb5pMux
初採択!泣いた(泣いてない) 👏🏻めちゃ嬉しかった!
部活はバスケットボールをやっててルーズボールは全力で取りに行けと教え込まれて育ったのでプロダクト開発も同じだな〜って思ってる。取ったらドリブルしたりパスしたりシュートしたりやり方はたくさんあるね。楽しいね。
— まきやま (@_rmakiyama) 2021年8月31日
わかる。(自分で書いているのでそれはそう)
9月
マネージャーではないけど、組織としての出力を最大化するために自分が今どう動くべきかは最近とても考えるが答えはない。問題解決の化身になりたい🤡
— まきやま (@_rmakiyama) 2021年9月7日
エンジニアリングマネージャーは「問題解決ブルドーザー」の夢を見るのか|Jumbo #note #私の仕事 https://t.co/NDXmeIU44n
永遠に考えているが難しいけど楽しい部分でもある。
進捗です🍺 pic.twitter.com/W6mSajDzmD
— まきやま (@_rmakiyama) 2021年9月21日
キャンプデビューした!!!!来年はたくさんいきたい!!!
10月
購入しました! 設計を知る、パターンを知る、導入する「iOSアプリ設計パターン入門」が一般販売開始! https://t.co/9w02Brdty2 #iOS_architecture
— まきやま (@_rmakiyama) 2021年10月12日
クライアント(iOS/Android)リードのポジションになったのでiOSをキャッチアップし始めたころ。この本とても良かった。
今日はグループ会社の総会でBEST Creator Awardを頂きました🙏🏻!フォロワーシップの高いチームだからこその賞だと思っております!これからもチームみんなでRadiotalkをどんどん前に進めていきます!!!🚀 pic.twitter.com/8PkSjTpMfk
— まきやま (@_rmakiyama) 2021年10月18日
グループ会社で表彰してもらった 🏆
セッション・オフィスアワーまでありがとうございました!!!自分にとっても非常に良い経験でした!!!少しでも不安と向き合うきっかけになったり楽しく働く手助けになれていれば幸いです!!! #DroidKaigihttps://t.co/oL2y15zWBb
— まきやま (@_rmakiyama) 2021年10月19日
最高の体験でした!DroidKaigiありがとう!!
11月
今日はiOSのテストを書く実績を解除したので褒めて下さい!えらい!すごい!!
— まきやま (@_rmakiyama) 2021年11月18日
えらい 👏🏻
高い山を作るためには裾野を広げるのも大事だよねって自分で言って自分でしっくりきてるので良い山脈を築いていきたい🏔🏔
— まきやま (@_rmakiyama) 2021年11月19日
12月
iOSのテストのためにMockoloを導入したので来世は宝くじが当たるぞ!
— まきやま (@_rmakiyama) 2021年12月21日
積極的に自分を褒め始めた 👏🏻
ライブラリ管理をVersion Catalogへの移行が完了したので優勝です!ありがとうございます!🏆
— まきやま (@_rmakiyama) 2021年12月22日
優勝しがち。
「Androidのテストをはじめよう🧪」と「iOSのテストをはじめよう🧪」の記事をKibelaに簡単にまとめたので一富士二鷹三茄子確定🗻🦅🍆
— まきやま (@_rmakiyama) 2021年12月28日
来年も安泰です!
まとめ
Twitter検索でfrom:_rmakiyama until:2021-4-1
みたいにしてザッと振り返ってみた。
良いなと思ったものは積極的にツイートしたりしているので、それを改めて思い出せたのも良かった 👍🏻
いろんな変化もありながら相変わらず楽しくやっていけていて、今年もハッピーでした!来年はもっと楽しくなるよねハム太郎!!!
MockKを使ってて便利だった関数たち
MockKにお世話になっていて、便利だった関数をいくつかご紹介します。
confirmVerified
verify
ですべての呼び出しが検証されたかをチェックすることができます。
たとえば「ボタンがクリックされたときにアナリティクスイベントを記録する」という挙動をテストしたいというケースで、このようにテストを書いたとします。(ViewModelでクリックイベントをハンドリングしたとする)
val analytics: AnalyticsManager = mockk(relaxed = true) // テスト対象を生成 val viewModel: HogeViewModel = createViewModel(analytics = analytics) viewModel.onClickButton() verify(exactly = 1) { analytics.logCustomEvent(Event.TapButton) } // analyticsの呼び出しすべてを検証したかをチェック confirmVerified(analytics)
このとき、HogeViewModel#onClickButton
を呼び出した際にanalytics
に対してverify
で検証したもの以外の呼び出しがあったときに、confirmVerified
は例外をスローしてくれます。
予期せぬ呼び出しがないかや、検証の漏れがないかという場合に便利です。
ofType
マッチャーのひとつで、値の型をチェックすることができます。
通常の検証ではeq(value)
が使われますが、ものによってはequalsの比較の検証が難しい場合もあります。
val analytics: AnalyticsManager = mockk(relaxed = true) // テスト対象を生成 val viewModel: HogeViewModel = createViewModel(analytics = analytics) viewModel.onClickSave() verify(exactly = 1) { // Event.Saveという型のイベントが記録されたことを検証 analytics.logCustomEvent(ofType(Event.Save::class)) }
このように書くと、AnalyticsManager#logCustomEvent
に渡したパラメータがEvent.Save
であることを検証できます。
withArg
こちらもマッチャーの一つで、検証するパラメータについてコードの実行が可能なため、ofType
より’柔軟に検証することができます。
こちらはMockKVerificationScope
内でのみ使うことができます。
val analytics: AnalyticsManager = mockk(relaxed = true) // テスト対象を生成 val viewModel: HogeViewModel = createViewModel(analytics = analytics) viewModel.onClickSave() verify(exactly = 1) { // 引数についてAssertで詳細に検証 analytics.logCustomEvent(withArg { event: Event -> Assert.assertEquals(1234, event.params["user_id"]) Assert.assertEquals("hoge", event.params["type"]) }) }
メソッド呼び出しの引数についてテストしたい場合に便利です。
アフターデジタル2を読み始めた
アフターデジタル2の1章を読んだ。
Kindleは便利で、気になったところにさっとハイライトとメモを残せる。
ザクッとメモを振り返りながら思ったことをザクッとブログに残そうと思う。
ハイライトとメモと振り返り
リアルとデジタルの接点の主従関係を逆転させて考える必要があるというのが、「アフターデジタル」という
ほんのタイトルにもある"アフターデジタル"という言葉の意味が面白かった。
書いてもある通り、どうやってリアルの中にデジタルを、言い換えれば、どうやって人の生活の中でサービスを使ってもらうか、という考えになりがちだなあと感じた。
言葉遊びにならないように気をつけなければいけないと思うものの、インターネットの普及によって色んなものが繋げられた今は、リアルとデジタルを分けて考える必要はなくなっている、といのは自分の体感としてもあるし、意識していきたい。
個別接点のデータがいくら集まっても大した意味はなく、データがシーケンス型に整理されていることが大事
プロダクトの成長や分析のためにも、データを取ることは必要不可欠になっているが、そのデータを線として捉えるのは意外とできていないし、難しい。でもただただ取りがち。
ユーザーの行動の整理ができていないのかもしれない。どう行動させたいか、という定義すら決まってないとシーケンス的に取ることはかなわない。
こういったとこからも、エクスペリエンスと行動データ、つまりUXとエンジニアリングはつながるのかもなと感じた。
どういう体験をさせたいか、それが実現できているかを、体験ベースのシーケンスになるように行動データを取るべきで、それができていれば、UXの良し悪しは数字によって測定可能になりそう。
デジタルによる利便性という意味では、中国は日本より進んでいます。「利便性というマスの余白」は既に取りつくされてしまっており、多くの日本人が求めるような「バズりやすいキャッチーな事例」が出てこなくなってしまった
「利便性というマスの余白」という言い回し良い。そしてこれの取り合いがまだまだ日本だと多い印象がある。これについてはもちろん、余白が残っているということかもしれない。
だが、この取り合いに終止してしまうと伸びしろは余白分しかないとも言えるかもしれない。人の生活は点でもマスでもパズルでもなくて、時間軸のある線なので、余白を埋めるだけではそこに入るのは難しいかも。
目標設定とかなんとかでよく「whatじゃなくてwhy」と言われているが、サービスにおいても自然と「何を使うか」ではなく「なぜ使うか」という視点で選ばれていく時代になりそうな気がする。本の言葉を使うと「新たな生活スタイルの提案」をしていくことが重要と言えるかもしれない。便利な○○を使う、のではなく、こういう自分でありたい、あるいはこういう生活をしたいから○○を使う、というフェーズになったときに戦えるようだと強そう。
雑記
自分はUXに興味があって、だけど(だけどってのもおかしいけど)軸としてはエンジニアなので、どう向き合うかという部分についてふわふわしてたけど、少しだけ、解像度が上がった気がする。
エンジニアとしても、点を線にすることが大事。データにも言えるしユーザーの分析にも言える。点を提供するのではなく、点は線にし、線と線のコネクタも作らなければならない。 どうアプローチするのかしたいのか、まだまだ具体化できない。抽象的である。
あしたには別のことを言っているかもしれない。
言語化すると自分との対話みたいで思考が整理されるのでよいです。
Navigation Architecture Componentを使ったログイン機能実装方法
素振りの一環でTwitterクライアントのサンプルを作っています。(WIP)
starをもらえると喜びます。
github.com
そんなときに@AndroidDevのツイートで、Navigation Architecture Component(以下Navigation)を使った際のログインのCase Studyが紹介されていたので、Twitterクライアントにも必要であろうと実装してみました。
🗺️ Sail through Jetpack Navigation
— Android Developers (@AndroidDev) 2020年7月23日
Join @ianhlake as he covers the Jetpack Navigation Architecture Component. In this video, he shares some newly added functionality and dives into a case study on Login. #11WeeksOfAndroid
😎 Find your way → https://t.co/8wL9o6GLWW pic.twitter.com/zHWO7Dl1pU
ログイフロー概説
Navigationを用いる場合、まずはナビゲーショングラフに開始のディスティネーションを設定する必要があります。
ログインを必須とするアプリの場合、開始のディスティネーションにログイン画面を設定したくなりますが、これはよくないとされています。
(記事末にこのときの弊害について記載しておきます。)
ナビゲーションの原則に従いながら、ログイン画面への遷移を実現するためには、各画面から必要なときのみログイン画面に遷移する方法を取るのが好ましいようです。
詳しくはAndroid DevelopersのYouTube動画を御覧ください。
実装
前提として私が試した環境はこちらです。
- Android Studio 4.1 Beta 5
- Navigation 2.3.0
サンプルアプリ概略
一般的なTwitterクライアントを題材にしています。
アプリはタイムラインを表示する画面(以下HomeFragment)があり、こちらはログインをしているユーザのみ見れる想定です。また、今回は開始ディスティネーションをHomeFragmentとしています。
未ログインのユーザにはログイン画面(以下LoginFragment)へ遷移させるようにします。
順を追って説明します。
LoginFragmentへの遷移
未ログインの状態を判定し、ログイン画面へ遷移をさせます。
class HomeFragment : Fragment(R.layout.fragment_home) { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... viewLifecycleOwner.lifecycleScope.launchWhenStarted { viewModel.authUser.collect { user -> if (user == null) navigateLogin() } } } ... }
今回は簡易的に、保存されたログインユーザがnullの場合に遷移する処理を実装しています。 ログインが必須の場合は、ディープリンク経由で遷移できる画面すべてに同様の処理を実装する必要がありそうです。
ログイン結果を遷移元(HomeFragment)に伝える
LoginFragmentは、必要なときに別の画面から呼び出されることを前提として作ります。
Navigation(ver2.3.0)ではpreviousBackStackEntry
を使い、遷移元のFragmentに値を伝えることができるので、これを活用します。
class LoginFragment : Fragment(R.layout.fragment_login) { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... val navController = findNavController() val savedStateHandle = requireNotNull(navController.previousBackStackEntry).savedStateHandle val binding = FragmentLoginBinding.bind(view) binding.loginButton.setOnClickListener { viewModel.saveAuthUser() } viewModel.succeeded.observe(viewLifecycleOwner) { // ログインの成功を前の画面に伝える savedStateHandle.set(KEY_LOGIN_SUCCESSFUL, true) navController.popBackStack() } } ... }
サンプルではログインボタンを押したら適当なAuthUserを保存するようにしていますが、実際には認証処理を行い、その結果の成否によって処理を分ける必要があるでしょう。
ログインの成否を受け取る
HomeFragmentではcurrentBackStackEntry
を使い、先程LoginFragmentがセットした成否の値をもとに処理を行います。
class HomeFragment : Fragment(R.layout.fragment_home) { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... val navController = findNavController() val savedStateHandle = requireNotNull(navController.currentBackStackEntry).savedStateHandle savedStateHandle.getLiveData<Boolean>(KEY_LOGIN_SUCCESSFUL) .observe(viewLifecycleOwner) { success -> // 成否の結果から処理を行う if (success) viewModel.getTweets() savedStateHandle.remove<Boolean>(KEY_LOGIN_SUCCESSFUL) } } ... }
アプリの性質によって成否の処理はうまく処理しましょう。
今回はログインが成功したときのみ前の画面に戻るように実装しているので、失敗したときの処理は実装していません。
開始ディスティネーションにログイン画面を設定したときの弊害
アプリの多くは、ディープリンクによってWebサイトやSNSアプリなどからアプリに遷移させることが多いかと思います。
Navigationでもディープリンクをハンドリングする機構が整っています。そして、Navigationではディープリンクの場合、手動ナビゲーションをシミュレーションするという性質があります。
つまり、リスト画面とリスト要素の詳細画面を持つアプリの場合、ディープリンク経由で詳細画面に遷移した場合も、バックスタックにはリスト画面も含まれているということになります。(詳しくは公式ドキュメントのナビゲーションの原則をご参照ください)
これにより、ログイン画面を開始ディスティネーションに設定した場合、ディープリンクでアプリ内のコンテンツにアクセスした際に、ログイン画面がバックスタックに積まれることになってしまいます。
もちろん、ログイン済みかどうかの判定をしてここの調整をするとは思いますが、少し煩雑になりますし、ナビゲーションの原則に沿っていません。
References
potatotips #68 参加していました!
参加した回はこちら。
ブログ枠での参加でしたが、大変遅れてしまって申し訳ないです、書いていきます!
potatotipsはAndroid/iOSの入り乱れた勉強会で、全部で10個以上のLTが!
1つは5分と短いですが、Tipsの所感を掴むのにもってこいです。
Android開発者としては、普段は聞かないiOSのつらみや解決策を聞けるのも良いです!
Androidの発表はこちら!
- 今日からはじめるGithub Actions
- Navigation Componentのデータ受け渡しのつまづき
- 複雑になった画面をリファクタした話
- ViewBindingで手軽にView操作
- Flutter (Dart) と Platform (Android/iOS)- 相互呼び出しのMethodChannelについて -
- ML Complete Features(Flutter)
- Badging for Tabs and Bottom Navigation
今日からはじめるGithub Actions
ワークフローを網羅的に説明していてもはやバイブル!
Github ActionsはGitHubのさまざまなイベントをフックにできるので触っていて楽しい!
実際にリリースノートを自動化していて素敵でした。
Navigation Componentのデータ受け渡しのつまづき
Nested Graphのときのデータ受け渡しのTipsでした!
Nested Graphを使う場合はactionタグにargumentタグを追加で解決とのこと。
これはハマりそう…知見…
複雑になった画面をリファクタした話
複雑になりがちなメッセージング画面をリファクタリングした話でした。
こういう実プロダクトでの課題解決は本当に聞いていて面白いですね。
1Activity&1Fragment
-> 1Activity&2Fragment
にして、責務によって階層を分けるという解決策でした。
メッセージング画面、すごい知見の宝庫だと思うので各社の実装方法でわいわい議論するの楽しそう。。
ViewBindingで手軽にView操作
ViewBindingはだいぶ浸透してきたという肌感。お手軽で便利なので個人でも使っていきたい!
DataBindingライブラリを使うまでもないけどfindViewById
もKotlin Android Extension
もなあ〜ってときはすぐ使える。
スライドにもあるように、メモリリークにも注意しましょう。
最近個人的には、極力onViewCreated
の中でbindingを使って完結させられるように意識してます。(なかなかそうはいかない)
Flutter (Dart) と Platform (Android/iOS)- 相互呼び出しのMethodChannelについて -
Flutterのお話。
ネイティブの機能を使うandよいライブラリがなければやはり自前実装になりますが、そのつなぎをどうやるかという発表。
Flutterは最近少し触っていますが、非常に開発者体験がよいです!
いざというときにネイティブの知識を持っているのは強みだな〜と感じてます。
ML Complete Features(Flutter)
続きましてもFlutterの話、ですが、ML Completeというコード補完のお話。
実験的機能ですが、変数が補完されるのかなり嬉しいかも…変数めちゃめちゃ悩みますよね…
未来は簡単な変数名ならエディタが考えてくれる時代を感じました。
Badging for Tabs and Bottom Navigation
Material Components 1.1.0でのBottomNavigationViewでバッヂがつけれるように!
ドットにしたりマックス値以上は+
で表現したり、基本的なユースケースは満たしてくれそうで素敵。