Slide 1

Slide 1 text

ViewModel使ってますか? 2018/4/20 Osaka Mix Leap Study #11 - スマホアプリ勉強会

Slide 2

Slide 2 text

Speaker 中谷 克紀 仕事  Enterprise Server Engineer GDG 神戸スタッフ Twitter  @KatsukiNakatani

Slide 3

Slide 3 text

What's ViewModel? MVVMとか設計の話ではないです

Slide 4

Slide 4 text

これの話

Slide 5

Slide 5 text

ViewPagerでこんなデータを表示したい 仮想通貨のデータ 最近、仮想通貨流行ってますよね?

Slide 6

Slide 6 text

データの持ち方 data class CurrencyOrder( var exchanger: String? = null, //購入Exchanger var folio_group:Long = FolioGroup.DEFAULT_ID, //この通貨のグループ var currency_pair: String? = null, //通貨ペア var proc_date: String = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")), //処理日付 var amount: Double = 0.toDouble(), //処理数量 var price: Double = 0.toDouble() //ベースとなる通貨の価格 exchanger folio_group currency_pair proc_date amount price zaif 1 jpy_btc 2018/1/1 1 850000 zaif 2 jpy_xem 2018/2/2 1 35

Slide 7

Slide 7 text

データの概要 folio_groupがここ

Slide 8

Slide 8 text

安易に考える Activity ViewPager Pager1 Fragment Pager2 Fragment ActivityViewModel FragmentViewModel FragmentViewModel

Slide 9

Slide 9 text

安易に考える Activity ViewPager Pager1 Fragment Pager2 Fragment ActivityViewModel 1.ActivityViewModelがデータを全件取得 2.ActivityがそのデータをDataCallbackInterfaceを 実装しているであろう Fragmentに送る 3.FragmentがCallbackを受け取り、データを表示 FragmentViewModel FragmentViewModel DataCallback DataCallback

Slide 10

Slide 10 text

めんどくさい Activity ViewPager Pager1 Fragment Pager2 Fragment ActivityViewModel ・ActivityがDataCallbackInterfaceを実装していることを知る必要あり ・ActivityはただViewPagerだけ管理していたい FragmentViewModel FragmentViewModel DataCallback DataCallback

Slide 11

Slide 11 text

ViewModelの登場 ViewModelのインスタンス生成時に渡すparameterに 紐付いて生存期間のスコープが作成されます ViewModelProviders.of(parameter).get(MyViewModel.class); 画面回転時にデータ保存を意識しなくても良い!! ※ただし低メモリ時に破棄されると困るデータはきちんと  SaveInstanceStateで保存しましょう

Slide 12

Slide 12 text

ViewModelの共有 ViewModelのインスタンス生成時に渡すparameterが同じものは別インスタンスじゃなくて 同じインスタンスにアクセスできる ViewPager Fragment Code viewModel = ViewModelProviders.of(activity).get(AssetsViewModel::class.java) Activity ViewPager Pager1 Fragment Pager2 Fragment getActivity()した結果は同じActivity

Slide 13

Slide 13 text

諸問題が解決 Activity ViewPager Pager1 Fragment Pager2 Fragment ActivityViewModel AssetViewModel DataCallback DataCallback ・DataCallbackを用意しなくても良くなり、 ActivityがFragmentの実装を意識しなくて良くなった ・Activityの回転時に再度データを検索、表示するような実装を意識しなくても良くなった

Slide 14

Slide 14 text

ViewModelの作り方 class AssetsViewModel @Inject constructor(private val database: AppDatabase, private val messageRepository: MessageRepository, private val assetRepository: AssetsRepository, private val preferenceRepository: PreferenceRepository) : ViewModel() Architecture ComponentのViewModelを継承する

Slide 15

Slide 15 text

注意すること 生存期間が渡したパラメータのライフサイクルより長い = ViewModel側でViewにアクセスする、またはライフサイクル内の コンテキストを使用するような実装は避けましょう contextがほしいViewModelの場合はAndroidViewModelを 継承してください

Slide 16

Slide 16 text

ViewModelはLiveDataと組み合わせると便利 LiveDataの特徴 SubscribeするとActivityやFragmentのライフサイクル状態を 見てコールバックを呼び出してくれる LiveDataの定義 var assetsList: MutableLiveData = MutableLiveData() LiveDataへデータのプッシュ assetsList.postValue(response) viewModel.assetsList.observe(this,Observer { it -> //表示処理}) LiveDataのオブザーブ ViewModel Fragment

Slide 17

Slide 17 text

よくある通信例 1.画面を開くと外部通信を行う 2.外部通信を行っている場合はProgressが表示される 3.通信を行っている間に画面が回転する可能性もある 4.通信結果を画面に表示する、ただし画面を落としている可能性もあるよね   落としている時はデータ表示処理してほしくないし復帰したら処理してほしい

Slide 18

Slide 18 text

よくある通信例 1.画面を開くと外部通信を行う 2.外部通信を行っている場合はProgressが表示される 3.通信を行っている間に画面が回転する可能性もある 4.通信結果を画面に表示する、ただし画面を落としている可能性もある   落としている時はデータ表示処理してほしくないし復帰したら処理してほしい   ー>ViewModelにbooleanを持ってDatabindingで表示・非表示を切り替え   ー>ViewModelを使えば渡すContextより長いスコープで     生存してくれるので気にしなくて良い   ー>LiveDataをViewModel内に持たせておけば、回転してもデータを維持しUI復帰時に     データをPostしてコールバックしてくれる

Slide 19

Slide 19 text

使ってみた https://goo.gl/NB9R7y 結果・Room+ViewModel+LiveDataを使って実装してみたのでよければ使ってください。 Architecture Componentのモジュールを使うと 今まで苦労していたAndroidのライフサイクル関係は 大分楽に実装できます

Slide 20

Slide 20 text

おしまい 御清聴ありがとうございました