Successfully reported this slideshow.

React Native Androidはなぜ動くのか

13

Share

Upcoming SlideShare
React Nativeの光と闇
React Nativeの光と闇
Loading in …3
×
1 of 144
1 of 144

React Native Androidはなぜ動くのか

13

Share

Download to read offline

Description

DroidKaigi 2018で講演したやつです

Transcript

  1. 1. React Native Android 2018.2.9 DroidKaigi 2018 Yukiya Nakagawa / @Nkzn Room2 12:50-13:40 #droidkaigi_room2
  2. 2. Who are you? • Yukiya Nakagawa / @Nkzn • @ • • Android 2009 • React Native v0.17
  3. 3. React Native
  4. 4. • • Hello World • Production
  5. 5. Target • React Native 
 Android • Android React Native
  6. 6. Best Match • • JavaScript • React Native
  7. 7. Agenda
  8. 8. Overview
  9. 9. React
  10. 10. React is
  11. 11. React 2017
  12. 12. React https://facebook.github.io/react/
  13. 13. • • JSX • Reactive
  14. 14. JSX
  15. 15. <div> <Header /> <LeftPane /> <RightPane name={myName}/> </div>
  16. 16. React
  17. 17. import React from 'react'; import ReactDOM from 'react-dom'; const styles = { container: {display: 'flex', flexDirection: ‘row', …} }; class App extends React.Component { render() { const myName = /* props or state */; return ( <div style={styles.container}> <Header /> <LeftPane /> <RightPane name={myName} /> </div> ); } } ReactDOM.render( <App />, document.getElementById('app') );
  18. 18. Virtual DOM
  19. 19. <ccc style={{ width: 200, color: "red" }} enabled={true} />
  20. 20. React VirtualDOM DOM
  21. 21. React VirtualDOM DOM
  22. 22. React VirtualDOM DOM
  23. 23. React VirtualDOM DOM
  24. 24. https://tylermcginnis.com/an-introduction-to-life-cycle-events-in-react-js/
  25. 25. https://developer.android.com/reference/android/app/Activity.html
  26. 26. React is • Facebook JS • https://facebook.github.io/react/ • • • View View View
  27. 27. React Native React
  28. 28. import React from 'react'; import ReactDOM from 'react-dom'; const styles = { container: {display: 'flex', flexDirection: ‘row', …} }; class App extends React.Component { render() { const myName = /* props or state */; return ( <div style={styles.container}> <Header /> <LeftPane /> <RightPane name={myName} /> </div> ); } } ReactDOM.render( <App />, document.getElementById('app') ); import ReactDOM from 'react-dom'; div div ReactDOM.render( <App />, document.getElementById('app') );
  29. 29. import React from "react"; import { View, AppRegistry } from "react-native"; const styles = { container: {display: 'flex', flexDirection: ‘row', …} }; class App extends React.Component { render() { const myName = /* props or state */; return ( <View style={styles.container}> <Header /> <LeftPane /> <RightPane name={myName} /> </View> ); } } AppRegistry.registerComponent( "MyReactNativeApp", () => App );
  30. 30. React ReactDOM
  31. 31. React UI React Native
  32. 32. React is not
  33. 33. React • React DOM • React View Web • React Native • React View UI
  34. 34. React • View props • • • DOM • UI • • View • UI GUI Virtual DOM
  35. 35. React React DOM 

  36. 36. React is not • React • React View • React View
  37. 37. React Native Android
  38. 38. React Native
  39. 39. React Native • JavaScript • JS Java • React Android View •
  40. 40. Activity ReactRootView (FrameLayout) JS
  41. 41. Activity ReactRootView JS
  42. 42. Activity ReactRootView JS
  43. 43. Activity ReactRootView JS
  44. 44. JavaScript
  45. 45. Activity ReactRootView JS
  46. 46. JS • JavaScriptCore • WebKit(Safari) JS • Facebook Android NDK 
 https://github.com/facebook/android-jsc
  47. 47. • ReactRootView God FrameLayout • ReactInstanceManager JS • CatalystInstance JNI
  48. 48. • ReactInstanceManager • JSC • JS • CatalystInstance • JNI Java • Java JSC IF startReactApplication() JS
  49. 49. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java Activity RN
  50. 50. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java ReactRootView FrameLayout
  51. 51. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java ReactInstanceManager
  52. 52. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java RootView InstanceManager
  53. 53. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java setContentView
  54. 54. import React from "react"; import { View, AppRegistry } from "react-native"; const styles = { container: {display: 'flex', flexDirection: ‘row', …} }; class App extends React.Component { render() { const myName = /* props or state */; return ( <View style={styles.container}> <Header /> <LeftPane /> <RightPane name={myName} /> </View> ); } } AppRegistry.registerComponent( "MyReactNativeApp", () => App ); MyReactNativeApp
  55. 55. ReactInstance • React JS Java • React React
  56. 56. JSC JS ReactInstanceManager ↑ View ReactRootView ReactRootView#startReactApplication() Java JavaScript
  57. 57. NDK
  58. 58. JS Java
  59. 59. Activity ReactRootView JS
  60. 60. Native Modules
  61. 61. Native Modules • Java Swift JS • RN Android Java JS •
  62. 62. Native Modules 3
  63. 63. const ToastAndroid = require('ToastAndroid'); ToastAndroid.show(" ", ToastAndroid.SHORT); JS Toast JS
  64. 64. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } Toast Java
  65. 65. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } ReactContextBaseJavaModule Java
  66. 66. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } Native Module Java ※name
  67. 67. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } JS @ReactMethod Java
  68. 68. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } Android not UI Thread Java
  69. 69. ReactInstanceManager JS
  70. 70. public class ToastPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Arrays.<NativeModule>asList( new ToastModule(reactContext)); } } ReactPackage Java
  71. 71. public class ToastPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Arrays.<NativeModule>asList( new ToastModule(reactContext)); } } ReactPackage Java
  72. 72. public class ToastPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Arrays.<NativeModule>asList( new ToastModule(reactContext)); } } createNativeModules Java
  73. 73. ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .addPackage(new ToastPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); ReactInstanceManager Java
  74. 74. ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .addPackage(new ToastPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); Java
  75. 75. ReactInstanceManager JSC JS
  76. 76. const ToastAndroid = require('ToastAndroid'); ToastAndroid.show(" ", ToastAndroid.SHORT); JavaScript JS
  77. 77. Great!
  78. 78. @ReactMethod
  79. 79. Readable/Writable Map/Array • JS Java/C++
  80. 80. + hasKey(name: String): boolean + isNull(name: String): boolean + getBoolean(name: String): boolean + getDouble(name: String): double + getInt(name: String): int + getString(name: String): String + getArray(name: String): ReadableArray + getMap(name: String): ReadableMap + getDynamic(name: String): Dynamic + getType(name: String): ReadableType + keySetIterator(): ReadableMapKeySetIterator + toHashMap(): HashMap<String, Object> + putNull(key: String) + putBoolean(key: String, value: boolean) + putDouble(key: String, value: double) + putInt(key: String, value: int) + putString(key: String, value: String) + putArray(key: String, value: WritableArray) + putMap(key: String, value: WritableMap) + merge(source: ReadableMap);
  81. 81. + size(index: int): int + isNull(index: int): boolean + getBoolean(index: int): boolean + getDouble(index: int): double + getInt(index: int): int + getString(index: int): String + getArray(index: int): ReadableArray + getMap(index: int): ReadableMap + getDynamic(index: int): Dynamic + getType(index: int): ReadableType + toArrayList(index: int): ArrayList<Object> + pushNull() + pushBoolean(value: boolean) + pushDouble(value: double) + pushInt(value: int) + pushString(value: String) + pushArray(array: WritableArray) + pushMap(map: WritableMap)
  82. 82. JSC++Java { name: "nkzn", age: 30 } [ "cupcake", "donut", "eclair" ]
  83. 83. Promise
  84. 84. Promise • ReactMethod Promise JS Promise • promise.resolve() promise.reject() JS
  85. 85. @ReactMethod public void getString(Promise promise) { try { ClipboardManager clipboard = getClipboardService(); ClipData clipData = clipboard.getPrimaryClip(); if (clipData == null) { promise.resolve(""); } else if (clipData.getItemCount() >= 1) { ClipData.Item firstItem = clipboard .getPrimaryClip() .getItemAt(0); promise.resolve("" + firstItem.getText()); } else { promise.resolve(""); } } catch (Exception e) { promise.reject(e); } } Clipboard#getString Java
  86. 86. @ReactMethod public void getString(Promise promise) { try { ClipboardManager clipboard = getClipboardService(); ClipData clipData = clipboard.getPrimaryClip(); if (clipData == null) { promise.resolve(""); } else if (clipData.getItemCount() >= 1) { ClipData.Item firstItem = clipboard .getPrimaryClip() .getItemAt(0); promise.resolve("" + firstItem.getText()); } else { promise.resolve(""); } } catch (Exception e) { promise.reject(e); } } JS RxJava onNext, onError ※ Clipboard Java
  87. 87. // Promise Style Clipboard.getString() .then(str => { // use string }); // async/await Style async function getClip() { const str = await Clipboard.getString(); return str; } JS JS
  88. 88. Java JS
  89. 89. EventEmitter Android Broadcast
  90. 90. // JS class RCTDeviceEventEmitter extends EventEmitter { emit(eventType) {...} addListener(eventType, listener, context) {...} removeAllListeners(eventType) {...} removeSubscription(subscription) {...} } JS RCTDeviceEventEmitter.js ※ emit EventEmitter
  91. 91. // interface // ReactInstanceModule public interface RCTDeviceEventEmitter extends JavaScriptModule { void emit(String eventName, @Nullable Object data); } Java DeviceEventManagerModule.java
  92. 92. // JS public void emitHardwareBackPressed() { getReactApplicationContext() .getJSModule(RCTDeviceEventEmitter.class) .emit("hardwareBackPress", null); } JS emit Java DeviceEventManagerModule.java
  93. 93. C++
  94. 94. JS→Java ReactModule Java→JS JavaScriptModule
  95. 95. ReactModule React 🤔
  96. 96. React Android 
 View
  97. 97. Activity ReactRootView JS
  98. 98. React DOM Android
  99. 99. Android View React
  100. 100. Native UI Components 3
  101. 101. public class PhotoView extends ImageView { public PhotoView(Context context) { ... } // Android } Java
  102. 102. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } React Java
  103. 103. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } SimpleViewManager Java
  104. 104. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } React Java
  105. 105. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } Android View Java
  106. 106. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } props Java
  107. 107. // @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } // <PhotoView uri="http://example.com/hoge.png" /> Java JS
  108. 108. public class MyLibraryPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Arrays.<ViewManager>asList( new PhotoViewManager() ); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Collections.emptyList(); } } ReactPackage Java
  109. 109. public class MyLibraryPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Arrays.<ViewManager>asList( new PhotoViewManager() ); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Collections.emptyList(); } } createViewManagers Java
  110. 110. ReactInstanceManager Native Modules
  111. 111. import PropTypes from “prop-types”; import { requireNativeComponent, View } from "react-native"; const name = "PhotoView"; const photoViewInterface = { name: name, displayName: name, propTypes: { ...View.propTypes, uri: PropTypes.string.isRequired } }; export default requireNativeComponent(name, photoViewInterface); JS PhotoView.js JS Java Java
  112. 112. import PhotoView from "./PhotoView"; // <PhotoView uri="http://example.com/hoge.png" /> JS
  113. 113. • JS UI props interface • ViewManager
  114. 114. React Android View
  115. 115. Native Module UIManagerModule
  116. 116. UIManagerModule • React React Native React DOM Java • createView updateView ReactMethod
  117. 117. @ReactMethod public void createView( int tag, String className, int rootViewTag, ReadableMap props) { mUIImplementation.createView( tag, className, rootViewTag, props); } @ReactMethod public void updateView( int tag, String className, ReadableMap props) { mUIImplementation.updateView( tag, className, props); } UIManagerModule.java
  118. 118. React ReactMethod
  119. 119. View • React View Java ReactShadowNode Java View Yoga • UIManagerModule React Java View • View View
  120. 120. Yoga https://facebook.github.io/yoga/
  121. 121. • Flexbox Yoga Android • borderColor ViewManager Android setBorderColor
  122. 122. React
  123. 123. • Java C++ JS • ReactInstanceManager • ReactInstanceManager Native Module JavaScript Module • UI Native Module
  124. 124. React Native Modules
  125. 125. Android
  126. 126. • Android APK • APK
  127. 127. Application Sources import $buildDir/intermediates /assets/release /res/merged/release
  128. 128. iOS require("path/to/awesome.png")
  129. 129. iOS
  130. 130. React Native Android • API View Android • • JS JS
  131. 131. • Android SDK iOS SDK • Web • JS
  132. 132. • React Native 
 http://tomoima525.hatenablog.com/entry/2017/12/19/180523 • Android 
 7 
 https://peaks.cc/Nkzn/architecture_patterns @tomoaki_imai

Description

DroidKaigi 2018で講演したやつです

Transcript

  1. 1. React Native Android 2018.2.9 DroidKaigi 2018 Yukiya Nakagawa / @Nkzn Room2 12:50-13:40 #droidkaigi_room2
  2. 2. Who are you? • Yukiya Nakagawa / @Nkzn • @ • • Android 2009 • React Native v0.17
  3. 3. React Native
  4. 4. • • Hello World • Production
  5. 5. Target • React Native 
 Android • Android React Native
  6. 6. Best Match • • JavaScript • React Native
  7. 7. Agenda
  8. 8. Overview
  9. 9. React
  10. 10. React is
  11. 11. React 2017
  12. 12. React https://facebook.github.io/react/
  13. 13. • • JSX • Reactive
  14. 14. JSX
  15. 15. <div> <Header /> <LeftPane /> <RightPane name={myName}/> </div>
  16. 16. React
  17. 17. import React from 'react'; import ReactDOM from 'react-dom'; const styles = { container: {display: 'flex', flexDirection: ‘row', …} }; class App extends React.Component { render() { const myName = /* props or state */; return ( <div style={styles.container}> <Header /> <LeftPane /> <RightPane name={myName} /> </div> ); } } ReactDOM.render( <App />, document.getElementById('app') );
  18. 18. Virtual DOM
  19. 19. <ccc style={{ width: 200, color: "red" }} enabled={true} />
  20. 20. React VirtualDOM DOM
  21. 21. React VirtualDOM DOM
  22. 22. React VirtualDOM DOM
  23. 23. React VirtualDOM DOM
  24. 24. https://tylermcginnis.com/an-introduction-to-life-cycle-events-in-react-js/
  25. 25. https://developer.android.com/reference/android/app/Activity.html
  26. 26. React is • Facebook JS • https://facebook.github.io/react/ • • • View View View
  27. 27. React Native React
  28. 28. import React from 'react'; import ReactDOM from 'react-dom'; const styles = { container: {display: 'flex', flexDirection: ‘row', …} }; class App extends React.Component { render() { const myName = /* props or state */; return ( <div style={styles.container}> <Header /> <LeftPane /> <RightPane name={myName} /> </div> ); } } ReactDOM.render( <App />, document.getElementById('app') ); import ReactDOM from 'react-dom'; div div ReactDOM.render( <App />, document.getElementById('app') );
  29. 29. import React from "react"; import { View, AppRegistry } from "react-native"; const styles = { container: {display: 'flex', flexDirection: ‘row', …} }; class App extends React.Component { render() { const myName = /* props or state */; return ( <View style={styles.container}> <Header /> <LeftPane /> <RightPane name={myName} /> </View> ); } } AppRegistry.registerComponent( "MyReactNativeApp", () => App );
  30. 30. React ReactDOM
  31. 31. React UI React Native
  32. 32. React is not
  33. 33. React • React DOM • React View Web • React Native • React View UI
  34. 34. React • View props • • • DOM • UI • • View • UI GUI Virtual DOM
  35. 35. React React DOM 

  36. 36. React is not • React • React View • React View
  37. 37. React Native Android
  38. 38. React Native
  39. 39. React Native • JavaScript • JS Java • React Android View •
  40. 40. Activity ReactRootView (FrameLayout) JS
  41. 41. Activity ReactRootView JS
  42. 42. Activity ReactRootView JS
  43. 43. Activity ReactRootView JS
  44. 44. JavaScript
  45. 45. Activity ReactRootView JS
  46. 46. JS • JavaScriptCore • WebKit(Safari) JS • Facebook Android NDK 
 https://github.com/facebook/android-jsc
  47. 47. • ReactRootView God FrameLayout • ReactInstanceManager JS • CatalystInstance JNI
  48. 48. • ReactInstanceManager • JSC • JS • CatalystInstance • JNI Java • Java JSC IF startReactApplication() JS
  49. 49. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java Activity RN
  50. 50. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java ReactRootView FrameLayout
  51. 51. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java ReactInstanceManager
  52. 52. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java RootView InstanceManager
  53. 53. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication( mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } Java setContentView
  54. 54. import React from "react"; import { View, AppRegistry } from "react-native"; const styles = { container: {display: 'flex', flexDirection: ‘row', …} }; class App extends React.Component { render() { const myName = /* props or state */; return ( <View style={styles.container}> <Header /> <LeftPane /> <RightPane name={myName} /> </View> ); } } AppRegistry.registerComponent( "MyReactNativeApp", () => App ); MyReactNativeApp
  55. 55. ReactInstance • React JS Java • React React
  56. 56. JSC JS ReactInstanceManager ↑ View ReactRootView ReactRootView#startReactApplication() Java JavaScript
  57. 57. NDK
  58. 58. JS Java
  59. 59. Activity ReactRootView JS
  60. 60. Native Modules
  61. 61. Native Modules • Java Swift JS • RN Android Java JS •
  62. 62. Native Modules 3
  63. 63. const ToastAndroid = require('ToastAndroid'); ToastAndroid.show(" ", ToastAndroid.SHORT); JS Toast JS
  64. 64. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } Toast Java
  65. 65. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } ReactContextBaseJavaModule Java
  66. 66. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } Native Module Java ※name
  67. 67. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } JS @ReactMethod Java
  68. 68. @ReactModule(name = "ToastAndroid") public class ToastModule extends ReactContextBaseJavaModule { @ReactMethod public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(() -> { Toast.makeText( getReactApplicationContext(), message, duration).show(); }); } } Android not UI Thread Java
  69. 69. ReactInstanceManager JS
  70. 70. public class ToastPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Arrays.<NativeModule>asList( new ToastModule(reactContext)); } } ReactPackage Java
  71. 71. public class ToastPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Arrays.<NativeModule>asList( new ToastModule(reactContext)); } } ReactPackage Java
  72. 72. public class ToastPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Arrays.<NativeModule>asList( new ToastModule(reactContext)); } } createNativeModules Java
  73. 73. ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .addPackage(new ToastPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); ReactInstanceManager Java
  74. 74. ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .addPackage(new ToastPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); Java
  75. 75. ReactInstanceManager JSC JS
  76. 76. const ToastAndroid = require('ToastAndroid'); ToastAndroid.show(" ", ToastAndroid.SHORT); JavaScript JS
  77. 77. Great!
  78. 78. @ReactMethod
  79. 79. Readable/Writable Map/Array • JS Java/C++
  80. 80. + hasKey(name: String): boolean + isNull(name: String): boolean + getBoolean(name: String): boolean + getDouble(name: String): double + getInt(name: String): int + getString(name: String): String + getArray(name: String): ReadableArray + getMap(name: String): ReadableMap + getDynamic(name: String): Dynamic + getType(name: String): ReadableType + keySetIterator(): ReadableMapKeySetIterator + toHashMap(): HashMap<String, Object> + putNull(key: String) + putBoolean(key: String, value: boolean) + putDouble(key: String, value: double) + putInt(key: String, value: int) + putString(key: String, value: String) + putArray(key: String, value: WritableArray) + putMap(key: String, value: WritableMap) + merge(source: ReadableMap);
  81. 81. + size(index: int): int + isNull(index: int): boolean + getBoolean(index: int): boolean + getDouble(index: int): double + getInt(index: int): int + getString(index: int): String + getArray(index: int): ReadableArray + getMap(index: int): ReadableMap + getDynamic(index: int): Dynamic + getType(index: int): ReadableType + toArrayList(index: int): ArrayList<Object> + pushNull() + pushBoolean(value: boolean) + pushDouble(value: double) + pushInt(value: int) + pushString(value: String) + pushArray(array: WritableArray) + pushMap(map: WritableMap)
  82. 82. JSC++Java { name: "nkzn", age: 30 } [ "cupcake", "donut", "eclair" ]
  83. 83. Promise
  84. 84. Promise • ReactMethod Promise JS Promise • promise.resolve() promise.reject() JS
  85. 85. @ReactMethod public void getString(Promise promise) { try { ClipboardManager clipboard = getClipboardService(); ClipData clipData = clipboard.getPrimaryClip(); if (clipData == null) { promise.resolve(""); } else if (clipData.getItemCount() >= 1) { ClipData.Item firstItem = clipboard .getPrimaryClip() .getItemAt(0); promise.resolve("" + firstItem.getText()); } else { promise.resolve(""); } } catch (Exception e) { promise.reject(e); } } Clipboard#getString Java
  86. 86. @ReactMethod public void getString(Promise promise) { try { ClipboardManager clipboard = getClipboardService(); ClipData clipData = clipboard.getPrimaryClip(); if (clipData == null) { promise.resolve(""); } else if (clipData.getItemCount() >= 1) { ClipData.Item firstItem = clipboard .getPrimaryClip() .getItemAt(0); promise.resolve("" + firstItem.getText()); } else { promise.resolve(""); } } catch (Exception e) { promise.reject(e); } } JS RxJava onNext, onError ※ Clipboard Java
  87. 87. // Promise Style Clipboard.getString() .then(str => { // use string }); // async/await Style async function getClip() { const str = await Clipboard.getString(); return str; } JS JS
  88. 88. Java JS
  89. 89. EventEmitter Android Broadcast
  90. 90. // JS class RCTDeviceEventEmitter extends EventEmitter { emit(eventType) {...} addListener(eventType, listener, context) {...} removeAllListeners(eventType) {...} removeSubscription(subscription) {...} } JS RCTDeviceEventEmitter.js ※ emit EventEmitter
  91. 91. // interface // ReactInstanceModule public interface RCTDeviceEventEmitter extends JavaScriptModule { void emit(String eventName, @Nullable Object data); } Java DeviceEventManagerModule.java
  92. 92. // JS public void emitHardwareBackPressed() { getReactApplicationContext() .getJSModule(RCTDeviceEventEmitter.class) .emit("hardwareBackPress", null); } JS emit Java DeviceEventManagerModule.java
  93. 93. C++
  94. 94. JS→Java ReactModule Java→JS JavaScriptModule
  95. 95. ReactModule React 🤔
  96. 96. React Android 
 View
  97. 97. Activity ReactRootView JS
  98. 98. React DOM Android
  99. 99. Android View React
  100. 100. Native UI Components 3
  101. 101. public class PhotoView extends ImageView { public PhotoView(Context context) { ... } // Android } Java
  102. 102. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } React Java
  103. 103. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } SimpleViewManager Java
  104. 104. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } React Java
  105. 105. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } Android View Java
  106. 106. public class PhotoViewManager extends SimpleViewManager<PhotoView> { @Override public String getName() { return "PhotoView"; } @Override protected PhotoView createViewInstance( ThemedReactContext reactContext) { return new PhotoView(reactContext); } @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } } props Java
  107. 107. // @ReactProp(name = "uri") public void setUri(PhotoView view, @Nullable String uri) { view.setUri(uri); } // <PhotoView uri="http://example.com/hoge.png" /> Java JS
  108. 108. public class MyLibraryPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Arrays.<ViewManager>asList( new PhotoViewManager() ); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Collections.emptyList(); } } ReactPackage Java
  109. 109. public class MyLibraryPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers( ReactApplicationContext reactContext) { return Arrays.<ViewManager>asList( new PhotoViewManager() ); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { return Collections.emptyList(); } } createViewManagers Java
  110. 110. ReactInstanceManager Native Modules
  111. 111. import PropTypes from “prop-types”; import { requireNativeComponent, View } from "react-native"; const name = "PhotoView"; const photoViewInterface = { name: name, displayName: name, propTypes: { ...View.propTypes, uri: PropTypes.string.isRequired } }; export default requireNativeComponent(name, photoViewInterface); JS PhotoView.js JS Java Java
  112. 112. import PhotoView from "./PhotoView"; // <PhotoView uri="http://example.com/hoge.png" /> JS
  113. 113. • JS UI props interface • ViewManager
  114. 114. React Android View
  115. 115. Native Module UIManagerModule
  116. 116. UIManagerModule • React React Native React DOM Java • createView updateView ReactMethod
  117. 117. @ReactMethod public void createView( int tag, String className, int rootViewTag, ReadableMap props) { mUIImplementation.createView( tag, className, rootViewTag, props); } @ReactMethod public void updateView( int tag, String className, ReadableMap props) { mUIImplementation.updateView( tag, className, props); } UIManagerModule.java
  118. 118. React ReactMethod
  119. 119. View • React View Java ReactShadowNode Java View Yoga • UIManagerModule React Java View • View View
  120. 120. Yoga https://facebook.github.io/yoga/
  121. 121. • Flexbox Yoga Android • borderColor ViewManager Android setBorderColor
  122. 122. React
  123. 123. • Java C++ JS • ReactInstanceManager • ReactInstanceManager Native Module JavaScript Module • UI Native Module
  124. 124. React Native Modules
  125. 125. Android
  126. 126. • Android APK • APK
  127. 127. Application Sources import $buildDir/intermediates /assets/release /res/merged/release
  128. 128. iOS require("path/to/awesome.png")
  129. 129. iOS
  130. 130. React Native Android • API View Android • • JS JS
  131. 131. • Android SDK iOS SDK • Web • JS
  132. 132. • React Native 
 http://tomoima525.hatenablog.com/entry/2017/12/19/180523 • Android 
 7 
 https://peaks.cc/Nkzn/architecture_patterns @tomoaki_imai

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

×