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
200
AbemaTVを支えるアプリの優しさ / abematv_devcon_2017
ogaclejapan
3
6.5k
Architecture Components - Lifecycle library
ogaclejapan
3
2.4k
Your app name
ogaclejapan
1
2.8k
Flux de Relax :)
ogaclejapan
13
61k
Dagger2 has been released!
ogaclejapan
3
3.2k
Other Decks in Programming
See All in Programming
CSS Linter による Baseline サポートの仕組み
ryo_manba
1
100
チームリードになって変わったこと
isaka1022
0
200
お前もAI鬼にならないか?👹Bolt & Cursor & Supabase & Vercelで人間をやめるぞ、ジョジョー!👺
taishiyade
6
4k
ペアーズでの、Langfuseを中心とした評価ドリブンなリリースサイクルのご紹介
fukubaka0825
2
320
パスキーのすべて ── 導入・UX設計・実装の紹介 / 20250213 パスキー開発者の集い
kuralab
3
780
Domain-Driven Transformation
hschwentner
2
1.9k
Unity Android XR入門
sakutama_11
0
160
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
2
280
Multi Step Form, Decentralized Autonomous Organization
pumpkiinbell
1
740
さいきょうのレイヤードアーキテクチャについて考えてみた
yahiru
3
750
SpringBoot3.4の構造化ログ #kanjava
irof
2
990
Ruby on cygwin 2025-02
fd0
0
140
Featured
See All Featured
Fireside Chat
paigeccino
34
3.2k
Building a Scalable Design System with Sketch
lauravandoore
461
33k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
366
25k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
174
51k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.2k
What's in a price? How to price your products and services
michaelherold
244
12k
Rails Girls Zürich Keynote
gr2m
94
13k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.2k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
240
Practical Orchestrator
shlominoach
186
10k
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!??
͞ͱϦεΫࢴҰॏ