Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code sharing at Transit by Samuel Dionne

Code sharing at Transit by Samuel Dionne

How does Transit go about doing an application available for both Android and iOS. Why we decided to go with native and what hurdles did we ran into while doing it. Should everybody be following our route and if not how to identify that we’re ready for code sharing. We’ll look at different approaches available today to code sharing and how they differ from one another.

GDG Montreal

March 28, 2018
Tweet

More Decks by GDG Montreal

Other Decks in Technology

Transcript

  1. ➔ All iOS native UI ➔ All iOS native business

    logic ➔ Online API using JSON serving raw data ➔ Offline data implemented with CoreData
  2. ➔ All Android (java) UI ➔ All Android (java) business

    logic ➔ Online API using JSON serving raw data ➔ No Offline capability
  3. ➔ Different issues on both platforms ➔ Same issues on

    both platforms ➔ Not able to port CoreData files to Android ➔ Hard to keep up with new features / cities launch
  4. ➔ Slow app launch ➔ Not a good experience ➔

    Janky animations ➔ Fragmentation ➔ Custom views interaction
  5. ➔ Hard to do threading correctly ➔ StackTrace that doesn’t

    make sense ➔ No good framework available
  6. ➔ It works for games ➔ No need of framework

    ➔ Super easy integration on iOS ➔ Re-use same code on the server ➔ Use battle tested libraries ➔ Custom binary file format
  7. ➔ You have to do everything in C++ ➔ You

    have to manage pointers ➔ It’s hard to setup ➔ You can’t debug C++ code on Android
  8. ➔ Crossing Java / C++ boundary too often ➔ Caching

    classes and method references ➔ Proguard obfuscating your references ➔ Gradle is rebuilding often
  9. Foo foo = new Foo(); foo.setBar(10); foo.setBaz(“yup”); 1. Foo class

    reference 2. Foo contructor reference 3. Call Foo constructor 4. setBar method reference 5. Call setBar 6. setBaz method reference 7. Create string 8. Call setBaz reference Foo foo = new Foo(10, “yup”); 1. Foo class reference* 2. Foo constructor reference* 3. Create String 4. Call Foo constructor
  10. Foo foo = new Foo(10, “yup”); 1. Foo class reference*

    2. Foo constructor reference* 3. Create String 4. Call Foo constructor
  11. Before proguard Foo foo = new Foo(); foo.setBar(10); foo.setBaz(“yup”); After

    proguard A a = new A(); a.AA(10); a.AB(“yup”); env->FindClass("mobi/dinoz/Foo") env->GetMethodID(clazz, "setBar", "(I)V");
  12. ➔ Touching gradle file ➔ Touching CMakeList.txt ➔ Touching a

    .cpp or .h file ➔ Changing branch External tool like CCache helps a lot
  13. ➔ SmartPointers don’t know about Java ➔ Java object have

    their own lifecycle ➔ Link them together
  14. ➔ SmartPointers don’t know about Java ➔ Java object have

    their own lifecycle ➔ Link them together c++ shared_ptr<CppFoo>* pNew = new shared_ptr<CppFoo>; *pNew = item; jlong cppRef = reinterpret_cast<jlong>(pNew);
  15. java public class Foo { private long cppRef; public Foo(long

    cppRef) { this.cppRef = cppRef; } @Override protected void finalize() { // Call C++ to release the pointer } } ➔ SmartPointers don’t know about Java ➔ Java object have their own lifecycle ➔ Link them together c++ shared_ptr<CppFoo>* pNew = new shared_ptr<CppFoo>; *pNew = item; jlong cppRef = reinterpret_cast<jlong>(pNew);
  16. ➔ Lot of business logic on device ➔ Performance requirements

    ➔ Need direct access to: ◆ Audio ◆ Camera ◆ Memory
  17. ➔ Languages ◆ Kotlin ◆ Swift ◆ C++ ◆ JavaScript

    ➔ Frameworks ◆ React Native ◆ Xamarin ➔ Flutter