【個人開発】FlutterでQiitaクライアントアプリを公開したので、技術選定や振り返り

## リリースしたアプリ

どこでもQiita（現在はAndroidのみ公開中。）

https://play.google.com/store/apps/details?id=com.wumpuss.anywhere_qiita


## 今回やりたかったこと
Flutterは業務で経験して約10ヶ月くらいになるのですが、知識の整理もかねて、業務以外で自分でもFlutterアプリをリリースするという目標を掲げました。
業務中の開発だけだと、どうしても自分が担当するタスクに集中しがちだったり、他の方と相談して大きな方針を決定することが多いです。
なので今回は自分一人で全体を1から考え抜くことをやりたかったです。

## アプリの設計など
今回、リリースしたアプリの主な設計としては、Provider + StateNotifierを基本設計として、その他のライブラリではfreezed、retrofit、moorなどを使用しました。
基本的に使用するライブラリは、なるべく公式のライブラリなどに限定したいです。Flutterはバージョンアップが早いため、そのライブラリがどこまでメンテナンスされるか不安なためです。

個人的にはChangeNotifierで書くのがあまり得意ではないので(notifyListenerを忘れたりする)、StateNotifierを使うことはすぐに確定しました。Providerにするか、Riverpodを使うかに関しては迷いました。（実際には、途中までRiverpodを使ってアプリの全体の6割くらいを作り終えた後、Providerで作り直しました。）

しかし私の場合はRiverpodだとどういう風に書くのが正解なのか、よく分からなくなることが多いです。この辺は自分自身のRiverpodに対する理解の浅さや、経験的にProviderを多く使用してきたので慣れてしまっているのかもしれません。あとはRiverpodは破壊的変更が入る時もあるらしく、個人開発にかけられる時間を考えると躊躇したり、まだ世の中にRiverpodのコード例が少なく感じています。

### Null Safety未対応

まだNull Safetyには対応出来ていません。作成時に全てのライブラリが安定版でNull Safety対応していなかったことが大きな理由です。

## 画面一覧と主な機能&参考にした記事
今回のアプリを作成するにあたって、なるべく今まで自分が記事を書いたりしたことをベースに、リリースまで、あまり時間をかけずに作り切ることを優先しました。そのため自分のスキル外のことには一旦、手を出さないように開発を進めました。

ほとんどは自分の過去の記事ですが、実装時に参考にした記事などが明確になっているものに関しては、リンクにしておきます。出来れば、全ての機能の実装例の記事を書きたいです。

[Qiita APIドキュメント](https://qiita.com/api/v2/docs#part-ed57fb9a23559eaf)

| 画面名 | 機能名 | スクリーンショット |
|:-----------|:------------|:----------:|
| ログイン画面       | ・[アニメーション](https://qiita.com/toda-axiaworks/items/f1f7acf9a636f52c67b3)<br>・[ログイン認証](https://www.flutter-study.dev/create-app/qiita-app/)       | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/86855301-1849-c875-3f70-943b3e774d47.png" width=50%> |
|ホーム画面|・最新記事表示<br>・[無限スクロール(リストの一番下にスクロールすると、記事一覧の続きをロード)](https://www.flutter-study.dev/create-app/qiita-app/)|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/9fbd40b8-b43d-742e-69fd-bac15cd14d6c.png" width=50%>|
|タグ一覧画面|・タグ一覧表示|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/2f4f390d-2688-96a0-4c6d-b00decb6c8b7.png" width=50%>|
|タグ記事一覧画面|・選択したタグの記事一覧表示|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/2235408c-485b-0d22-33d1-db3a355f8261.png" width=50%>|
|記事の検索画面|・記事の検索結果一覧表示<br>・[検索ワード履歴表示](https://qiita.com/Ryota-Nakamura-317/items/b847fba91ca530d3d78c)|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/f48a52ea-7a56-3d98-34d8-2075167fbacc.png" width=50%>|
|ストック記事一覧画面|・ストック記事一覧表示|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/e1dee725-9d07-68f4-23d9-157d8bcded02.png" width=50%>|
|記事詳細画面|・[WebViewで記事詳細表示](https://qiita.com/toda-axiaworks/items/9d5f9d5eb5a13e972e15)|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/2c00ffd2-6444-e327-836a-5e40d0dec6c8.png" width=50%>|
|アカウント画面|・アカウント情報取得<br>・自分が投稿した記事一覧表示|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/6752c5f4-7f35-5c53-aa61-a61ae6e57949.png" width=50%>|
|設定画面|・ダークモードOn/Off|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/374b8516-93bf-a47d-b966-cf8ec65c8dc2.png" width=50%>|


## 主に妥協したこと
個人でアプリ公開を目標にしている場合、途中でモチベーションがなくなる前にリリース目指すべきだと考えています。そのためには、機能的にデザイン的にも妥協も必要だと思っています。
その代わりリリース後に、継続してアップデートをするのが大事だと思います。

- 記事詳細画面はWebViewにしたこと
今回記事詳細画面はWebViewで表示するようにしています。flutter_htmlなどを利用して、取得した記事を変換して画面表示したいです。（軽く試したのですが、tableタグの部分などが一部崩れたので、ひとまずWebView表示に変更しました。）

- Contributions数の確認機能
やりたいこと自体は過去に記事を書きました。

[FlutterでWebスクレイピング(QiitaのマイページからLGTMの数を取得)](https://qiita.com/toda-axiaworks/items/dd05264d5a7953316494)

ContributionsはQiita APIからは取得出来ないです。Webスクレイピングして取得しているだけなので、Qiitaのページに修正が入ると動作しなくなる問題があります。


## まとめ
今回、これまでに書いてきた記事などをベースにアプリを作成し、あまり多くの時間を使わずにアプリをリリースすることが出来ました。完全に１からやろうとすると時間がかかってしまうと思います。

やはり常に自分のアウトプットを記事にしたり、あるいは記事にしなくても「Githubのリポジトリなどに自己学習の成果物をためておく」という作業を積み重ねることは、自分を助けてくれると実感しました。

またFlutterでのリリース作業をしたのは始めてのことでした。過去にAndroidアプリのリリースを経験していましたが、Flutterでアプリをリリースするのは、Androidで公開した時とは手順が少し違っていました。

クオリティを上げつつ、少し余裕ができたら、iOSでのリリースもしたいと思います。