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

10 ways to improve your Android app performance

Boris Farber
October 28, 2015
110

10 ways to improve your Android app performance

Boris Farber

October 28, 2015
Tweet

Transcript

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

    Activity • Activity holds its layout ==> holds all views
  2. Listeners leak public class LeakActivity extends Activity { // ...

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

    NastyManager.getInstance().removeListener(this); } remove listener
  4. 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()
  5. 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) { } }; // ...
  6. 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) { } // ... }
  7. Prefer static to non static inner classes • Non static

    Handler --> Activity leak • Both classes have a different lifetime
  8. What you can do Activity Leaks • Remove away static

    references • Use event bus • Unregister listeners • Prefer static inner classes to non static ones
  9. What you can do Activity Leaks • Do code reviews

    • Understand your app structure • Use tools (MAT ...) • Print logs on callbacks
  10. Not on UI thread • Images (caching, loading) • Networking

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

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

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

    blocking ◦ Streams ◦ Equals of URL class result in DNS call
  14. JSON • Small JSONs - GSON is the best •

    Large JSONs - Jackson, ig-json-parser
  15. What you can do Scrolling • Keep UI thread only

    for UI • Understand concurrency APIs (next bullet) • Use libraries (memory, caching, json ...) • Use loaders
  16. Service • Service methods run on UI thread ! •

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

    • No job system (keep track for jobs) • No way to stop it
  18. 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)
  19. 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
  20. Deprecation • API will be removed • Your app will

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

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

    APIs • Refactor your dependencies
  23. Don't use Apache Http Connection • Removed at M (still

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

    • Update your dependencies and tools
  25. Bring your own gloves • Various versions, devices, OEMs •

    APIs and libraries shipped with platform might behave differently • Async task ...
  26. Bring your own gloves • Consider bundling your own version

    • Check dex limit • Check code bloat
  27. Work with framework not against ... • Framework components have

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

    Plays nicely with your current dependencies • Dex method count • Dependencies • Maintenance • Runtime permissions
  29. What you can do Architecture • Consistent • Get people

    on board quickly • Have someone experienced • Pick your dependencies wisely
  30. HandlerThread • A thread with a message box • Saves

    a lot of boilerplate code • Uses Looper
  31. 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
  32. 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