With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep...

37
www.nevernull.io © 2020 NEVERNULL ® GmbH. All Rights Reserved. With Micronaut on iOS & Android A modern Java-based approach for mobile app development Dr. Daniel Thommes NEVERNULL ® GmbH

Transcript of With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep...

Page 1: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

With Micronaut on iOS & Android A modern Java-based approach for mobile app development

Dr. Daniel Thommes

NEVERNULL® GmbH

Page 2: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

2

WITH MICRONAUT ON IOS & ANDROIDNEVERNULL

• Overview & Deep Dive:

Dependency Injection

systems for mobile Java

• How Java Forum app

applies DI

• The app’s internals

• ORM

• Sync

• Rx

• Cross-Platform GUI

Page 3: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

3

DEPENDENCY INJECTION REQUIREMENTSNEVERNULL

• Why Dependency Injection?

• Component-based development

• Polymorphic use of interchangeable implementations

• Maximizing code re-use

• Increase productivity

Requirements

• Good Performance (on mobile)

• Good Developer Experience

Page 4: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

4

DEPENDENCY INJECTION ON ANDROIDNEVERNULL

History of DI systems for mobile

• RoboGuice (2011)

• RoboSpring (2012)

• Dagger 1.0 (2012)

• Dagger 2.0 (2012)

• Micronaut (2018)

Page 5: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

5

PERFORMANCE OF DINEVERNULL

• Problem: Frequent restarts due to limited memory and

missing swapping

• Reflection is slow, especially on mobile.

• Reflection-based DI metadata allocate a lot of memory.

• Result: Slow start times for reflection-based DI

Page 6: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

6

PERFORMANCE OF DINEVERNULL

public class MainActivity extends AppCompatActivity {

@Inject private Vibrator vibrator;

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DISystem.inject(this); }}

MainActivity

AppCompatActivity

FragmentActivity

androidx.activity

ComponentActivity

androidx.core.app

ComponentActivity

Activity

ContextThemeWrapper

ContextWrapper

Context

Page 7: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

7

PERFORMANCE OF DINEVERNULL

ExtraData addContentView applyOverrideConfiguration attachBaseContext bindIsolatedService bindService bindService checkCallingOrSelfPermission checkCallingOrSelfUriPermission checkCallingPermission checkCallingUriPermission checkPermission checkSelfPermission checkUriPermission checkUriPermission clearWallpaper clone closeContextMenu closeOptionsMenu createConfigurationContext createContextForSplit createDeviceProtectedStorageContext createDisplayContext createPackageContext createPendingResult databaseList deleteDatabase deleteFile deleteSharedPreferences dismissDialog dismissKeyboardShortcutsHelper dispatchGenericMotionEvent dispatchKeyEvent dispatchKeyShortcutEvent dispatchPopulateAccessibilityEvent dispatchTouchEvent dispatchTrackballEvent dump enforceCallingOrSelfPermission enforceCallingOrSelfUriPermission enforceCallingPermission enforceCallingUriPermission enforcePermission enforceUriPermission enforceUriPermission enterPictureInPictureMode enterPictureInPictureMode equals fileList

finalize findViewById finish finishActivity finishActivityFromChild finishAffinity finishAfterTransition finishAndRemoveTask finishFromChild getColor getColorStateList getDatabasePath getDir getDrawable getExternalFilesDir getExternalFilesDirs getExtraData getFileStreamPath getPreferences getSharedPreferences getString getString getSystemService getSystemService getSystemServiceName getText grantUriPermission hashCode hasWindowFocus invalidateOptionsMenu managedQuery moveDatabaseFrom moveSharedPreferencesFrom moveTaskToBack navigateUpTo navigateUpToFromChild notify notifyAll obtainStyledAttributes obtainStyledAttributes obtainStyledAttributes obtainStyledAttributes onActionModeFinished onActionModeStarted onActivityReenter onActivityResult onApplyThemeResource onAttachedToWindow onAttachFragment onAttachFragment

onBackPressed onChildTitleChanged onConfigurationChanged onContentChanged onContextItemSelected onContextMenuClosed onCreate onCreate onCreateContextMenu onCreateDescription onCreateDialog onCreateDialog onCreateNavigateUpTaskStack onCreateOptionsMenu onCreatePanelMenu onCreatePanelView onCreateSupportNavigateUpTaskStack onCreateThumbnail onCreateView onCreateView onDestroy onDetachedFromWindow onEnterAnimationComplete onGenericMotionEvent onGetDirectActions onKeyDown onKeyLongPress onKeyMultiple onKeyShortcut onKeyUp onLocalVoiceInteractionStarted onLocalVoiceInteractionStopped onLowMemory onMenuItemSelected onMenuOpened onMultiWindowModeChanged onMultiWindowModeChanged onNavigateUp onNavigateUpFromChild onNewIntent onNightModeChanged onOptionsItemSelected onOptionsMenuClosed onPanelClosed onPause onPerformDirectAction onPictureInPictureModeChanged onPictureInPictureModeChanged onPointerCaptureChanged onPostCreate

onPostCreate onPostResume onPrepareDialog onPrepareDialog onPrepareNavigateUpTaskStack onPrepareOptionsMenu onPrepareOptionsPanel onPreparePanel onPrepareSupportNavigateUpTaskStack onProvideAssistContent onProvideAssistData onProvideKeyboardShortcuts onProvideReferrer onRequestPermissionsResult onRestart onRestoreInstanceState onRestoreInstanceState onResume onResumeFragments onRetainCustomNonConfigurationInstance onRetainNonConfigurationInstance onSaveInstanceState onSaveInstanceState onSearchRequested onSearchRequested onStart onStateNotSaved onStop onSupportActionModeFinished onSupportActionModeStarted onSupportContentChanged onSupportNavigateUp onTitleChanged onTopResumedActivityChanged onTouchEvent onTrackballEvent onTrimMemory onUserInteraction onUserLeaveHint onVisibleBehindCanceled onWindowAttributesChanged onWindowFocusChanged onWindowStartingActionMode onWindowStartingActionMode onWindowStartingSupportActionMode openContextMenu openFileInput openFileOutput openOptionsMenu openOrCreateDatabase

openOrCreateDatabase overridePendingTransition peekWallpaper postponeEnterTransition putExtraData recreate registerActivityLifecycleCallbacks registerComponentCallbacks registerForContextMenu registerReceiver registerReceiver registerReceiver registerReceiver releaseInstance removeDialog removeStickyBroadcast removeStickyBroadcastAsUser reportFullyDrawn requestDragAndDropPermissions requestPermissions requestShowKeyboardShortcuts requestVisibleBehind requestWindowFeature requireViewById revokeUriPermission revokeUriPermission runOnUiThread sendBroadcast sendBroadcast sendBroadcastAsUser sendBroadcastAsUser sendOrderedBroadcast sendOrderedBroadcast sendOrderedBroadcastAsUser sendStickyBroadcast sendStickyBroadcastAsUser sendStickyOrderedBroadcast sendStickyOrderedBroadcastAsUser setContentView setFeatureDrawable setFeatureDrawableAlpha setFeatureDrawableResource setFeatureDrawableUri setResult setVrModeEnabled shouldShowRequestPermissionRationale shouldUpRecreateTask showAssist showDialog showDialog

showLockTaskEscapeMessage startActionMode startActionMode startActivities startActivities startActivity startActivity startActivityForResult startActivityForResult startActivityFromChild startActivityFromChild startActivityFromFragment startActivityFromFragment startActivityFromFragment startActivityFromFragment startActivityIfNeeded startActivityIfNeeded startForegroundService startInstrumentation startIntentSender startIntentSender startIntentSenderForResult startIntentSenderForResult startIntentSenderFromChild startIntentSenderFromChild startIntentSenderFromFragment startLocalVoiceInteraction startLockTask startManagingCursor startNextMatchingActivity startNextMatchingActivity startPostponedEnterTransition startSearch startService startSupportActionMode stopLocalVoiceInteraction stopLockTask stopManagingCursor stopService superDispatchKeyEvent supportFinishAfterTransition supportInvalidateOptionsMenu supportNavigateUpTo supportPostponeEnterTransition supportRequestWindowFeature supportShouldUpRecreateTask supportStartPostponedEnterTransition takeKeyEvents toString triggerSearch

unbindService unregisterActivityLifecycleCallbacks unregisterComponentCallbacks unregisterForContextMenu unregisterReceiver updateServiceGroup validateRequestPermissionsRequestCode wait wait wait ACCESSIBILITY_SERVICE ACCOUNT_SERVICE ACTIVITY_SERVICE ALARM_SERVICE APP_OPS_SERVICE APPWIDGET_SERVICE AUDIO_SERVICE BATTERY_SERVICE BIND_ABOVE_CLIENT BIND_ADJUST_WITH_ACTIVITY BIND_ALLOW_OOM_MANAGEMENT BIND_AUTO_CREATE BIND_DEBUG_UNBIND BIND_EXTERNAL_SERVICE BIND_IMPORTANT BIND_INCLUDE_CAPABILITIES BIND_NOT_FOREGROUND BIND_NOT_PERCEPTIBLE BIND_WAIVE_PRIORITY BIOMETRIC_SERVICE BLUETOOTH_SERVICE CAMERA_SERVICE CAPTIONING_SERVICE CARRIER_CONFIG_SERVICE CLIPBOARD_SERVICE COMPANION_DEVICE_SERVICE CONNECTIVITY_SERVICE CONSUMER_IR_SERVICE CONTEXT_IGNORE_SECURITY CONTEXT_INCLUDE_CODE CONTEXT_RESTRICTED CROSS_PROFILE_APPS_SERVICE DEFAULT_KEYS_DIALER DEFAULT_KEYS_DISABLE DEFAULT_KEYS_SEARCH_GLOBAL DEFAULT_KEYS_SEARCH_LOCAL DEFAULT_KEYS_SHORTCUT DEVICE_POLICY_SERVICE DISPLAY_SERVICE DOWNLOAD_SERVICE

DROPBOX_SERVICE EUICC_SERVICE FINGERPRINT_SERVICE FOCUSED_STATE_SET HARDWARE_PROPERTIES_SERVICE INPUT_METHOD_SERVICE INPUT_SERVICE IPSEC_SERVICE JOB_SCHEDULER_SERVICE KEYGUARD_SERVICE LAUNCHER_APPS_SERVICE LAYOUT_INFLATER_SERVICE LOCATION_SERVICE MEDIA_PROJECTION_SERVICE MEDIA_ROUTER_SERVICE MEDIA_SESSION_SERVICE MIDI_SERVICE MODE_APPEND MODE_ENABLE_WRITE_AHEAD_LOGGING MODE_MULTI_PROCESS MODE_NO_LOCALIZED_COLLATORS MODE_PRIVATE MODE_WORLD_READABLE MODE_WORLD_WRITEABLE NETWORK_STATS_SERVICE NFC_SERVICE NOTIFICATION_SERVICE NSD_SERVICE POWER_SERVICE PRINT_SERVICE RECEIVER_VISIBLE_TO_INSTANT_APPS RESTRICTIONS_SERVICE RESULT_CANCELED RESULT_FIRST_USER RESULT_OK ROLE_SERVICE SEARCH_SERVICE SENSOR_SERVICE SHORTCUT_SERVICE STORAGE_SERVICE STORAGE_STATS_SERVICE SYSTEM_HEALTH_SERVICE TELECOM_SERVICE TELEPHONY_SERVICE TELEPHONY_SUBSCRIPTION_SERVICE TEXT_CLASSIFICATION_SERVICE TEXT_SERVICES_MANAGER_SERVICE TRIM_MEMORY_BACKGROUND TRIM_MEMORY_COMPLETE TRIM_MEMORY_MODERATE

TRIM_MEMORY_RUNNING_CRITICAL TRIM_MEMORY_RUNNING_LOW TRIM_MEMORY_RUNNING_MODERATE TRIM_MEMORY_UI_HIDDEN TV_INPUT_SERVICE UI_MODE_SERVICE USAGE_STATS_SERVICE USB_SERVICE USER_SERVICE VIBRATOR_SERVICE WALLPAPER_SERVICE WIFI_AWARE_SERVICE WIFI_P2P_SERVICE WIFI_RTT_RANGING_SERVICE WIFI_SERVICE WINDOW_SERVICE

Page 8: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

8

PERFORMANCE OF DINEVERNULL

ExtraData addContentView applyOverrideConfiguration attachBaseContext bindIsolatedService bindService bindService checkCallingOrSelfPermission checkCallingOrSelfUriPermission checkCallingPermission checkCallingUriPermission checkPermission checkSelfPermission checkUriPermission checkUriPermission clearWallpaper clone closeContextMenu closeOptionsMenu createConfigurationContext createContextForSplit createDeviceProtectedStorageContext createDisplayContext createPackageContext createPendingResult databaseList deleteDatabase deleteFile deleteSharedPreferences dismissDialog dismissKeyboardShortcutsHelper dispatchGenericMotionEvent dispatchKeyEvent dispatchKeyShortcutEvent dispatchPopulateAccessibilityEvent dispatchTouchEvent dispatchTrackballEvent dump enforceCallingOrSelfPermission enforceCallingOrSelfUriPermission enforceCallingPermission enforceCallingUriPermission enforcePermission enforceUriPermission enforceUriPermission enterPictureInPictureMode enterPictureInPictureMode equals fileList

finalize findViewById finish finishActivity finishActivityFromChild finishAffinity finishAfterTransition finishAndRemoveTask finishFromChild getColor getColorStateList getDatabasePath getDir getDrawable getExternalFilesDir getExternalFilesDirs getExtraData getFileStreamPath getPreferences getSharedPreferences getString getString getSystemService getSystemService getSystemServiceName getText grantUriPermission hashCode hasWindowFocus invalidateOptionsMenu managedQuery moveDatabaseFrom moveSharedPreferencesFrom moveTaskToBack navigateUpTo navigateUpToFromChild notify notifyAll obtainStyledAttributes obtainStyledAttributes obtainStyledAttributes obtainStyledAttributes onActionModeFinished onActionModeStarted onActivityReenter onActivityResult onApplyThemeResource onAttachedToWindow onAttachFragment onAttachFragment

onBackPressed onChildTitleChanged onConfigurationChanged onContentChanged onContextItemSelected onContextMenuClosed onCreate onCreate onCreateContextMenu onCreateDescription onCreateDialog onCreateDialog onCreateNavigateUpTaskStack onCreateOptionsMenu onCreatePanelMenu onCreatePanelView onCreateSupportNavigateUpTaskStack onCreateThumbnail onCreateView onCreateView onDestroy onDetachedFromWindow onEnterAnimationComplete onGenericMotionEvent onGetDirectActions onKeyDown onKeyLongPress onKeyMultiple onKeyShortcut onKeyUp onLocalVoiceInteractionStarted onLocalVoiceInteractionStopped onLowMemory onMenuItemSelected onMenuOpened onMultiWindowModeChanged onMultiWindowModeChanged onNavigateUp onNavigateUpFromChild onNewIntent onNightModeChanged onOptionsItemSelected onOptionsMenuClosed onPanelClosed onPause onPerformDirectAction onPictureInPictureModeChanged onPictureInPictureModeChanged onPointerCaptureChanged onPostCreate

onPostCreate onPostResume onPrepareDialog onPrepareDialog onPrepareNavigateUpTaskStack onPrepareOptionsMenu onPrepareOptionsPanel onPreparePanel onPrepareSupportNavigateUpTaskStack onProvideAssistContent onProvideAssistData onProvideKeyboardShortcuts onProvideReferrer onRequestPermissionsResult onRestart onRestoreInstanceState onRestoreInstanceState onResume onResumeFragments onRetainCustomNonConfigurationInstance onRetainNonConfigurationInstance onSaveInstanceState onSaveInstanceState onSearchRequested onSearchRequested onStart onStateNotSaved onStop onSupportActionModeFinished onSupportActionModeStarted onSupportContentChanged onSupportNavigateUp onTitleChanged onTopResumedActivityChanged onTouchEvent onTrackballEvent onTrimMemory onUserInteraction onUserLeaveHint onVisibleBehindCanceled onWindowAttributesChanged onWindowFocusChanged onWindowStartingActionMode onWindowStartingActionMode onWindowStartingSupportActionMode openContextMenu openFileInput openFileOutput openOptionsMenu openOrCreateDatabase

openOrCreateDatabase overridePendingTransition peekWallpaper postponeEnterTransition putExtraData recreate registerActivityLifecycleCallbacks registerComponentCallbacks registerForContextMenu registerReceiver registerReceiver registerReceiver registerReceiver releaseInstance removeDialog removeStickyBroadcast removeStickyBroadcastAsUser reportFullyDrawn requestDragAndDropPermissions requestPermissions requestShowKeyboardShortcuts requestVisibleBehind requestWindowFeature requireViewById revokeUriPermission revokeUriPermission runOnUiThread sendBroadcast sendBroadcast sendBroadcastAsUser sendBroadcastAsUser sendOrderedBroadcast sendOrderedBroadcast sendOrderedBroadcastAsUser sendStickyBroadcast sendStickyBroadcastAsUser sendStickyOrderedBroadcast sendStickyOrderedBroadcastAsUser setContentView setFeatureDrawable setFeatureDrawableAlpha setFeatureDrawableResource setFeatureDrawableUri setResult setVrModeEnabled shouldShowRequestPermissionRationale shouldUpRecreateTask showAssist showDialog showDialog

showLockTaskEscapeMessage startActionMode startActionMode startActivities startActivities startActivity startActivity startActivityForResult startActivityForResult startActivityFromChild startActivityFromChild startActivityFromFragment startActivityFromFragment startActivityFromFragment startActivityFromFragment startActivityIfNeeded startActivityIfNeeded startForegroundService startInstrumentation startIntentSender startIntentSender startIntentSenderForResult startIntentSenderForResult startIntentSenderFromChild startIntentSenderFromChild startIntentSenderFromFragment startLocalVoiceInteraction startLockTask startManagingCursor startNextMatchingActivity startNextMatchingActivity startPostponedEnterTransition startSearch startService startSupportActionMode stopLocalVoiceInteraction stopLockTask stopManagingCursor stopService superDispatchKeyEvent supportFinishAfterTransition supportInvalidateOptionsMenu supportNavigateUpTo supportPostponeEnterTransition supportRequestWindowFeature supportShouldUpRecreateTask supportStartPostponedEnterTransition takeKeyEvents toString triggerSearch

unbindService unregisterActivityLifecycleCallbacks unregisterComponentCallbacks unregisterForContextMenu unregisterReceiver updateServiceGroup validateRequestPermissionsRequestCode wait wait wait ACCESSIBILITY_SERVICE ACCOUNT_SERVICE ACTIVITY_SERVICE ALARM_SERVICE APP_OPS_SERVICE APPWIDGET_SERVICE AUDIO_SERVICE BATTERY_SERVICE BIND_ABOVE_CLIENT BIND_ADJUST_WITH_ACTIVITY BIND_ALLOW_OOM_MANAGEMENT BIND_AUTO_CREATE BIND_DEBUG_UNBIND BIND_EXTERNAL_SERVICE BIND_IMPORTANT BIND_INCLUDE_CAPABILITIES BIND_NOT_FOREGROUND BIND_NOT_PERCEPTIBLE BIND_WAIVE_PRIORITY BIOMETRIC_SERVICE BLUETOOTH_SERVICE CAMERA_SERVICE CAPTIONING_SERVICE CARRIER_CONFIG_SERVICE CLIPBOARD_SERVICE COMPANION_DEVICE_SERVICE CONNECTIVITY_SERVICE CONSUMER_IR_SERVICE CONTEXT_IGNORE_SECURITY CONTEXT_INCLUDE_CODE CONTEXT_RESTRICTED CROSS_PROFILE_APPS_SERVICE DEFAULT_KEYS_DIALER DEFAULT_KEYS_DISABLE DEFAULT_KEYS_SEARCH_GLOBAL DEFAULT_KEYS_SEARCH_LOCAL DEFAULT_KEYS_SHORTCUT DEVICE_POLICY_SERVICE DISPLAY_SERVICE DOWNLOAD_SERVICE

DROPBOX_SERVICE EUICC_SERVICE FINGERPRINT_SERVICE FOCUSED_STATE_SET HARDWARE_PROPERTIES_SERVICE INPUT_METHOD_SERVICE INPUT_SERVICE IPSEC_SERVICE JOB_SCHEDULER_SERVICE KEYGUARD_SERVICE LAUNCHER_APPS_SERVICE LAYOUT_INFLATER_SERVICE LOCATION_SERVICE MEDIA_PROJECTION_SERVICE MEDIA_ROUTER_SERVICE MEDIA_SESSION_SERVICE MIDI_SERVICE MODE_APPEND MODE_ENABLE_WRITE_AHEAD_LOGGING MODE_MULTI_PROCESS MODE_NO_LOCALIZED_COLLATORS MODE_PRIVATE MODE_WORLD_READABLE MODE_WORLD_WRITEABLE NETWORK_STATS_SERVICE NFC_SERVICE NOTIFICATION_SERVICE NSD_SERVICE POWER_SERVICE PRINT_SERVICE RECEIVER_VISIBLE_TO_INSTANT_APPS RESTRICTIONS_SERVICE RESULT_CANCELED RESULT_FIRST_USER RESULT_OK ROLE_SERVICE SEARCH_SERVICE SENSOR_SERVICE SHORTCUT_SERVICE STORAGE_SERVICE STORAGE_STATS_SERVICE SYSTEM_HEALTH_SERVICE TELECOM_SERVICE TELEPHONY_SERVICE TELEPHONY_SUBSCRIPTION_SERVICE TEXT_CLASSIFICATION_SERVICE TEXT_SERVICES_MANAGER_SERVICE TRIM_MEMORY_BACKGROUND TRIM_MEMORY_COMPLETE TRIM_MEMORY_MODERATE

TRIM_MEMORY_RUNNING_CRITICAL TRIM_MEMORY_RUNNING_LOW TRIM_MEMORY_RUNNING_MODERATE TRIM_MEMORY_UI_HIDDEN TV_INPUT_SERVICE UI_MODE_SERVICE USAGE_STATS_SERVICE USB_SERVICE USER_SERVICE VIBRATOR_SERVICE WALLPAPER_SERVICE WIFI_AWARE_SERVICE WIFI_P2P_SERVICE WIFI_RTT_RANGING_SERVICE WIFI_SERVICE WINDOW_SERVICE

Avoid reflection-based DI!

Page 9: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

9

DEPENDENCY INJECTION ON ANDROIDNEVERNULL

History of DI systems for mobile

• RoboGuice (2011 - 2016)

• RoboSpring (2012 - 2015)

• Dagger 1.0 (2012 - 2016)

• Dagger 2.0 (2012 - today)

• Micronaut (2018 - today)

Page 10: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

10

DI WITH ANNOTATION PROCESSORSNEVERNULL

• Dagger

*.java + Annotations *.java

Generated *.java

*.class

Analyze & Generate

Compile

*.java + Annotations

Generated *.class

*.class

Analyze & Generate

Compile

• Micronaut

Page 11: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

11

DAGGERNEVERNULL

• Google Project

• Complicated

• Components are obligatory.

• Modules are obligatory.

• Initialization is difficult.

• Documentation is incomplete.

• Hilt -> „standard Android way to Dagger“

Pro: It's fast.

Con: Developer experience is low.

Page 12: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

12

MICRONAUTNEVERNULL

• Open Source project by OCI (2018)

• Works like Spring Boot.

• Just use Annotations like @Singleton.

• Use Configuration with Beans.

• Optionally use AOP.

Pro: It's fast.

Pro: Developer experience is high.

Con: But….

Page 13: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

13

MICRONAUT & JAVA 8 NEVERNULL

• Lambdas & default interfaces supported

• Full Java 8 API support only on Android 7+

• Lower Version make up >25% market share.

• However: Java 8+ API desugaring support

(Android Gradle Plugin 4.0.0+, May 2020)

• Lambdas & default interfaces supported

• Minor quirk with default interfaces + abstract

classes

• Only Java 7 APIs available (Android 4.4)

• Java 8+ API desugaring support not applicable

iOS / RoboVM 2.3

Android

Android Dashboard as of September 2020

Page 14: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

14

BRINGING MICRONAUT TO MOBILENEVERNULL

Retro Streaming

•Add streamsupport library (GPL + CE)

•replace all occurrences of Java 8 calls (automation welcome)

e.g. via gradle:

list.stream() -> java8.util.stream.StreamSupport.stream(list)

set.foreach() -> java8.lang.Iterables.forEach(set)

Arrays.stream(array) -> J8Arrays.stream(array)

...

dependencies { api “net.sourceforge.streamsupport:streamsupport:1.7.1“}

content.replaceAll(‚Arrays\\.stream\\(', "J8Arrays.stream(")

Page 15: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

15

BRINGING MICRONAUT TO MOBILENEVERNULL

Micronaut as part of MobileUI App Framework

•MobileUI Inject = Micronaut for Android 5 & RoboVM

• solves all compatiblity issues

• adds additional platform support for Android & iOS

• automatically initialized with MobileUI

•Micronaut-based plugin system for iOS & Android

•Cross platform native UI system

Learn more on https://www.mobileui.dev/

Page 16: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

16

USING MICRONAUT ON MOBILENEVERNULL

import javax.inject.Singleton;

@Singletonpublic class GreetingService { public String getGreeting() { return "Rock on!"; }}

import javax.inject.Inject;

public class MainController {

@Inject GreetingService greetingService;

public MainController() { MobileUI.inject(this); }

public String getGreeting() { return greetingService.getGreeting(); }

}

Defining & injecting a bean into an unmanaged object

Page 17: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

17

USING MICRONAUT ON MOBILENEVERNULL

import javax.inject.Singleton;

@Singletonpublic class GreetingService { public String getGreeting() { return "Rock on!"; }}

import javax.inject.Inject;import io.micronaut.context.annotation.Prototype;

@Prototypepublic class MainController {

@Inject GreetingService greetingService;

public String getGreeting() { return greetingService.getGreeting(); }

}

Defining & injecting a bean into an managed object

Page 18: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

18

USING MICRONAUT ON MOBILENEVERNULL

import javax.inject.Singleton;

@Singletonpublic class GreetingService { public String getGreeting() { return "Rock on!"; }}

import javax.inject.Inject;import io.micronaut.context.annotation.Prototype;

@Prototypepublic class MainController {

private GreetingService greetingService;

public MainController(GreetingService greetingService){ this.greetingService = greetingService; }

public String getGreeting() { return greetingService.getGreeting(); }

}

Defining & injecting a bean into an managed object using constructor injection

Page 19: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

19

USING MICRONAUT ON MOBILENEVERNULL

Encapsulating platform specifica

Vibrator

VibratorIosImpl VibratorAndroidImpl

iOS

Page 20: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

20

USING MICRONAUT ON MOBILENEVERNULL

public interface Vibrator { void vibrate();}

import org.robovm.apple.audiotoolbox.AudioServices;import javax.inject.Singleton;

@Singletonpublic class VibratorIosImpl implements Vibrator { @Override public void vibrate() { AudioServices.playAlertSound(AudioServices.SystemSoundVibrate); }}

@Singletonpublic class VibratorAndroidImpl implements Vibrator {

@Inject private Context context;

@Override public void vibrate() { android.os.Vibrator v =

(android.os.Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); // Vibrate for 500 milliseconds if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE)); } else { //deprecated in API 26 v.vibrate(500); } }}iOS

Page 21: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

21

USING MICRONAUT ON MOBILENEVERNULL

Encapsulating platform specifica

import io.micronaut.context.annotation.Prototype;import javax.inject.Inject;

@Prototypepublic class MainController {

@Inject public Vibrator vibrator;}

Page 22: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

22

USING MICRONAUT ON MOBILENEVERNULL

A Micronaut-based cross-platform plugin system

allprojects { ext { //versions are examples mobileuiVersion = "0.5.1" roboVMVersion = "2.3.9"

mobileuiPlugins = [ "io.nevernull:mobileui-inject", "io.nevernull:mobileui-plugin-vibrator", ] }}

import io.micronaut.context.annotation.Prototype;import javax.inject.Inject;

@Prototypepublic class MainController {

@Inject public Vibrator vibrator;}

Page 23: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

23

USING MICRONAUT ON MOBILENEVERNULL

A Micronaut-based cross-platform plugin system

allprojects { ext { //versions are examples mobileuiVersion = "0.5.1" roboVMVersion = "2.3.9"

mobileuiPlugins = [ "io.nevernull:mobileui-inject", "io.nevernull:mobileui-plugin-vibrator", ] }}

io.nevernull:mobileui-plugin-vibrator

io.nevernull:mobileui-plugin-vibrator-android

io.nevernull:mobileui-plugin-vibrator-ios

Page 24: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

24

USING MICRONAUT ON MOBILENEVERNULL

A Micronaut-based cross-platform plugin system

allprojects { ext { //versions are examples mobileuiVersion = "0.5.1" roboVMVersion = "2.3.9"

mobileuiPlugins = [ "io.nevernull:mobileui-inject", "io.nevernull:mobileui-plugin-vibrator", ] }}

io.nevernull:mobileui-plugin-vibrator:0.5.1

io.nevernull:mobileui-plugin-vibrator-android:0.5.1

io.nevernull:mobileui-plugin-vibrator-ios:0.5.1

api platform("io.nevernull:mobileui-platform:$mobileuiVersion")

Page 25: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

25

USING ORM ON MOBILENEVERNULL

OrmLite as Micronaut-based plugin allprojects { ext { //versions are examples mobileuiVersion = "0.5.1" roboVMVersion = "2.3.9"

mobileuiPlugins = [ "io.nevernull:mobileui-inject", "io.nevernull:mobileui-plugin-ormlite", ] }}

import io.micronaut.context.annotation.Factory;import io.nevernull.mobileui.ormlite.OrmLiteConfiguration;import javax.inject.Singleton;

@Factorypublic class Config {

@Singleton public OrmLiteConfiguration ormLiteConfiguration() { return OrmLiteConfiguration .entities(Person.class, Team.class, Project.class) .name("project.db") .version(1) .autoCreateTables(true) .onCreate(s -> { System.out.println("Created"); }) .onUpgrade((connection, oldVersion, newVersion) -> { System.out.println(oldVersion); System.out.println(newVersion); }); }}

Page 26: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

26

USING ORM ON MOBILENEVERNULL

OrmLite in the Java Forum App (excerpt)

@Prototypepublic class ProgramController implements LifeCycleAware {

@Inject DaoFactory daoFactory;

List<Talk> talkList;

@Override public void onStart(Object o) { try { talkList = daoFactory.getDao(Talk.class).queryBuilder().orderBy(„timeSlot", true) .orderBy("id", true).query(); } catch (SQLException e) { logger.error("Error when loading talks: ", e); talkList = new ArrayList<>(); } }

…}

Page 27: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

27

USING ORM ON MOBILENEVERNULL

OrmLite in the Java Forum App (excerpt) @DatabaseTablepublic class Talk {

@DatabaseField(id = true) public String id; @DatabaseField public String title; @DatabaseField public String abstr; @DatabaseField public String room; @DatabaseField public String topic; @DatabaseField public String timeSlot; @DatabaseField public String type; @DatabaseField public String keyWords; @DatabaseField public String audience; @DatabaseField public String slidesUrl; @DatabaseField public int favorite = 0;

@ForeignCollectionField public Collection<SpeakerTalk> speakers;…

}

Page 28: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

28

USING ORM ON MOBILE & BACKENDNEVERNULL

OrmLite in the Java Forum Backend

void parseFile(File file) { ConnectionSource connectionSource = null; try { JfsHtmlParser parser = new JfsHtmlParser(); List<Talk> talks = parser.parse(file);

connectionSource = new JdbcConnectionSource("jdbc:sqlite:javaforum.db");

TableUtils.createTableIfNotExists(connectionSource, Speaker.class); TableUtils.createTableIfNotExists(connectionSource, Talk.class); TableUtils.createTableIfNotExists(connectionSource, SpeakerTalk.class);

Dao<Talk, String> talkDao = DaoManager.createDao(connectionSource, Talk.class); Dao<Speaker, String> speakerDao = DaoManager.createDao(connectionSource, Speaker.class); Dao<SpeakerTalk, String> speakerTalkDao = DaoManager.createDao(connectionSource, SpeakerTalk.class); for (Talk talk : talks) { talkDao.create(talk); for (SpeakerTalk speakerTalk : talk.speakers) { speakerDao.createIfNotExists(speakerTalk.speaker); speakerTalkDao.createIfNotExists(speakerTalk); } } connectionSource.close(); } catch (Exception e) {

... }}

Java Forum Sqlite DB

Page 29: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

29

SQLITE-BASED SYNCNEVERNULL

Syncing Apps and Backend via SQLite & HTTP

javaforum.db

HTTP GET

Web Server

HTTP 200

Close DB

Replace DB File

Re-Open DB

Reload UI

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Page 30: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

30

SQLITE-BASED SYNCNEVERNULL

Syncing Apps and Backend via SQLite & HTTP

javaforum.db

HTTP GET

Web Server

HTTP 200

Close DB

Replace DB File

Re-Open DB

Reload UI

favStrategy.onBeforeMigration()

favStrategy.onAfterMigration()

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Page 31: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

31

SQLITE-BASED SYNCNEVERNULL

Syncing Apps and Backend via SQLite & HTTP

javaforum.db

HTTP GET If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Web Server

HTTP 304 (Not Modified)

Page 32: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

32

SQLITE-BASED SYNC WITH OKHTTPNEVERNULL

Syncing Apps and Backend via SQLite & HTTP

this.client = new OkHttpClient.Builder() .cache(new Cache(cacheDirectory, 4 * 1024 * 1024)) .build();

Request request = new Request.Builder().cacheControl(new CacheControl.Builder() .maxAge(0, TimeUnit.SECONDS) .build()) .url(url) .build();try (Response response = client.newCall(request).execute()) { if (response.networkResponse() != null && response.networkResponse().code() == HttpURLConnection.HTTP_OK) {

// do migrate!}

} catch (Exception e) { logger.warn("Request not successful: ", e);}

Page 33: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

33

SAFELY SYNCING WITH RXJAVANEVERNULL

Using RxJava to safely manage resources on mobile

public Disposable startSync(Runnable updateListener);

private Disposable updateDisposable;

public void checkForUpdates() { if (System.currentTimeMillis() > (lastUpdate + UPDATETIME)) { lastUpdate = System.currentTimeMillis(); logger.debug("DataUpdate: Starting data update request."); updateDisposable = client.startSync(() -> { loadTalks(); MobileUI.firePropertyChanged(this, "talkList"); }); }}

@Overridepublic void onDestroy(Object o) { if (updateDisposable != null) { updateDisposable.dispose(); }}

Page 34: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

34

CROSS PLATFORM UI WITH MOBILEUINEVERNULL

Displaying the data on iOS and Android

<?xml version="1.0" encoding="UTF-8"?><Layout xmlns="urn:nevernull:mobileui:layout"> <!-- @include{'app.mv'} --> <style>@include{'app.css'}</style> <LinearLayout height="fill_parent" orientation="vertical" padding="@{margin}dp" width="fill_parent"> <ImageView height="160dp" marginTop="16dp" href="#{'https://www.nevernull.io/download/mobileui-logo-for-template/'}" width="fill_parent" /> <TextView fontFamily="monospace" fontSize="18" marginTop="12dp" text="#{greeting}" textHorizontalAlign="center" width="fill_parent" /> <Button backgroundColor="#6111B1" horizontalAlign="center" marginTop="56dp" onClick="#{onOpenUrlClicked()}" paddingLeft="12dp" paddingRight="12dp" text="Yeah, take me to the candy shop" textColor="white" /> </LinearLayout></Layout>

Page 35: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

35

CROSS PLATFORM UI WITH MOBILEUINEVERNULL

Displaying the Talk list with MobileUI ListView

<ListView width="fill_parent" height="fill_parent" items="#{talkList}" onItemClicked="#{onTalkSelected(item)}"> <Template>

<!— only and example —> <TextView text=“#{item.title}“ width="fill_parent" height="48dp" textHorizontalAlign="center" textVerticalAlign="center" fontSize="16" /> </Template></ListView>

@Prototypepublic class ProgramController extends AbstractProgramListController {

public List<Talk> talkList;

...

public void onTalkSelected(Talk talk) { openTalkController(talk);}

}

Page 36: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

www.nevernull.io © 2020 NEVERNULL® GmbH. All Rights Reserved.

36

CHALLENGES & SOLUTIONSNEVERNULL

Using a single Java codebase for backends and mobile frontends:

•Stick with Java 8 (or consider Kotlin) and, for now, use Android 5/6

compatible libraries (they work on RoboVM as well).

•Use Micronaut as a fast and developer-friendly DI system.

•Consider SQLite as database system (maybe for sync as well).

•Combine it with ORMLite, if you want to go ORM on all platforms.

•For HTTP and REST consider OkHTTP and Retrofit

•Use RxJava for reactive programming (great compatibility).

•Use Gradle as build system (as of Android tooling).

•Consider MobileUI for high quality mobile user interfaces and

easy-to-use DI and plugins.

Page 37: With Micronaut on iOS & Android...WITH MICRONAUT ON IOS & ANDROID NEVERNULL • Overview & Deep Dive: Dependency Injection systems for mobile Java • How Java Forum app applies DI

CODE SMARTER - NOT HARDER.

EMAIL

PHONE

+49 7034 9422225

+49 179 7389529

ADDRESS

NEVERNULL GmbH

Löwengasse 4

71134 Aidlingen

[email protected]

WEB

https://mobileui.dev

https://nevernull.io