Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
How to keep data between orientation changes
Search
Masaki Ogata
April 20, 2017
Programming
7
2.5k
How to keep data between orientation changes
AbemaTVで実装している画面回転を支えるデータ保持についての話
Masaki Ogata
April 20, 2017
Tweet
Share
More Decks by Masaki Ogata
See All by Masaki Ogata
Jetpack Composeで始めるServer Cache State
ogaclejapan
2
230
AbemaTVを支えるアプリの優しさ / abematv_devcon_2017
ogaclejapan
3
6.6k
Architecture Components - Lifecycle library
ogaclejapan
3
2.5k
Your app name
ogaclejapan
1
2.9k
Flux de Relax :)
ogaclejapan
13
61k
Dagger2 has been released!
ogaclejapan
3
3.2k
Other Decks in Programming
See All in Programming
iOSアプリ開発で 関数型プログラミングを実現する The Composable Architectureの紹介
yimajo
2
220
来たるべき 8.0 に備えて React 19 新機能と React Router 固有機能の取捨選択とすり合わせを考える
oukayuka
2
860
Cline指示通りに動かない? AI小説エージェントで学ぶ指示書の書き方と自動アップデートの仕組み
kamomeashizawa
1
580
Blazing Fast UI Development with Compose Hot Reload (droidcon New York 2025)
zsmb
1
240
ReadMoreTextView
fornewid
1
480
PostgreSQLのRow Level SecurityをPHPのORMで扱う Eloquent vs Doctrine #phpcon #track2
77web
2
390
生成AIコーディングとの向き合い方、AIと共創するという考え方 / How to deal with generative AI coding and the concept of co-creating with AI
seike460
PRO
1
330
『自分のデータだけ見せたい!』を叶える──Laravel × Casbin で複雑権限をスッキリ解きほぐす 25 分
akitotsukahara
1
570
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
280
0626 Findy Product Manager LT Night_高田スライド_speaker deck用
mana_takada
0
110
LT 2025-06-30: プロダクトエンジニアの役割
yamamotok
0
530
エラーって何種類あるの?
kajitack
5
310
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
173
14k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
BBQ
matthewcrist
89
9.7k
Speed Design
sergeychernyshev
32
1k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Making the Leap to Tech Lead
cromwellryan
134
9.3k
VelocityConf: Rendering Performance Case Studies
addyosmani
330
24k
The Straight Up "How To Draw Better" Workshop
denniskardys
234
140k
The Cost Of JavaScript in 2023
addyosmani
51
8.5k
Being A Developer After 40
akosma
90
590k
Transcript
CA.apk #2 @CyberAgent Masaki Ogata ը໘ճసΛࢧ͑Δσʔλอ࣋ :)
ࣗݾհ Masaki Ogata CyberAgent, Inc. / AbemaTV, Inc. ogaclejapan @ogaclejapan
New
20174݄11ൃച ࢁށໜथɼࡔాߊҰɼࠇ༸ɼ౻ా ୖຏɼࢁాߤɼాࡔெɼ۽୩ࢠɼ ຊརതɼࡔຊେɼখܗণथɼླ େوɼࢤำါلɹஶ B5ʗ192ϖʔδ ఆՁʢຊମ1,980ԁʴ੫ʣ ISBN 978-4-7741-8863-8 https://goo.gl/Jcy3lJ
New
ը໘ճసΛࢧ͑Δσʔλอ࣋ :) by AbemaTV
2017/4 ॎରԠϦϦʔε͠·ͨ͠
Կ͕มΘͬͨͷ͔ʁ
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tv.abema" > ... <activity android:name=".components.activity.MainActivity" android:configChanges="orientation|keyboardHidden| screenSize" android:screenOrientation="sensorLandscape"
android:theme="..." /> ... </manifest> AndroidManifest.xml
AndroidManifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tv.abema" > ... <activity android:name=".components.activity.MainActivity" android:configChanges="orientation|keyboardHidden| screenSize"
android:screenOrientation="sensorLandscape" android:theme="..." /> ... </manifest>
AndroidManifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tv.abema" > ... <activity android:name=".components.activity.MainActivity" android:screenOrientation="behind" android:theme="..."
/> ... </manifest>
Activity࠶ੜͱ ৽͍͠ੜ׆࢝Ί·ͨ͠$
ཧ༝̍ɿॎʗԣͰ࠷దͳUIΛ࣮ݱ͍ͨ͠
ཧ༝̎ɿMultiWindowʹରԠ͍ͨ͠
Activity࠶ੜԿ͕ͳͷ͔ʁ
Activity࠶ੜͷɿ • ϨΠΞτঢ়ଶͷ෮ݩ ʢChannelɺFullscreenɺ…ʣ • αʔόʔ͔Βऔಘͨ͠σʔλͷ࠶ར༻ • ॎʗԣͷը໘Γସ͑ͷγʔϜϨε͞
ҰൠతͳΞϓϩʔν
onSaveInstanceState(..)ͰBundleอଘ public class MainActivity extends AppCompatActivity { @Override protected void
onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable("foo", foo); ... } @Override protected void onCreate(Bundle savedInstanceState) { ... if (savedInstanceState != null) { Foo foo = savedInstanceState.getParcelable("foo"); }
(‘A`)ΫιΊΜͲͤ͐͘ʔʂ
AbemaTVͷΞϓϩʔν
onRetainCustomNonConfigurationInstance()ͰObjectฦ͢ public class MainActivity extends AppCompatActivity { @Override public Object
onRetainCustomNonConfigurationInstance() { return foo; } @Override protected void onCreate(Bundle savedInstanceState) { ... Object obj = getLastCustomNonConfigurationInstance(); if (obj instanceof Foo) { Foo foo = (Foo) obj; }
͜Εͩ! ! ‷( ŋŷŋ)و ̑̑ ŞƄŕ !
ͪΐͬ͜ͱιʔείʔυΛͬͯΈͨ
FragmentActivity.java public Object onRetainCustomNonConfigurationInstance() { return null; } @Override public
final Object onRetainNonConfigurationInstance() { ... Object custom = onRetainCustomNonConfigurationInstance(); ... NonConfigurationInstances nci = new NonConfigurationInstances(); nci.custom = custom; nci.fragments = fragments; nci.loaders = loaders; return nci; }
Activity.java public Object onRetainNonConfigurationInstance() { return null; } NonConfigurationInstances retainNonConfigurationInstances()
{ Object activity = onRetainNonConfigurationInstance(); ... NonConfigurationInstances nci = new NonConfigurationInstances(); nci.activity = activity; nci.children = children; nci.fragments = fragments; nci.loaders = loaders; ... return nci; }
ActivityThread.java public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) { return
performDestroyActivity(token, finishing, 0, false); } private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) { ActivityClientRecord r = mActivities.get(token); ... if (getNonConfigInstance) { try { r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances(); ...
ActivityThread.java private void handleRelaunchActivity(ActivityClientRecord tmp) { ... handleDestroyActivity(r.token, false, configChanges,
true); ... ... handleLaunchActivity(r, currentIntent, ".."); ... } private Activity performLaunchActivity(...) { activity.attach(appContext, ..., r.lastNonConfigurationInstances, ...); ... r.lastNonConfigurationInstances = null;
Configuration ChangeʹΑΔ Activity࠶ੜ࣌ͷΈ෮ݩՄೳ
AbemaTVͰ Ͳ͏࣮͍ͯ͠Δͷ͔ʁ
AbemaTVͷΞʔΩςΫνϟɿ https://speakerdeck.com/ogaclejapan/flux-de-relax
AbemaTVͷFluxΞʔΩςΫνϟɿ
ը໘ճసͰഁغͤ͞ͳ͍DaggerͷComponentΛؚΊΔ @Override public ScreenComponent getScreenComponent() { if (screenComponent == null)
{ ScreenInstance retainedInstance = (ScreenInstance) getLastCustomNonConfigurationInstance(); if (retainedInstance == null) { ... screenComponent = Components.forApp(this).plus(...); } else { screenComponent = retainedInstance.component; } } return screenComponent; } @Override public Object onRetainCustomNonConfigurationInstance() { return new ScreenInstance(screenComponent, ...); }
AbemaTVͷDIίϯϙʔωϯτߏɿ AppComponent: ʢશମʣ ScreenComponent: ʢը໘୯Ґʣ ActivityComponent: ʢը໘୯Ґʣ ը໘ճసΛӽ͑ͯσʔλΛอ࣋͢ΔͨΊʹ ScreenίϯϙʔωϯτΛՃɻ
Activity࠶ੜͷɿ •ϨΠΞτঢ়ଶͷ෮ݩ ʢChannelɺFullscreenɺ…ʣ • αʔόʔ͔Βऔಘͨ͠σʔλͷ࠶ར༻ • ॎʗԣͷը໘Γସ͑ͷγʔϜϨε͞
͓ΘΓʹ /** * Return the value previously returned from *
{@link #onRetainCustomNonConfigurationInstance()}. */ @SuppressWarnings("deprecation") public Object getLastCustomNonConfigurationInstance() { NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); return nc != null ? nc.custom : null; } d..deprecation!??
͞ͱϦεΫࢴҰॏ