Sunday, June 22, 2014

Best practices for better performance in Android



  • Avoid runtime scaling of Bitmap

Background drawable always fits images, so it basically auto scales to fit and runtime scaling is very expensive, it effects performance. As it uses bifiltering technique to scale which is expensive but gives good scaled image.
Always prescale bitmap to increase performance, performance difference is 50% increase.
OriginalImage = Bitmap.CreateScaledBitmap(originalImage,
                                                view.getWidth(), //new width
                                                view,getHeight(), //new height
                                                true // bilinearfiltering);

  •  Use invalidate() for required portion only

invalidate() though looks simple but comes with big cost as it actually refreshes the whole screen.
So instead use, this will only refresh the required area and performance will increase upto 50%
invalidate(Rect);
invalidate(left, top, right, bottom);

  • Use Hierarchy View tool - view hierarchy is directly proportional to performance

 When clicked on view load hierarchy, it will show the the whole view hierarchy used in the focused window.
    • The less the view, good will be performance.
    • It also shows time taken to measure layout and draw views in miliseconds.
    • Try to look for layout which has only one child and get rid of that.


For example, Instead of using a layout with a textview and image just use textview with drawableleft

<TextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”@string/hello”
android:drawableleft=”@drawable/icon”
/>

  • Use ViewStub where ever views are mostly invisible or gone state
 A ViewStub is an invisible, zero-sized View that can be used to lazily inflate layout resources at runtime. When a ViewStub is made visible, or wheninflate() is invoked, the layout resource is inflated. The ViewStub then replaces itself in its parent with the inflated View or Views. Therefore, the ViewStub exists in the view hierarchy until setVisibility(int) or inflate() is invoked. The inflated View is added to the ViewStub's parent with the ViewStub's layout parameters. Similarly, you can define/override the inflate View's id by using the ViewStub's inflatedId property. For instance:


     <ViewStub android:id="@+id/stub"
                                android:inflatedId="@+id/subTree"
                                android:layout="@layout/mySubTree"
                                android:layout_width="120dip"
              android:layout_height="40dip" />



  • Use <merge/> tag to avoid unnecessary  declaration of layout for single child
 The <merge /> tag helps eliminate redundant view groups in your view hierarchy when including one layout within another. For example, if your main layout is a vertical LinearLayout in which two consecutive views can be re-used in multiple layouts, then the re-usable layout in which you place the two views requires its own root view. However, using another LinearLayout as the root for the re-usable layout would result in a verticalLinearLayout inside a vertical LinearLayout. The nested LinearLayout serves no real purpose other than to slow down your UI performance.

To avoid including such a redundant view group, you can instead use the <merge> element as the root view for the re-usable layout. For example:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/add"/>
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/delete"/>
</merge>

Now, when you include this layout in another layout (using the <include/> tag), the system ignores the<merge> element and places the two buttons directly in the layout, in place of the <include/> tag.

  • Use optimized data containers
Use SparseArray instead of hash maps as for maps where keys are of type integer, it’s typically more efficient to use the Android SparseArray API

The main interest of the SparseArray is that it saves memory by using primitives instead of objects as the key.

  • Use services sparingly and properly

If your app needs a service to perform work in the background, do not keep it running unless it's active and doing some task . The best way to limit the lifespan of your service is to use an IntentService, which finishes itself as soon as it's done handling the intent that started it.

  • Release memory when your user interface becomes hidden and memory is running low

When the user navigates to a different app and your UI is no longer visible, you should release any resources that are used by only your UI. Releasing UI resources at this time can significantly increase the system's capacity for cached processes, which has a direct impact on the quality of the user experience.
To be notified when the user exits your UI, implement the onTrimMemory() callback in your Activity classes. You should use this method to listen for the TRIM_MEMORY_UI_HIDDEN level, which indicates your UI is now hidden from view and you should free resources that only your UI uses.

During any stage of your app's lifecycle, the onTrimMemory() callback also tells you when the overall device memory is getting low. You should respond by further releasing resources based on the following memory levels delivered by onTrimMemory():

 Implement ComponentCallbacks2, override onTrimMemory(int level) and level can be checked for different inbuilt values like   TRIM_MEMORY_UI_HIDDEN or  TRIM_MEMORY_RUNNING_LOW 

  • Memory and heap management
Heap allocation for app is different for different hardware. Like for initial phone G1 was 16 MB and Motorola zoom has 48 MB.

To get an estimate of your app available heap in megabytes use

ActivityManager.getMemoryClass();

Generally if you think you app requires extra heap then in honeycomb new attribute was added to take large heap for a particular app. But this should be avoided unless really required, as large heap means large garbage collection, which intern will effect on performance.

In manifest.xml under <application
                                                                android:largeHeap = “true”
                                                />
ActivityManager.getLargeMemoryClass().

  • Use parcelable where necessary instead of Serializable
There are two ways to pass object references to activities and fragments

 Serialization is a marker interface, which implies the user cannot marshal the data according to their requirements. In Serialization, a marshaling operation is performed on a Java Virtual Machine (JVM) using the Java reflection API. This helps identify the Java objects member and behavior, but also ends up creating a lot of garbage objects. Due to this, the Serialization process is slow in comparison to Parcelable.   



0 comments:

Post a Comment