Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
GDG Tokyo Android Architecture Components - Liv...
Search
Takashi EGAWA
January 24, 2018
Programming
2.6k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GDG Tokyo Android Architecture Components - LiveData
GDG Tokyo Techtalk Android Architecture Components - LiveData on Jan 24, 2018.
Takashi EGAWA
January 24, 2018
More Decks by Takashi EGAWA
See All by Takashi EGAWA
Fuchsia Shibuya.apk #28 2018.9.28
t_egg
1
330
Android TV - Japan Android Group 2016 Aug.
t_egg
0
620
DroidKaigi 2016 パフォーマンスを追求したAndroidアプリを作るには
t_egg
8
9.1k
Other Decks in Programming
See All in Programming
Simple Storage Service(S3) is not simple
iwatsukayura
0
290
golang-bob.pdf
iwatsukayura
0
130
AWS CDKのカスタムリソースでContinuum(旧Security Agent)を実装した話 | Implementing Continuum (formerly Security Agent) via AWS CDK Custom Resource
akihisaikeda
2
150
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
220
パスワード再設定メールのURLについて知っておこう
uyuki234
0
160
Next.js: The final boss of Web Performance
guaca
0
260
カツオ、ご期待ください
suneo3476
0
190
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
420
Event is what happens
moro
2
790
残高管理から台帳サービスへの進化
artoy
1
200
phperだってパンチカードでコーディングしたい
o0h
PRO
0
340
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
190
Featured
See All Featured
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
500
Embracing the Ebb and Flow
colly
88
5.2k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
2
950
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
270
Intergalactic Javascript Robots from Outer Space
tanoku
273
28k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.2k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
500
Are puppies a ranking factor?
jonoalderson
2
4.1k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
870
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
370
Transcript
Architecture Components ษڧձ ͕͑Θ Θ͞ͼʔ; ͋Β͖ ͋Μ͍͟Ώ͖ ୈ2ճ LiveData
Architecture Componentsษڧձ ͱ • Architecture Componentsͷجૅࣝʹֶ͍ͭͯͿษڧձ • ओ࠵ɿGDG Tokyo ϋογϡλά:
#gdgtokyo • ߨࢣɺνϡʔλʔɿGoogleࣾһͱGoogle Developer Expert ʢ͋Μ͍͟Ώ͖ɺ ͕͑ΘɺΘ͞ͼʔ;ɺ͋Β͖ʣ
Architecture Componentsษڧձ ͱ • ܭ4ճͷ༧ఆ • ୈ1ճ:Handling Lifecycles • ୈ2ճ:LiveData
• ୈ3ճ:ViewModel • ୈ4ճ:Room λΠϜςʔϒϧ 19:30ʙ19:35 ѫࡰˍઆ໌ 19:35ʙ20:15 LiveData ͷઆ໌ 20:15ʙ20:25 ٳܜ 20:25ʙ22:00 ՝औΓΈ
Download Android Studio 3.1 Canary 8 https://developer.android.com/studio/preview/index.html?hl=ja
Architecture Components ͱ • ෳͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •
ViewModel • Room • Paging
Architecture Components ͱ • ෳͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •
ViewModel • Room • Paging ݸผར༻OK
Architecture Components ͱ • ෳͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •
ViewModel • Room • Paging ݸผར༻OK Έ߹Θͤར༻OK
Architecture Components ͱ • ෳͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •
ViewModel • Room • Paging ࠓͷςʔϚ͜Ε લճ ࣍ճ
LiveData
LiveData • observe (ࢹ) Մೳͳσʔλ • Activity/Fragment/Service ͳͲͷϥΠϑαΠΫϧΛҙࣝ (LifecyclesͷΈΛར༻ʣ •
Ұൠతʹ ViewModel ͱ࿈ܞͯ͠ར༻͢Δ (ViewModelͱViewͷؒͷކͷΑ͏ͳΛՌͨ͢ʣ
Lifecycles ͓͞Β͍
Lifecycles • Lifecycles = Lifecycle-aware Components • ϥΠϑαΠΫϧΛݕ͢Δίϯϙʔωϯτ • Activity
Fragment ͷϥΠϑαΠΫϧঢ়ଶ͕มΘͬͨͱ͖ʹԿ͔ ΞΫγϣϯΛى͜͢ɺͱ͍͏͜ͱ͕Ͱ͖ΔΑ͏ʹͳΔ
Lifecycle.State • ݱࡏͷϥΠϑαΠΫϧঢ়ଶΛද͢ enum • INITIALIZED • DESTROYED • CREATED
• STARTED • RESUMED https://developer.android.com/topic/libraries/architecture/lifecycle.html
Lifecycle.Event • ϥΠϑαΠΫϧঢ়ଶ͕มΘͬͨ࣌ͷΠϕϯτΛද͢ enum https://developer.android.com/topic/libraries/architecture/lifecycle.html • ON_CREATE • ON_START •
ON_RESUME • ON_PAUSE • ON_STOP • ON_DESTROY • ON_ANY
FragmentActivity ͔Β Lifecycle Λऔಘ͢Δ public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Lifecycle lifecycle = getLifecycle(); }
ݱࡏͷϥΠϑαΠΫϧΛऔಘ͢Δ final Lifecycle.State state = lifecycle.getCurrentState();
ϥΠϑαΠΫϧΛࢹ͢Δ lifecycle.addObserver(observer);
LiveData
ओͳLiveData • LiveData (android.arch.lifecycle) ௨ৗͷ LiveData • MutableLiveData (android.arch.lifecycle) ֎෦͔ΒมߋՄೳͳ
LiveData • MediatorLiveData (android.arch.lifecycle) ෳͷ LiveData ΛଋͶͯཧ͢Δ LiveData * Java8 Language Support * RxJava * ReactiveStreams ʹ͍ͭͯࠓճऔΓ্͛·ͤΜ
android.arch.lifecycle.LiveData<T> observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) ͜ͷLiveDataͷΛࢹ͢Δ ༩͑ΒΕͨLifeCycleOwnerͷϥΠϑαΠΫϧ ʹैͬͯɺobserverʹ௨͞ΕΔ
observerʹ௨͞ΕΔͷϥΠϑαΠΫϧ͕ ΞΫςΟϒͷͱ͖ͷΈ active
android.arch.lifecycle.LiveData<T> observeForever(@NonNull Observer<T> observer) ϥΠϑϥΠΫϧͷΞΫςΟϒঢ়ଶʹ͔͔ΘΒͣ௨Λड͚औΔ CREATED ͷঢ়ଶͰ௨Λड͚औΕΔ
android.arch.lifecycle.LiveData<T> onActive() ΞΫςΟϒঢ়ଶʹ͋ΔΦϒβʔόʔ͕1Ҏ্ʹͳͬͨࡍʹݺΕΔ onInactive() ΞΫςΟϒঢ়ଶʹ͋ΔΦϒβʔόʔ͕1ະຬʹͳͬͨࡍʹݺΕΔ getValue() ݱࡏͷΛฦ͢
android.arch.lifecycle.Observer<T> onChanged(@Nullable T t) ͕มߋ͞ΕͨࡍʹݺΕΔ LiveData ͔ΒͷΛड͚औΔγϯϓϧͳΠϯλϑΣʔε
android.arch.lifecycle.MutableLiveData<T> ௨ৗͷ LiveData ֎෦͔ΒΛઃఆͰ͖ͳ͍ MutableLiveData ֎෦͔ΒΛઃఆՄೳͳϝιουΛެ։͍ͯ͠Δ
android.arch.lifecycle.MutableLiveData<T> setValue(T value) Λઃఆ͢ΔʢϝΠϯεϨουͰݺͼग़͢͜ͱʣ postValue(T value) ϝΠϯεϨου֎͔ΒΛઃఆ͢Δࡍͷศརϝιου
android.arch.lifecycle.MediatorLiveData<T> addSource(@NonNull LiveData<S> source, @NonNull Observer<S> onChanged) LiveData ΛՃ͢Δ removeSource(@NonNull
LiveData<S> toRemote) LiveData Λআ͢Δ ෳͷ LiveData ΛଋͶͯཧͰ͖ΔΫϥε ܕͷҧ͏ෳͷLiveDataʹΠϕϯτΛͤ͞Δ͜ͱ͕Ͱ͖Δ
android.arch.lifecycle.Transformations static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source, @NonNull final
Function<X, Y> func) LiveData ʹରͯؔ͠(func)Λద༻͠ɺผͷ LiveData ʹΠϕϯτΛͤ͞Δ static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> trigger, @NonNull final Function<X, LiveData<Y>> func) mapͱྨࣅͨ͠ϝιου͕ͩؔ(func)͔Β LiveData Λฦ͢͜ͱ͕Ͱ͖Δ MediatorLiveData Λ͍ͨ͘͢͠ϢʔςΟϦςΟ Java͔Β͏ͱͱͯμα͘ͳΔʂKotlinਪ
՝
՝ 0 • Empty Activity Ͱ৽͍͠ϓϩδΣΫτΛ࡞Δ ʢύοέʔδ໊ com.example.livedatacodelab Λఆʣ •
build.grade dependencies { implementation “com.android.support:appcompat-v7:27.0.2” … implementation "android.arch.lifecycle:extensions:1.1.0" annotationProcessor "android.arch.lifecycle:compiler:1.1.0" } • MainActivity ͷ onCreate ͷதͰ LifecycleObserver ΛͬͯɺϥΠϑαΠΫϧ มߋ࣌ʹݱࡏͷϥΠϑαΠΫϧͷঢ়ଶΛϩάʹग़ྗ͢ΔΑ͏ʹ͢Δ • Ͱ͖ͨΒɺը໘Λดͨ͡Γɺ։͍ͨΓɺཪʹճͨ͠Γɺը໘Λճసͤͨ͞Γͯ͠ϥΠϑα ΠΫϧͷঢ়ଶ͕ͲͷΑ͏ʹมΘΔ͔Λ֬ೝ͢Δ
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle
savedInstanceState) { super.onCreate(savedInstanceState); … final LifecycleObserver lifecycleObserver = new LifecycleObserver() { @OnLifecycleEvent(Lifecycle.Event.ON_ANY) public void calledWhenOnAny(LifecycleOwner source, Lifecycle.Event event) { Log.d("CODELAB", "Lifecycle state:" + source.getLifecycle().getCurrentState().name()); } }; getLifecycle().addObserver(lifecycleObserver); } } ྫ https://gist.github.com/egglang/f9014730def32395daae657429a08f1b
՝ 1 • ݱࡏ࣌ࠁͷ࣌ HH:MM Λը໘ʹදࣔ͢Δ࣌ܭΞϓϦΛ࡞Δ ʢϩέʔϧͳͲͷࡉ͔͍͜ͱؾʹ͠ͳ͍Ͱʣ activity_main.xml ͷ TextView
ʹదͳ id Λ͚ͭͯɺͦ͜ʹग़͢ • ·ͣɺݹ͍ํ๏ͰͬͯΈΔ • Ұྫͱͯ͠ɺ࣍ͷϖʔδʹ ClockLegacy ΫϥεΛهࡌ͍ͯ͠·͢ɻ • ͜ͷΫϥεΛίϐϖͯ͠ MainActivity ͔ΒͬͯԼ͍͞ • ࣗͰΓ͍ͨਓ͜ΕΛΘͣʹ͖ʹ࣮ͯ͘͠Ε͍͍ͯͰ͢ɻ
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import java.util.Calendar;
import java.util.Date; public class ClockLegacy { private final Context mAppContext; public interface ClockListener { void onReceive(Date date); } private ClockListener mListener; private BroadcastReceiver mTimeTickBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (mListener != null) { mListener.onReceive(Calendar.getInstance().getTime()); } } }; public ClockLegacy(Context appContext) { mAppContext = appContext; } public void setClockListener(ClockListener listener) { if (mListener != null) { return; } mListener = listener; IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_TIME_TICK); mAppContext.registerReceiver(mTimeTickBroadcastReceiver, intentFilter); } public void removeClockListener() { mListener = null; mAppContext.unregisterReceiver(mTimeTickBroadcastReceiver); } } https://gist.github.com/egglang/ae119ac753b901bbd2301dc323fd7402
private TextView mText; private ClockLegacy.ClockListener mListener = new ClockLegacy.ClockListener() {
@Override public void onReceive(Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); String dateString = String.format("%02d:%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); mText.setText(dateString); Log.d("CODELAB", “The current time is " + dateString); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); .. mText = findViewById(R.id.text); mClockData = new ClockLegacy(getApplicationContext()); final LifecycleObserver observer = new LifecycleObserver() { @OnLifecycleEvent(Lifecycle.Event.ON_START) public void calledWhenOnStart(LifecycleOwner source) { mClockData.setClockListener(mListener); } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void calledWhenOnStop(LifecycleOwner source) { mClockData.removeClockListener(); } }; getLifecycle().addObserver(observer); } ClockLegacy Λͬͨ MainActivity ͷ࣮ྫ https://gist.github.com/egglang/8862bc8ed7131dc5b847dcd5680a2d4e
՝ 2 • ݹ͍ํ๏ ClockLegacy Ϋϥεͷ࣮Λ LiveData Ͱॻ͖͑ͯΈΔ • ClockLiveData
ΫϥεΛ࡞͢Δʢ࣍ͷϖʔδʹςϯϓϨ public class ClockLiveData extends LiveData<Date> { ... } • MainActivity ͷ onCreate ͷதͰ ClockLiveData ʹ observe ͢Δ ʢClockLegacy Λ͏ͷࢭΊΔʣ
import android.arch.lifecycle.LiveData; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter;
import android.util.Log; import java.util.Calendar; import java.util.Date; public class ClockLiveData extends LiveData<Date> { private final Context mAppContext; private BroadcastReceiver mTimeTickBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // ... } }; public ClockLiveData(Context appContext) { mAppContext = appContext; } @Override protected void onActive() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_TIME_TICK); mAppContext.registerReceiver(mTimeTickBroadcastReceiver, intentFilter); } @Override protected void onInactive() { mAppContext.unregisterReceiver(mTimeTickBroadcastReceiver); } } https://gist.github.com/egglang/319231352e5538bfb9641634480aee04
՝ 2 ͷ 2 • ClockLiveDataͷonActive, onInactive ʹϩάΛૠೖ͠ɺ͍ͭݺΕͯ ͍Δ͔֬ೝ͠·͠ΐ͏ •
HomeϘλϯΛԡͯ͠Recent Apps͔Β෮ؼͨ͠ͱ͖ʹɺ࣌ͷදࣔͲ͏ͳ Δʁ • ͙͢ʹ෮ؼͤͨ͞߹ʁ͔ͬͯΒ෮ؼͤͨ͞߹ʁ • observe ϝιουͷΘΓʹ observeForever ϝιουΛͬͨΒʁ • ը໘Λճసͤͨ͞ͱ͖ʁ • MainActivity ͔Β ClockLiveData ʹ setValue ͠Α͏ͱͨ͠Βʁ
՝ 3 • ؆୯ͳ ViewModel Λͪΐͬͱ͚ͩͬͯΈ·͠ΐ͏ • ClockLiveData ͷΛ MutableLiveData
ʹม͑ΔʢViewModel͔ΒΞΫηεͰ͖ΔΑ͏ʹʣ public class ClockLiveData extends MutableLiveData<Date> • ClockViewModel ΫϥεΛ৽ͨʹ࡞Δ public class ClockViewModel extends AndroidViewModel { private MutableLiveData<Date> clock; public ClockViewModel(@NonNull Application application) { super(application); } public LiveData<Date> getClock() { if (clock == null) { clock = new ClockLiveData(getApplication()); } return clock; } } • MainActivity ͷ onCreate Ͱ ViewModel Λऔಘ͠ɺgetClock Ͱ observer Λઃఆ͢Δ ClockViewModel clockViewModel = ViewModelProviders.of(this).get(ClockViewModel.class); clockViewModel.getClock().observe(...); • Ͱ͖ͨΒɺը໘Λճసͤͨ͞ͱ͖ʹ࣌ͷද͕ࣔͲ͏ͳΔ͔༡ΜͰΈͯԼ͍͞ ViewModelͷৄࡉ ࣍ճʹΓ·͢ͷͰ ਂ͘ߟ͑ͳ͍ͰԼ͍͞ https://gist.github.com/egglang/221a0dcb016d80766cabee91fe42d476
՝ 4 • σʔλόΠϯσΟϯάΛͬͯ LiveDataͱ TextView Λܨ͛ͯΈ·͠ΐ͏ • build.gradle android
{ compileSdkVersion 27 dataBinding { enabled = true } ... • ClockLiveData Ұมߋ͠ͳ͍ͰɺܕҾ Date ͷ··ͰʢStringʹ͠ͳ͍ͰʣͬͯΈ·͠ΐ͏ • ҎԼͷ˚ͷΑ͏ͳํ๏͋ΓͰ͕͢ࠓճͳΔ͘ແ͠Ͱ Transformations ͰLiveDataΛมͯ͠Լ͞ ͍ △ <TextView android:text="@{DateFormatUtils.format(hoge, `HH:mm`)}" /> ◦ <TextView android:text=“@{foo.bar)}" /> ࢀߟɿσʔλόΠϯσΟϯά https://developer.android.com/topic/libraries/data-binding/index.html?hl=ja
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="clockModel" type="com.example.livedatacodelab.ClockViewModel"/>
</data> <android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{clockModel.clock}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/> </android.support.constraint.ConstraintLayout> </layout> ώϯτ: activity_main.xml ͷྫ https://gist.github.com/egglang/95fbd6d5748f54960030e51d07eab1e4
package com.example.livedatacodelab; import android.arch.lifecycle.ViewModelProviders; import android.databinding.DataBindingUtil; import android.os.Bundle; import android.support.v7.app.AppCompatActivity;
import com.example.livedatacodelab.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ClockViewModel clockViewModel = ViewModelProviders.of(this).get(ClockViewModel.class); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.setLifecycleOwner(this); binding.setClockModel(clockViewModel); } } ώϯτ: MainActivity ͷྫ https://gist.github.com/egglang/e7aef650555b932298d6a0c21917c889
EOF