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

10 ways to improve your Android app performance

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →
Boris Farber
October 28, 2015
170

10 ways to improve your Android app performance

Boris Farber

October 28, 2015

Transcript

61 slides
  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