10 ways to improve your Android app performance
-
Upload
boris-farber -
Category
Mobile
-
view
1.723 -
download
0
Transcript of 10 ways to improve your Android app performance
![Page 1: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/1.jpg)
10 ways to improve your app performanceBoris Farber Developer Advocate
+borisfarber @borisfarber www.api-solutions.com
![Page 2: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/2.jpg)
IF YOU HAVE A SMALL APP FORGET THESE SLIDES
![Page 3: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/3.jpg)
Symptoms
● Long start time● Slow app● Janky scrolling● Irresponsive app
![Page 4: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/4.jpg)
Activity Leaks
![Page 5: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/5.jpg)
Why memory leaks are dangerous
● Holding references to unused Activity○ handlers + static variables
● Activity holds its view
![Page 6: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/6.jpg)
● Activities/fragments etc - they have a life cycle● Static references
○ become dangling "pointers"○ staticActivity = staticFragment.getActivity()○ hold chain of references that lead to Activity <==
MEMORY LEAK
![Page 7: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/7.jpg)
Outer class (Activity)
Inner class (Handler)
![Page 8: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/8.jpg)
This is leakpublic class LeakActivity extends Activity {// ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); NastyManager.getInstance().addListener(this);// ...
![Page 9: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/9.jpg)
This is leak + fix@Overridepublic void onDestroy() { super.onDestroy();
NastyManager.getInstance().removeListener(this);}
remove listener
![Page 10: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/10.jpg)
This is leakpublic class MainActivity extends Activity {
// ...
Handler handler; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
} };
// ...
![Page 11: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/11.jpg)
What happens if ...
handler.postDelayed(...)
![Page 12: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/12.jpg)
This is 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) {
}
// ...
}
![Page 13: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/13.jpg)
Outer class (Activity)
Inner class (Handler)
![Page 14: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/14.jpg)
Prefer static to non static inner classes
● Non static Handler --> Activity leak● Both classes have a different lifetime
![Page 15: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/15.jpg)
3 ways to handle
● Use event bus● Unregister listeners● Prefer static inner classes to non static
![Page 16: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/16.jpg)
What you can do● Do code reviews● Understand your app structure● Use tools (MAT ...)● Print logs on callbacks
![Page 17: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/17.jpg)
Activity LeaksQuestions ?
![Page 18: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/18.jpg)
Scrolling
![Page 19: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/19.jpg)
Use UI Thread only for UI
● JSON parsing● Memory (images)● Networking● Database access
![Page 20: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/20.jpg)
What you can do to speed up scrolling
● Memory access - use library (caching, loading)● Networking access -
○ use library○ revisit your concurrency model
● Database access - use loaders
● JSON - use library DO NOT DO ANYTHING ON UI THREAD
![Page 21: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/21.jpg)
JSON
● Small JSONs - GSON is the best● Large JSONs - Jackson, ig-json-parser
![Page 22: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/22.jpg)
Large JSON
● Parsing has a performance effect● When converted to class with getters and
setters
![Page 23: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/23.jpg)
UI thread
Looper.myLooper() == Looper.getMainLooper()
![Page 24: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/24.jpg)
UI thread
● Never block it● Many java.net APIs are blocking
○ Streams○ Equals of URL class result in DNS call○ HttpURLConnection
![Page 25: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/25.jpg)
Don't over sync
● When user doesn't need it● Use push notifications
![Page 26: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/26.jpg)
Scrolling Questions ?
![Page 27: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/27.jpg)
Concurrency APIs 1
![Page 28: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/28.jpg)
Service
● Service methods run on UI thread ! ● Consider
○ IntentService○ AsyncTask○ Executors (separate bullet)○ HandlerThreads, Handlers and Loopers (separate
bullet)● Libraries do it for you
![Page 29: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/29.jpg)
IntentService
● Single threaded● Simple/One job in a time● No job system (keep track for jobs)● No way to stop to manage it
![Page 30: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/30.jpg)
AsyncTask
● Consider Loaders (part of support library)● 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)
![Page 31: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/31.jpg)
Concurrency APIs 1 Questions ?
![Page 32: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/32.jpg)
Deprecation
![Page 33: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/33.jpg)
Deprecation
● API will be removed● Your app will not work● No way to update APIs and tools
![Page 34: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/34.jpg)
Deprecation
● There is a compelling reason to move○ Security○ Correctness○ Performance
![Page 35: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/35.jpg)
What you can do around deprecation
● Know and use APIs● Refactor your dependencies
![Page 36: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/36.jpg)
Newer is better
● Prefer Toolbar to ActionBar● Prefer RecyclerView (especially for
animations)
![Page 37: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/37.jpg)
Don't use Apache Http Connection
● Removed at M (still available as dependency)
● Use HttpURLConnection○ Simple APIa○ Small size○ Transparent compression○ Response caching
![Page 38: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/38.jpg)
DeprecationQuestions ?
![Page 39: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/39.jpg)
JNI
![Page 40: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/40.jpg)
Best
● Use JNI as part of 3rd party lib
![Page 41: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/41.jpg)
Media
● Explore advanced CPU features● Memory ● Audio● Video
![Page 42: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/42.jpg)
Security
● Own wrapped library (SSL/crypto etc')● Rooted devices● Your own sensitive data/protocols
![Page 43: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/43.jpg)
What you can do
● Calls are expensive● Keep the boundaries simple● Keep native code to minimum● Keep native code isolated
○ All native methods in same class or package○ Porting layer
● Test, test, test ...
![Page 44: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/44.jpg)
JNIquestions?
![Page 45: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/45.jpg)
Architecture
![Page 46: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/46.jpg)
Understand app components life cycle
● Activities● Fragments● Tasks● Flags
● Add logs on callbacks
![Page 47: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/47.jpg)
Work with framework not against ...
● Framework components have a purpose○ Specific semantics○ Used when those semantics are desired
● Don't over engineer● Keep simple
![Page 48: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/48.jpg)
Your architecture
● Consistent● Get people on board quickly● Have someone experienced
![Page 49: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/49.jpg)
Design your app for
● Sleeping most of the time● Responsive when "awaken"
![Page 50: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/50.jpg)
Architecturequestions?
![Page 51: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/51.jpg)
Concurrency APIs 2
![Page 52: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/52.jpg)
ExecutorService
![Page 53: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/53.jpg)
Executor Framework
● Thread pool● Callbacks● Futures
![Page 54: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/54.jpg)
Dispatch downloadsExecutorService executor = Executors.newFixedThreadPool(1);// ...public void performAsyncCall(Handler handler) throws Exception{ // Fire a request. Future<Response> response = executor.submit(new Request (new URL("https://www.google.co.uk/")));
// Do your tasks here // ...
![Page 55: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/55.jpg)
Dispatch downloads// ...
// block current thread
InputStream body = response.get().getBody();
// System.out.print(getStringFromInputStream(body));
// post result to handler
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("text", "New data");
message.setData(bundle);
handler.sendMessage(message);
}
// ...
executor.shutdown();
![Page 56: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/56.jpg)
Parse resultspublic static class Request implements Callable<Response> {
private URL url;
public Request(URL url) {
this.url = url;
System.out.println("On async http dispatcher thread " + Thread.currentThread().getId());
}
@Override
public Response call() throws Exception {
System.out.println("On worker thread from pool " + Thread.currentThread().getId());
return new Response(url.openStream());
}
}
![Page 57: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/57.jpg)
Parse resultspublic static class Response {
private InputStream body;
public Response(InputStream body) {
this.body = body;
}
public InputStream getBody() {
System.out.println("On async http dispatcher thread " + Thread.currentThread().getId());
return body;
}
}
![Page 58: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/58.jpg)
Executor Framework
● Excellent for mapreduce jobs
![Page 59: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/59.jpg)
Handlers and Loopers
![Page 60: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/60.jpg)
HandlerThread
● A thread with a message box● Saves a lot of boilerplate code● Uses Looper
![Page 61: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/61.jpg)
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● Handler
○ Set of methods to post messages
![Page 62: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/62.jpg)
Parse results// Has Handler in own thread, will batch update the main Activity
private class MyLooper extends Thread {
@Override
public void run() {
// Prepare the current thread to loop for events
Looper.prepare();
dispatcherThreadHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
...
}
};
Looper.loop();
}
Push handler to any other thread
![Page 63: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/63.jpg)
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 (; ; ) { // ...
}
![Page 64: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/64.jpg)
Concurrency APIs 2Questions ?
![Page 65: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/65.jpg)
Miscellany
![Page 66: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/66.jpg)
Pick 3rd party lib checklist
● Solves your problem● Plays nicely with your current dependencies● Dex method count● Dependencies● Maintenance● Runtime permissions
![Page 67: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/67.jpg)
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
![Page 68: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/68.jpg)
Avoid complex views
● Visual clutter● Harder to maintain and draw● Use HierarchyViewer
![Page 69: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/69.jpg)
Use TimingLogging for measuring
![Page 70: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/70.jpg)
Best of luck in your journey wherever Android takes you
![Page 71: 10 ways to improve your Android app performance](https://reader034.fdocuments.net/reader034/viewer/2022042608/55c3bd0cbb61eb5d188b475b/html5/thumbnails/71.jpg)
Thank you !Boris FarberDeveloper Advocate