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

DroidCon NYC 2015 Boris Farber: 10 Ways to Improve You App's Performance

1fa9cb8c7997c8c4d3d251fb5e41f749?s=47 Realm
August 28, 2015
30k

DroidCon NYC 2015 Boris Farber: 10 Ways to Improve You App's Performance

1fa9cb8c7997c8c4d3d251fb5e41f749?s=128

Realm

August 28, 2015
Tweet

Transcript

  1. 10 ways to improve your app's performance Boris Farber Developer

    Advocate Google www.api-solutions.com
  2. IF YOU HAVE A SMALL APP FORGET THESE SLIDES

  3. Plan • Rules of thumb while working with data intensive

    apps ◦ Long launch time ◦ Janky scrolling ◦ Unresponsive app
  4. Activity Leaks

  5. Why memory leaks are dangerous • Holding references to unused

    Activity • Activity holds its layout ==> hold all views
  6. Static References • Activities/fragments etc - they have a life

    cycle • Activity will not be GC-ed • Static references ◦ become dangling "pointers" ◦ m_staticActivity = staticFragment.getActivity()
  7. Listeners leak public class LeakActivity extends Activity { // ...

    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); NastyManager.getInstance().addListener(this); // ...
  8. Listener's leak + fix @Override public void onDestroy() { super.onDestroy();

    NastyManager.getInstance().removeListener(this); } remove listener
  9. Outer class (Activity) Inner class (Handler)

  10. This is a leak public class MainActivity extends Activity {

    // ... Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... handler = new Handler() { @Override public void handleMessage(Message msg) { } }; // ...
  11. What happens if ... handler.postDelayed(...)

  12. This is a leak + fix private static class MyHandler

    extends Handler { private final WeakReference<MainActivity> mActivity; // ... public MyHandler(MainActivity activity) { mActivity = new WeakReference<MainActivity>(activity); // ... } @Override public void handleMessage(Message msg) { } // ... }
  13. Outer class (Activity) Inner class (Handler)

  14. Prefer static to non static inner classes • Non static

    Handler --> Activity leak • Both classes have a different lifetime
  15. What you can do Activity Leaks - 1 • Remove

    away static references • Use event bus • Unregister listeners • Prefer static inner classes to non static ones
  16. What you can do Activity Leaks - 2 • Do

    code reviews • Understand your app structure • Use tools (MAT ...) • Print logs on callbacks
  17. Scrolling

  18. Use UI thread only for UI

  19. Not on UI thread • Images (caching, loading) • Networking

    • JSON • Database access
  20. Not on UI thread • Images (caching, loading) • Networking

    • JSON • Database access Use Loaders Use libraries
  21. Images • Glide • Picasso • Fresco • ... Different

    design tradeoffs, especially around large image count
  22. Memory • Bitmaps are tricky ◦ Large size ◦ Fragmented

    heap ◦ ... • LRUCache - part of the support library
  23. Networking • Tricky APIs • Many java.net API calls are

    blocking ◦ Streams ◦ Equals of URL class result in DNS call
  24. Networking/Async Http • OkHttp - part of Android (from 4.4)

    • Volley • Retrofit - rest calls
  25. Large JSON • Parsing has a performance effect • Converted

    to class with getters and setters
  26. JSON • Small JSONs - GSON is the best •

    Large JSONs - Jackson, ig-json-parser
  27. UI thread Looper.myLooper() == Looper.getMainLooper()

  28. What you can do Scrolling • Keep UI thread only

    for UI • Understand concurrency APIs (next bullet) • Use libraries (memory, caching, json ...) • Use loaders
  29. Concurrency APIs

  30. Service • Service methods run on UI thread ! •

    Consider ◦ IntentService ◦ AsyncTask ◦ Executors ◦ HandlerThreads, Handlers and Loopers - Appendix
  31. IntentService • Single threaded • Simple/One job in a time

    • No job system (keep track for jobs) • No way to stop it
  32. AsyncTask • Don't care about result outside of UI •

    Activity lifecycles - can cause a memory leak (rotation) • Changes rapidly (grab latest and add to your project)
  33. Executor Framework • Thread pool • Callbacks • Futures •

    MapReduce tasks
  34. What you can do Concurrency API • Understand the APIs

    and tradeoffs • Refactor
  35. System Abuse & Deprecation

  36. System Abuse • Don't call private APIs by reflection •

    Don't call private native methods (NDK/C level) • Don't use Runtime.exec • "adb shell am" to communicate with other process is not something we want to support
  37. Deprecation • API will be removed • Your app will

    not work • No way to update APIs and tools
  38. Deprecation • There is a compelling reason to move ◦

    Security ◦ Correctness ◦ Performance
  39. What you can do around deprecation • Know and use

    APIs • Refactor your dependencies
  40. Newer is better • Prefer Toolbar to ActionBar • Prefer

    RecyclerView (especially for animations)
  41. Don't use Apache Http Connection • Removed at M (still

    available as dependency) • Use HttpURLConnection ◦ Simple API ◦ Small size ◦ Transparent compression ◦ Response caching
  42. What you can do Deprecation • Don't abuse the system

    • Update your dependencies and tools
  43. Architecture

  44. Understand app components life cycle • Activities • Fragments •

    Tasks • Flags • Add logs on callbacks
  45. Work with framework not against ... • Framework components have

    a purpose ◦ Specific semantics ◦ Used when those semantics are desired • Don't over engineer • Keep simple
  46. Pick 3rd party lib checklist • Solves your problem •

    Plays nicely with your current dependencies • Dex method count • Dependencies • Maintenance • Runtime permissions
  47. Design your app for • Sleeping most of the time

    • Responsive when "awaken"
  48. What you can do Architecture • Consistent • Get people

    on board quickly • Have someone experienced • Pick your dependencies wisely
  49. Thank You ! www.api-solutions.com @BorisFarber +BorisFarber

  50. Appendix Loopers/Handlers

  51. HandlerThread • A thread with a message box • Saves

    a lot of boilerplate code • Uses Looper
  52. Loopers and Handlers • Looper ◦ Synchronized message queue to

    process messages from handlers ◦ Takes the next task, executes it, then takes the next one and so on ◦ One looper per thread • Handler ◦ Set of methods to post messages
  53. Inside Looper (Android src) private Looper(boolean quitAllowed) { // ...

    mThread = Thread.currentThread(); } /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { final Looper me = myLooper(); // ... for (; ; ) { // ... } infinite loop