Slide 1

Slide 1 text

CA.apk #2 @CyberAgent Masaki Ogata ը໘ճసΛࢧ͑Δσʔλอ࣋ :)

Slide 2

Slide 2 text

ࣗݾ঺հ Masaki Ogata CyberAgent, Inc. / AbemaTV, Inc. ogaclejapan @ogaclejapan New

Slide 3

Slide 3 text

2017೥4݄11೔ൃച ࢁށໜथɼࡔాߊҰɼࠇ઒༸ɼ౻ా ୖຏɼࢁాߤɼాࡔ࿨ெɼ۽୩஌ࢠɼ ৿ຊརതɼࡔຊ࿨େɼখܗণथɼླ ໦େوɼࢤำါلɹஶ B5൑ʗ192ϖʔδ ఆՁʢຊମ1,980ԁʴ੫ʣ ISBN 978-4-7741-8863-8 https://goo.gl/Jcy3lJ New

Slide 4

Slide 4 text

ը໘ճసΛࢧ͑Δσʔλอ࣋ :) by AbemaTV

Slide 5

Slide 5 text

2017/4 ॎରԠϦϦʔε͠·ͨ͠

Slide 6

Slide 6 text

Կ͕มΘͬͨͷ͔ʁ

Slide 7

Slide 7 text

... ... AndroidManifest.xml

Slide 8

Slide 8 text

AndroidManifest.xml ... ...

Slide 9

Slide 9 text

AndroidManifest.xml ... ...

Slide 10

Slide 10 text

Activity࠶ੜ੒ͱ ৽͍͠ੜ׆࢝Ί·ͨ͠$

Slide 11

Slide 11 text

ཧ༝̍ɿॎʗԣͰ࠷దͳUIΛ࣮ݱ͍ͨ͠

Slide 12

Slide 12 text

ཧ༝̎ɿMultiWindowʹରԠ͍ͨ͠

Slide 13

Slide 13 text

Activity࠶ੜ੒͸Կ͕໰୊ͳͷ͔ʁ

Slide 14

Slide 14 text

Activity࠶ੜ੒ͷ໰୊఺ɿ • ϨΠΞ΢τঢ়ଶͷ෮ݩ
 ʢChannelɺFullscreenɺ…ʣ • αʔόʔ͔Βऔಘͨ͠σʔλͷ࠶ར༻ • ॎʗԣͷը໘੾Γସ͑ͷγʔϜϨε͞

Slide 15

Slide 15 text

ҰൠతͳΞϓϩʔν

Slide 16

Slide 16 text

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"); }

Slide 17

Slide 17 text

(‘A`)ΫιΊΜͲͤ͐͘ʔʂ

Slide 18

Slide 18 text

AbemaTVͷΞϓϩʔν

Slide 19

Slide 19 text

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; }

Slide 20

Slide 20 text

͜Εͩ! ! ‷( ŋŷŋ)و ̑̑ ŞƄŕ !

Slide 21

Slide 21 text

ͪΐͬ͜ͱιʔείʔυΛ௥ͬͯΈͨ

Slide 22

Slide 22 text

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; }

Slide 23

Slide 23 text

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; }

Slide 24

Slide 24 text

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(); ...

Slide 25

Slide 25 text

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;

Slide 26

Slide 26 text

Configuration ChangeʹΑΔ Activity࠶ੜ੒࣌ͷΈ෮ݩՄೳ

Slide 27

Slide 27 text

AbemaTVͰ͸ Ͳ͏࣮૷͍ͯ͠Δͷ͔ʁ

Slide 28

Slide 28 text

AbemaTVͷΞʔΩςΫνϟɿ https://speakerdeck.com/ogaclejapan/flux-de-relax

Slide 29

Slide 29 text

AbemaTVͷFluxΞʔΩςΫνϟɿ

Slide 30

Slide 30 text

ը໘ճసͰഁغͤ͞ͳ͍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, ...); }

Slide 31

Slide 31 text

AbemaTVͷDIίϯϙʔωϯτߏ੒ɿ AppComponent: ʢશମʣ ScreenComponent: ʢը໘୯Ґʣ ActivityComponent: ʢը໘୯Ґʣ ը໘ճసΛӽ͑ͯσʔλΛอ࣋͢ΔͨΊʹ ScreenίϯϙʔωϯτΛ௥Ճɻ

Slide 32

Slide 32 text

Activity࠶ੜ੒ͷ໰୊఺ɿ •ϨΠΞ΢τঢ়ଶͷ෮ݩ 
 ʢChannelɺFullscreenɺ…ʣ • αʔόʔ͔Βऔಘͨ͠σʔλͷ࠶ར༻ • ॎʗԣͷը໘੾Γସ͑ͷγʔϜϨε͞

Slide 33

Slide 33 text

͓ΘΓʹ /** * 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!??

Slide 34

Slide 34 text

଎͞ͱϦεΫ͸ࢴҰॏ