イカなる時も

なんか色々垂れ流してます

2023/12/12

Android JetpackのProto DataStoreを触ってみた。protobufのプラグインとprotobufコンパイラのバージョンが少し古くHiltでDIできない(自動生成されるHogePreferencesの型がコンパイラが理解できずエラーになる)問題に遭遇した。

github.com

コメントにある通り、バージョンを上げたらビルドできた。めでたしめでたし。

Just thought I'd add that bumping to 3.24.1 & 0.9.4 worked for me as well when I ran into this, I think this can be closed.

2023/08/03

いつの間にか8月になっていた。

最近はSQLGoogleのレシート(Androidアプリで課金を実装するために必要なやつ)と戯れている。

サブスクをアプリで扱おうと思うと結構大変で、契約の状態をちゃんと一貫性というか正しい状態にするのが割と複雑になる。あとレシートの通知タイプとか状態遷移とか、考えることがそこそこある。 でもAndroidというかGoogleは偉大で、神みたいな図を用意してくれている。下のリンクはAndroidアプリ側の課金ライブラリについてだが、レシートの話と読み替えて良いはず多分。図中のSUBSCRIPTION_RENEWとかはレシートのrenewedと一緒のはず。

developer.android.com

Appleは...どうなんだろう。

developer.apple.com

developer.apple.com

Androidみたいに良い感じの図はなさそうかな。

2023/07/30

ちょこちょこ時間を見つけて自作エミュレータで学ぶx86アーキテクチャという本を読んだ。可愛い女の子の絵が表紙に書いているやつ。 最初は本を読みつつコードをRustで実装していた。が、一旦知識を頭に入れたい欲求が湧き、一通り読んだ。インタプリタ的に頭から一行ずつ読んだわけではなくて、わからないところは適宜ググったり、頭の中で整理しづらいところは何回か読み直した。文章が読みづらいとかそういう話ではなく、単に自分のCS知識不足。解説は非常に丁寧で、プログラムが動くまでなんとなく知りたいけど何から手をつけて良いかわからない人にはおすすめしたい本だと思った。ただ、全くプログラミング初心者の人はちょっとハードル高いかもしれない。C言語で簡単なプログラムを書いてコンパイル、実行できる人じゃないと難しいかもしれない。

あと、自分がこの本を読んで完全に理解したかと言うとそうではないので以下の感想は全然間違っている気がする。後半の部分は、リアルモードで動作するx64命令セットの仕様の話が結構出てきて適当に読み飛ばした。 この本がカバーしているところは、実行ファイルを読み込みCPUの動作を仮想的に模倣してプログラムを実行するところまで。仮想的に模倣っていうところがわかりにくいが、要はCPUの基本動作?である機械語のフェッチ、デコード、エグゼクをC言語で実装するということ。なんかぱっと見難しそうに感じるが、難しいところは良い感じに省いてくれているので知識がなくても理解できると思う。例えば命令のパイプライン化とかCPUの高速化技術とかはこの本には出てこない。あと、数値の加算などはC言語の+をそのまま使う、つまり自分でその部分を実装しない。この本には出てこない部分は適宜文献や本を示してくれているので興味がある人はそれを見れば良いと思う。特にCPUがどうやって動いているかみたいな部分は、CPUの創り方というこれまた美少女が表紙の本が載せられている。ちなみに自分はこの本を読む前にCPUの創り方は読んでいた。CPU以外にも電子工作、電気回路についてかなりページを割いていてそこにも興味がある人はすごく良いんじゃないかと思う。

あとは、自分はI/O処理についてエミュレータでどうするのか非常に興味があったのだが、そこもちゃんと説明されていてよかった。実装自体は標準出力に文字列を出力する程度だが、他に色々自分でやりたかったら自力で調べられる程度の知識を得られた。ここら辺はあまり理解していないが、どうやらレガシーっぽいのだがまあ面白いのでヨシ! あと、ブートローダもわかりやすく解説されていて非常に良かった。エミュレータの実装としてはそこまで本筋の話ではないのかなと感じたが、普通に面白かった。MBRとか知っていたけど動作イメージが全くわからなかったが、読んである程度理解できた気がする。

前の記事から1週間も空いていてびっくりした。

2023/07/23

アスペルガー症候群と診断された人のyoutube動画を見た。 動画の中でこういう傾向がある人はアスペですよみたいなのが一部説明されていたが、自分は当てはまらなさそうだなとは思った。 が、気になってググると集団で行動するのが苦手な人もアスペ傾向があることを知った。 自分はまさにそんな人で、社交性が求められる場面とか自分がそこにいることを想像するだけでも緊張するタイプ。 診断テストもどの程度信用できるかはわからないが受けてみた。

www.ginza-pm.com

22点以上だとアスペの可能性があるみたいだが24点も獲得してしまった。 まあ自分のそういうところはかなり劣等感を感じていて、ちゃんと病気ですよって診断された方が気持ちも楽になる気がする。。。

2023/07/21

先週末から大風邪をひいていた。体温計の電池は切れていたので熱は測っていないが39度近く出ていた気がする。たぶん。 頭痛も酷くて、何をする気力も湧かずひたすらyoutubeのショート動画を眺めていた。 その中でかなり衝撃的な動画を投稿していた人がいた。(非常に)野生的youtuberなので、生物が苦手な人は本当に見ない方が良いと思う。

www.youtube.com

ショートを見た方が早いので説明は省く。

体調悪い時って本当に何もすることがないというか何もできないが正しいのだけど、みんなどうしているんだろう。 あと、文章も書かなかったしずっとぼーっとしてたせいか、今週はずっと頭にモヤっと霧がかかった感じがしている。たぶん。

2023/07/01

composeのサンプルコードを触って、ナビゲーションボトムバーをどう実装するかみた。

@Composable
fun PlayGroundScreen() {
    val navController = rememberNavController()

    Scaffold(
        bottomBar = {
            BottomNavigation(
                backgroundColor = Color.LightGray,
            ) {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentDestination = navBackStackEntry?.destination
                items.forEach { screen ->
                    BottomNavigationItem(
                        icon = { Icon(screen.iconImage, contentDescription = null) },
                        label = { Text(screen.route) },
                        selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
                        onClick = {
                            navController.navigate(screen.route) {
                                // navigateを実行するとバックスタックにdestinationの情報がどんどん積まれのを避けるためpopup
                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                // 同じdestinationが再度選択されたとき、インスタンスを再利用する。
                                launchSingleTop = true
                                // 同じdestinationが再度選択されたとき、状態をレストアする。
                                restoreState = true
                            }
                        }
                    )
                }
            }
        },
        content = { innerPadding ->
            NavHost(
                navController = navController,
                startDestination = Screen.Profile.route,
                modifier =  Modifier.padding(innerPadding),
            ) {
                composable(Screen.Profile.route) { Profile(navController) }
                composable(Screen.FriendsList.route) { Favotite(navController) }
            }
        }
    )
}

rememberNavController()でNavControllerを取得する。NavControllerは各destinationのbackstackやnavigation graphを持っているので、それをcompositionを超えて保存しておきたいからrememberしてる感じ。 画面が破棄されたときはどうするんだろうと思ったけど、中でrememberSaveableを使っているので大丈夫そう。

@Composable
public fun rememberNavController(
    vararg navigators: Navigator<out NavDestination>
): NavHostController {
    val context = LocalContext.current
    return rememberSaveable(inputs = navigators, saver = NavControllerSaver(context)) {
        createNavController(context)
    }.apply {
        for (navigator in navigators) {
            navigatorProvider.addNavigator(navigator)
        }
    }
}

popupしているところは少し複雑かも。

navigateが実行されるたびにバックスタックにdestinationが積まれてしまう。そうすると、例えば戻るボタンをタップしても(backstackに積まれた分だけ)同じ画面が表示され続ける(多分)。UXとしては最悪そうなのでちゃんとpopupしておく。

popUpTo(navController.graph.findStartDestination().id) {
    saveState = true
}

すでにbackstackのtopに積まれているdestinationと同じところへnavigateするとき、新たにbackstackに積むのは無駄なのでインスタンスを再利用する。つまり何もしないことっぽい(多分)。

launchSingleTop = true

これも同じところにnavigateするとき、stateが変わっちゃう(UIがリセットされる?)のを防ぐために設定するっぽい(多分)。

restoreState = true

あとはScaffoldのcontentにある通り、遷移先で画面に描画したいComposable関数を呼んであげる。

NavHost(
navController = navController,
startDestination = Screen.Profile.route,
modifier =  Modifier.padding(innerPadding),
) {
    composable(Screen.Profile.route) { Profile(navController) }
    composable(Screen.FriendsList.route) { Favotite(navController) }
}

SwiftUIの方がシンプルにかける感じはした。