Slide 1

Slide 1 text

個人開発始めてみた Android LT会 2022/04/12 Yuta Asada(bull)

Slide 2

Slide 2 text

ぶる(浅田悠太) 株式会社アトラエ 23卒予定 Yenta事業部 Androidエンジニア JetpackComposeへの移行 47都道府県制覇 世界一周、貧困支援の経験あり

Slide 3

Slide 3 text

ぶる(浅田悠太) Twitter: @assa_012 github :@asa-012

Slide 4

Slide 4 text

前置き 実はAndroidの個人開発を1年前にやっていた だが完成には至っていない&Javaで書かれているため 完全放置。。。。。。。。。 このままじゃだめだ。。。。。いつかリファクタリングしないと。。。 そしていつの間にか1年が経った。。

Slide 5

Slide 5 text

今回のLT会での決意表明 Javaをkotlinに移行して個人開発アプリを完成させます

Slide 6

Slide 6 text

Javaで作った時のアプリについて ● MVCアーキテクチャの崩壊版 ● LocalDateTime使わずCalendar型とDate型 ● ActivityResultConstantではなくonActivityResult使っている ● Dateの保存はLong型ではなく、String型である ● pngが使われている 今の時代はwebpかsvg ● ConstraintLayout使っていない ● findViewById ● 自作のデータクラス ● データベースは使わずGsonでJson化して保存

Slide 7

Slide 7 text

作っているアプリの概要 ● 料理を記録する ● Google Calendarを想像して貰えば良い(メインタブ) ○ 週間カレンダー、月間カレンダーを表示 ○ 日程部分に料理登録、表示が可能 ● 料理登録用タブ ● 設定画面タブ

Slide 8

Slide 8 text

kotlin移行するにあたって考えたこと ● ios版も出したいと思っていたからKMMの導入あり ● KMM使うならLiveDataよりStateFlow使うべきか ● Javaを封じ込めたいのでマルチモジュール化してlegacyモジュールに格納すべきか ● JetpackComposeの導入するかどうか 使うならsingle Activityにするかどうか ● 画面遷移はnav graph使うかどうか ● Gson保存をデータベース保存(Room)に書き換えるかどうか ● アーキテクチャはMVVM+Repository+UseCaseかMVVM+Repoか ● pngはwebpに書き換える ● build.gradleはktxに変更 ● DIはKoinではなくHiltでいいよな...? ● Firebase RealtimeDatabaseからFireStoreに入れ替えた方がいい? ● github actions使おうか ● ktlint入れようか ● ListViewをRecyclerViewに変えたい ● テストいるか...? ● ログいるか..? ● バックアップどうしよう

Slide 9

Slide 9 text

過去の自分のコード 理解できない

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

1つ1つのセルのadapter

Slide 12

Slide 12 text

//1つのセルの中身を決める @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); //TODO View view = inflater.inflate(R.layout.grid_item_calendar, parent, false); view.setLayoutParams(new AbsListView.LayoutParams(itemWidth, itemHeight)); holder.baseArea = view; holder.tapArea = view.findViewById(R.id.tap_area); holder.text = (TextView) view.findViewById(R.id.text); holder.backgroundToday = (ImageView) view.findViewById(R.id.calendar_background _today); holder.selectedDay = (ImageView) view.findViewById(R.id.selected_day); holder.imageTime = (ImageView) view.findViewById(R.id.image_time); view.setTag(holder); convertView = view; } } else { holder = (ViewHolder) convertView.getTag(); } // 初期化 holder.imageTime.setVisibility(View.INVISIBL E); holder.selectedDay.setVisibility(View.INVISIB LE); holder.tapArea.setOnClickListener(null); holder.tapArea.setClickable(false); holder.text.setBackgroundDrawable(null); //position:日が0,土が6 updateTextColor(position, holder.text); //HACK:最初の7つだけはどのpageでも日~ 月を表示 if (position < COLUMN_COUNT) { String weeks[] = {"日", "月", "火", "水", "木", "金", "土"}; holder.text.setText(weeks[position]); holder.text.setTypeface(Typeface.DEFAULT); return convertView; } //このconversionViewInfoのindex番号=セ ルの日付 CalendarGridItemEntity entity = calendarManager.conversionViewInfo(positio n - COLUMN_COUNT); List medicines = MedicineTabManager.getInstance(context).fi ndRecordEntitiesByDate(entity.date); holder.baseArea.setVisibility(View.VISIBLE); if (entity.isToday) { holder.backgroundToday.setVisibility(View.VI SIBLE); holder.backgroundToday.setBackgroundRes ource(R.drawable.shape_bg_calendar_today ); }else{ holder.backgroundToday.setVisibility(View.IN VISIBLE); } ClickInfo info = new ClickInfo(); info.date = entity.date; holder.tapArea.setClickable(true); holder.tapArea.setTag(info); holder.tapArea.setOnClickListener(innerClick Listener); holder.text.setText(entity.dateStr); Date today = new Date(); if (medicines.size() > 0 &&

Slide 13

Slide 13 text

カレンダー操作のControllerクラス

Slide 14

Slide 14 text

@Override public void onPageSelected (int position) { //枚数が変更になったら情報更新 selectedIndex = position; if (calendarListener != null) { calendarListener .onPageSelected(positi on); } adapter.clearSelectIfSet() ; setSelectDateForGridView() ; //今のindex番号を取得 int i = adapter.getDiffMonth(position) ; //HACK:カレンダーボタンを押したとき用の 処理 今日の日付を表示する  indexが隣ではな いから(indexが8→0もあり得るから押すと初期化 する) if(i == 0 && isCalendarMenu ){ Calendar calendar1 = Calendar.getInstance(); calendar1.setTime( new Date()); selectedDate = calendar1.getTime() ; beforeIndex = 0; //HACK:isCalendarMenu はカレンダーボタ ンを押されたらtrue,遷移したらfalseに戻すこ とでカレンダーボタン用処理を実現 isCalendarMenu = false; } //右に1スクロール カレンダー +7日 if(i == beforeIndex + 1){ Calendar calendar1 = Calendar.getInstance(); calendar1.setTime( selectedDate); calendar1.add(Calendar. DAY_OF_MONTH,7 ); selectedDate = calendar1.getTime() ; beforeIndex++; } //左に1スクロール カレンダー -7日 if(i == beforeIndex - 1){ Calendar calendar2 = Calendar.getInstance(); calendar2.setTime( selectedDate); calendar2.add(Calendar. DAY_OF_MONTH,- 7); selectedDate = calendar2.getTime() ; beforeIndex--; } CalenderGridAdapter listAdapter = adapter.getCurrentGridAdapter( viewPage r); //現在位置を表示 if(listAdapter != null){ //selectedDate は選択している日付 listAdapter.setSelectDate( selectedDate ); listAdapter.notifyDataSetChanged() ; } //データをつなげる部分 if (calendarListener != null) { calendarListener .onCalendarItemClick( s electedDate); } }

Slide 15

Slide 15 text

実際にやってみて感動したこと ● Javaで長々と書いている部分をkotlinは省略してくれている ○ 理解度上げるためには Javaの方が良いかも

Slide 16

Slide 16 text

Java public class ToDo { private final Strnig _mTitle; private final String _mText; public ToDo(@NonNull final String aTitle, @Nullable final String aText) { _mTitle = aTitle; _mText = aText; } public String getTitle() { return _mTitle; } public String getText() { return _mText; } }

Slide 17

Slide 17 text

Kotlin data class ToDo( val title: String, val text: String?)

Slide 18

Slide 18 text

改めてktxすごい ● view.isVisible = hoge > 0 ● val bundle = bundleOf( "hoge" to "fuga", "isHoge" to true)

Slide 19

Slide 19 text

Webpやっぱりすごい 1. 変更したいpngを右クリックする 2. convert png to webpをクリック 3. 75%圧縮でOKなのでconvert 場合によっては容量が半分以下になる しかもほぼ画質変わらない デメリットないかと

Slide 20

Slide 20 text

build-gradleでIDEが認識してくれるのとても助かる ● このextどこで定義されているんだ?ってなった時にIDEが認識してくれていれば Command+クリックで探せる

Slide 21

Slide 21 text

findViewByIdがない便利さ Button btn = (Button) this.findViewById(R.id.button_new); btnNew.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { //TODO } });

Slide 22

Slide 22 text

findViewByIdがない便利さ binding.btn.setOnClickListener { //TODO }

Slide 23

Slide 23 text

ConstraintLayout便利だ 慣れたら圧倒的に使いやすい。 直感的に書くことができる。 ※ただConstraintLayoutは他レイアウトと比べ 重いのでできるだけネストしないように心がけ る必要あり LinearLayoutが使える箇所は使ったり、 CardViewなどのViewで済むならそちらを使っ た方が良いかもしれない

Slide 24

Slide 24 text

ご静聴ありがとうございました!