Android code optimization

Source: Internet
Author: User
Tags integer division
Android code optimization [go]

Designed for performance:
1) Avoid creating objects
Object creation is never free. Although GC makes the memory application cost no longer high, the application is always more expensive than the application. If you apply for an object in a user interface loop, you will forcibly execute the periodic GC, and there will be some small "snoring" in the user experience, unless you have, you should avoid creating object instances. The following examples can help you understand:
When you extract a string from a set of input data, try to return the child string of the source data instead of creating a copy. You will create a new String object, but it will share the character array char [] with the data.
If you have a method to return a string, and you know that the result will be appended to stringbuffer all the time, change your signature and implementation, so that the function can be directly appended, avoid creating temporary objects.
A more radical idea is to cut multi-dimensional arrays into parallel one-dimensional arrays:
An int array is better than an integer array, but it is also recognized that two parallel int arrays are much more efficient than an array of (INT, INT) objects. This is also true for other original data types.
If you need to implement a container that stores a group of objects (Foo, bar, remember that two equal Foo [] and bar [] arrays are usually better than a custom object array (of course, there is an exception for this, that is, when you design an API for access by other code, in that case, it is usually better to sacrifice a little speed to ensure the correctness of the API. But in your internal code, you should be as efficient as possible ).
Generally, avoid creating temporary objects, if you can. Creating fewer objects means less frequent GC, which has a direct impact on user experience.
2) NATIVE METHOD
When processing strings, do not hesitate to use strings such as string. indexof (), String. special methods such as lastindexof () are typical methods implemented using C/C ++ code. They can be 10-times faster than Java loops that implement the same function.
The opposite of this suggestion is that calling a native method is better than calling a parsing method. Do not use the native Method for trivial computation, if possible.
Virtual instead of interface is preferred.
If you have a hashmap object, you can declare it as a hashmap or a general map:
Map mymap1 = new hashmap ();
Hashmap mymap2 = new hashmap ();
Which one is better?
Generally, you should select map because it allows you to change its implementation. This is right for general programming, but it is not very good for embedded systems. Calling a method through interface reference takes two times more time than calling a virtual method through a specific type of reference.
If you have selected a hashmap, because it is suitable for what you are doing, calling through map has no value. Considering that IDE can refactor the code for you, calling with map does not have much value, even if you don't know where your code is going (but again, A public API is another exception: Good APIs seldom consider performance ).
3) Select static instead of virtual.
If you do not need to access an object field, make your method a static method. It can be called more quickly because it does not require indirect calls from a virtual method table. It is also a good practice, because the method signature shows that calling this method does not change the object state.
4) avoid internal getter/setter
In some languages like C ++, the usual practice is to use getter (for example, I = getcount () instead of directly accessing the field (I = mcount ), in C ++, this is a good habit, because the compiler can usually inline this access, and you need to restrict or debug field access, you can add code at any time.
In Android, this is a bad idea. Virtual method calls are expensive, and instance field searches are more expensive. It is reasonable to provide gettter and setter to object programming practices in public interfaces, but you should directly access fields in a class.

Cache field search
Accessing object fields is much slower than accessing local variables, as shown in the following section:
For (INT I = 0; I <this. mcount; I ++)
Dumpitem (this. mitems [I]);
It should be written as follows:
Int COUNT = This. mcount;
Item [] items = This. mitems;
For (INT I = 0; I <count; I ++)
Dumpitems (items [I]);
(We use an explicit "This" to indicate that this is a member variable .)
A similar guideline is that you do not call a method in the second clause of the for statement. For example, the following code will execute getcount () every iteration, which is a huge waste. You can cache its value as an int.
For (INT I = 0; I <this. getcount (); I ++)
Dumpitems (this. getitem (I ));
Generally, if you want to access an instance field multiple times, a good habit is to create a temporary variable. For example:
Protected void drawhorizontalscrollbar (canvas, int width, int height ){
If (ishorizontalscrollbarenabled ()){
Int size = mscrollbar. getsize (false );
If (size <= 0 ){
Size = mscrollbarsize;
}
Mscrollbar. setbounds (0, height-size, width, height );
Mscrollbar. setparams (computehorizontalscrollrange (),
Computehorizontalscroloffset (),
Computehorizontalscrollextent (), false );
Mscrollbar. Draw (canvas );
}
}
This is a separate search for the member field mscrollbar four times. By caching the mscrollbar to a local variable, the four member field searches are changed to four local variable references, which is more efficient.
Similarly, method parameters as local variables share the same performance characteristics.
Declare constant as final
Consider the following declaration at the beginning of the class:
Static int intval = 42;
Static string strval = "Hello, world !";
The compiler generates a class initialization method called <clinit>, which is executed when the class is used for the first time. This method saves 42 to intval and extracts a reference from the String constant table of the class file for intval. When these values are referenced later, they are accessed as field searches.
We can use the final keyword to improve it:
Static final int intval = 42;
Static final string strval = "Hello, world !";
This class no longer requires a <clinit> method, because the constant is saved to the static field initializer of the class file that is directly processed by the VM. When the code accesses intval, the integer value 42 is directly used, however, intval access will use a relatively cheap "String constant" command to replace a field search.
Declaring a method or class as final does not directly obtain performance benefits, but it does play an optimization role. For example, if the compiler knows that a "Getter" cannot be overwritten by a subclass, it can call this method inline.
You can also declare local variables as final, but this does not actually improve performance. For location variables, use final only when making the code clearer (or you have to, for example, to be used in anonymous internal classes.
Use the enhanced for loop statement with caution
The enhanced for statement can be used to implement the collection of iterable interfaces. For these objects, an iterator is applied to call the hasnext () and next () interfaces (). For arraylist, you 'd better traverse it directly, but for other collections, the enhanced for loop statement will be equivalent to the explicit iterative usage.
However, the following code demonstrates the acceptable use of enhanced for statements:
Public class Foo {
Int msplat;
Static Foo marray [] = new Foo [27];
Public static void zero (){
Int sum = 0;
For (INT I = 0; I <marray. length; I ++ ){
Sum + = marray [I]. msplat;
}
}
Public static void one (){
Int sum = 0;
Foo [] localarray = marray;
Int Len = localarray. length;
For (INT I = 0; I <Len; I ++ ){
Sum + = localarray [I]. msplat;
}
}
Public static void two (){
Int sum = 0;
For (foo a: marray ){
Sum + = A. msplat;
}
}
}
Zero () in a loop, each iteration obtains a static field and calculates the length of the array twice.
One () stores everything in local variables to avoid searching.
Two () uses an enhanced for loop statement. The code generated by the compiler copies the array reference and the array length to the local variable, making it a good choice for Traversing array elements. It does produce an additional local load/storage in the main loop, making it a little slower and 4 bytes longer than one.
In short, the enhanced for statement performs well for arrays, but be careful when using iterable objects because additional objects are created.
Avoid Enum type
Enum is very convenient, but unfortunately it is painful to consider time and speed. For example:
Public class Foo {
Public Enum shrubbery {ground, crawler, hanging}
}
Compile it into a byte. Class file. When used for the first time, the class initializer activates the <init> Method on every enumerated value object. Each object has its static fields, and the entire set is stored in an array (a static field called "$ values"). For only three integers, that's too much code and data.
This:
Shrubbery shrub = shrubbery. ground;
A static field query is performed. If "Ground" is a static final int, the compiler will regard it as a constant and inline it.
On the contrary, of course, you can use Enum to get a more elegant API and some compile-time value checks. Therefore, the usual compromise is: For API, you should do everything possible to use Enum, but when considering performance, try to avoid using it.
Use the internal class to use the package's domain
Consider the following class definitions:
Public class Foo {
Private int mvalue;
Public void run (){
Inner in = new inner ();
Mvalue = 27;
In. Stuff ();
}
Private void dostuff (INT value ){
System. Out. println ("value is" + value );
}
Private class inner {
Void stuff (){
Foo. This. dostuff (FOO. This. mvalue );
}
}
}
Here we should note that an internal class (FOO $ inner) is defined here, which can directly access the private methods and private instance fields of the external class, which is legal, the result of code execution is as expected "value is 27 ".
The problem is that Foo $ inner is a completely independent class, which makes it illegal to directly access its private method. to bridge the gap, the compiler will generate the following two virtual methods:

/* Package */static int Foo. Access $100 (Foo ){
Return Foo. mvalue;
}
/* Package */static void Foo. Access $200 (Foo, int value ){
Foo. dostuff (value );
}
These methods are called when the internal class code needs to access the mvalue variable of the external class or activate the dostuff method. This means that the code above clearly shows that you access the member fields through the accessors rather than directly accessing them. As we have discussed earlier, accessors are slower than direct access, so this is a potential performance blow caused by a specific language or dialect.
We can resolve this problem by declaring fields and Methods accessed by internal classes to have a package scope rather than a private scope. This method runs faster and removes additional methods (unfortunately, this also means that these fields can be accessed by other classes in the same package, this violates the standard oo practice of making all fields private. Once again, if you are designing a public API, you may need to carefully consider this optimization strategy ).
9) avoid using the Float Type
Before the launch of the Pentium CPU, it was normal for game authors to do a lot of integer computing. With Pentium, the floating point computing integrated processor has become a built-in function, and your game runs much faster through staggered integer and floating point operations than only integer computing. Floating Point Numbers are usually available on the desktop system.
Unfortunately, embedded processors rarely have hardware floating point support, so all "float" and "double" operations are performed on software. Some basic floating point operations may take several microseconds.
In addition, for integer data, some chips Support Hardware multiplication but lack hardware Division. In this case, integer Division and modulo operation are performed in software. If you are designing a hash table or performing many mathematical operations, you need to consider this.

Design for Response Sensitivity

Code may pass various performance tests, but it still takes a long wait for users to use them. These are the applications that are not responsive-they are slow to respond, and they have a long suspension or freezing period, or it takes a long time to process the input.
On Android, the system displays a dialog box called ANR: application not responding to users to prevent slow response within a period of time. You can choose to continue the application, but the user does not want to process this dialog box every time. Therefore, you should design your application to be responsive so that the system does not need to display ANR to users.
Generally, the system displays an ANR when it cannot respond to user input. For example, if an application blocks I/O operations (often network access), the main application thread cannot process ongoing user input events. After a period of time, the system considers that the application has been suspended and displays an ANR to the user so that the user can choose to disable it.
Similarly, if your application spends too much time building a detailed memory structure or computing the next action of the game, the system will think that your application has been suspended. It is always important to use the above technologies to ensure that these computation is efficient, but even the most efficient code operation takes time.
In both cases, the solution is to create a subthread to do most of your work on this subthread. In this way, your main thread (driving the user interface event loop) remains running and your code is immune from being frozen by the system. Because such threading is usually completed at the class level, you can think that the response performance problem is a class problem (with the method-level performance problem described above ).
This document discusses how the Android system determines that an application does not respond, and provides guidance to ensure that your application is responsive.
1) What caused ANR?
In the Android system, the response sensitivity of an application is monitored by activity manager and window manager system services. When it detects one of the following conditions, android displays an ANR for a specific application:
No response to the input event within 5 seconds.
A broadcastreceiver fails to be executed within 10 seconds.
How to Avoid ANR?
Considering the definition of ANR, let's take a look at why and how best to organize your application to avoid ANR.
Android applications normally run in a separate (such as main) thread, this means that the ANR dialog box can be activated for all the things that are being done in your main application process that take a long time to complete. Because your application does not give yourself a chance to handle input events or intent broadcasts.
Therefore, any method running in the main thread should do as few things as possible. In particular, activitiy should do as few settings as possible in key life cycle methods such as oncreate () and onresume. Potential time-consuming operations (such as network or database operations, or high-consumption mathematical calculations such as changing the bitmap size) should be completed in the Child thread (or take database operations as an example, can be passed through asynchronous requests ). However, this does not mean that your main thread must be blocked when waiting for the completion of the sub-thread-you do not have to call the thread. wait () or thread. sleep (), on the contrary, your main thread should provide a handler for the sub-thread so that it can be submitted back to the main thread when the sub-thread completes. Designing your application in this way will allow your main thread to always respond to input, to avoid ANR conversations caused by 5 seconds of input event timeout. These practices should also be followed by any other display UI thread because they belong to the same type of timeout.
The specific execution time limit of intentreciever limits what they should do: some trivial tasks executed in the background, such as saving settings or registering notifications. For other methods called in the main thread, in broadcastreceiver, applications should avoid potentially time-consuming operations or computations, instead, subthreads should be used to complete intensive tasks (because the life cycle of broadcastreceiver is short ). In response to intent broadcast, your application should start a service to perform time-consuming operations. Similarly, you should avoid starting the activity from the intent receiver because it will generate a new screen and steal the focus of any application that the user is running. The response to intent broadcast should be completed using notification manager if your application needs to display something to the user.

Enhanced Response Sensitivity
Generally, in an application, 100 to 200 microseconds is a threshold that makes users feel blocked. Therefore, there are some tips to make your application seem more responsive.
If your application is responding to user input in the background, the progress is displayed (progressbar and progressdialog are useful ).
Especially for games, mobile computing is performed in sub-threads.
If your application has a time-consuming initialization process, consider rendering the main interface as quickly as possible with a splash screen and asynchronously filling information. In both cases, you should indicate that the progress is in progress, so that users do not feel that your application is frozen.

Seamless design:

Even if your application is fast and responsive, some designs can still cause problems to users-unexpected data loss due to unplanned interactions or conversations with other applications, unconscious blocking and so on. To avoid these problems, it helps you understand the running environment of your application and the system interaction that can affect your application. In short, you should do your best to develop an application that interacts seamlessly with the system and other applications.
A common seamless problem is that a background process of an application (such as a service or broadcast receiver) responds to an event and a dialog box pops up, which seems to be no problem, especially when you build and test your applications separately on the simulator. However, when your application runs on a real device and the background thread displays a dialog box, your application may not gain the user focus at the time. This will display a dialog box after the active application, or get the focus from the current application and display the dialog box, let's talk about what the user was doing at the time (such as making a phone call ). Such behavior may not work for your applications or users.
To avoid these problems, your application should use the appropriate system resource-Notification class to notify users. With notifications, your application can display an icon on the status bar to notify users that an event has occurred, rather than getting focus and interrupting users.
Another example of the seamless problem is that the activity accidentally loses its status or user data because it fails to correctly implement onpause () and other lifecycle methods. Alternatively, to expose data for other applications, you should use contentprovider instead of a source file or database that can be read all over the world.
The common feature of these examples is that they are all about how to better collaborate with the system and other applications. The Android system design regards all applications as a loosely coupled component Federation, not a bunch of ink cartridge code. This allows you as a developer to regard the entire system as a larger component Federation. This allows you to clearly and seamlessly integrate applications with other applications. In return, you should better design your code.
This document discusses common seamless integration problems and how to avoid them. It contains the following topics:
Do not discard data
Remember that android is a mobile platform. It seems obvious, but it is very important to remember this fact that any activity (such as the "Incoming call" app) may pop up to overwrite your activity at any time, this will activate the onsaveinstancestate () and onpause () methods, and cause your application to be killed. If another activity occurs, the user edits data on your application. When your application is killed, the data may be lost. Of course, unless you save the work in progress. The "Android method" does this: applications that can receive and edit user input must rewrite the onsaveinstancestate () method and save their statuses in an appropriate way. When users access the application again, you can obtain data again.
A typical example of using this behavior is the mail application. When the user is writing an email, another activity starts. The application should save the edited email as a draft.
Do not expose raw data
If you don't want to walk in the street in your underwear, you shouldn't do the same with your data. Although some applications may be exposed to facilitate reading by other applications, this is usually not the best idea. Exposing raw data requires other applications to understand your data format. If you change the format, you will destroy other applications that are not updated at the same time.
The "android method" is to create a contentprovider to expose your data to other applications through a clear, thoughtful, and maintainable API. Using contentprovider is like a Java interface to separate code closely coupled with componentization. This means that you can modify the internal format of your data without modifying the interfaces exposed by contentprovider, this will not affect other applications.
Do not interrupt the user
It is safe to ensure that a user runs an application with a purpose. That is why you should avoid the cause of activity unless you directly respond to the user input of the current activity.
That is to say, do not call startactivity () from broadcastreceiver and service running in the background (). This will interrupt any running application and make the user angry. Even your activity may become a "hit key robber" to receive the input that some users are providing for the previous activity, depending on what your application does. This may be a bad message.
Instead of directly generating activity UIS from the background, you should use notificationmanager to set notifications, which will appear on the status bar, when users are idle, click them to see what your application shows them.
(Note: When your activity is already in the foreground, none of this applies: In this case, the user expects to see your next activity for the input response .)
Are there too many things to do? In a thread
If your application requires a costly or time-consuming computing, you may need to move it to a thread. This will prevent the "Application not responding" dialog box from being displayed to the user, resulting in the end of your application completely.
By default, the code in an activity runs on the same thread as all its views. This is the same as the thread that handles the UI event. For example, when a key is pressed, a key-down event is added to the queue of the active thread of the activity. The event processing system needs to quickly list and process the event. Otherwise, the system will think that the application has been suspended and killed for the user several seconds later.
If you have a long time-consuming code, letting it run inline on your activity will cause it to run on the event processing thread, which largely blocks the event processing handle. This will delay the input processing and cause the ANR dialog box. To avoid this, move your computing to a thread. We have discussed how to design the response sensitivity.
5) Do not overload a single activity Screen
Any worthy application may have several different screens. When designing your UI screen, you must use multiple activity object instances. Depending on your development background, you may interpret an activity like something similar to a Java Applet. activity is the entry point of your application. However, it is not accurate: The subclass of an applet is a single entry point of a Java Applet, and an activity should be seen as a potential entry point for your application. The only difference between your "Main" activity and any other activity you may have is that the "miain" activity happens to be the only one in your androidmanifest. in the XML file. intent. action. the main action is only interesting.
Therefore, when designing your application, consider your application as the Union of an activity object. In the long run, this makes your code more maintainable.
6) extended system themes
Coordination is important when it comes to the perception of user interfaces. Users shake applications that are opposite to the user interfaces they expect. When designing your UI, you should try to avoid too many theme. On the contrary, use the same theme. You can override or extend the theme that you need, but at least you are based on the same UI as other applications. For details, see the "Application style and topic" section.
7) design your UI to work with the multi-screen resolution
Different Android-based devices may support different resolutions. You can change the resolution at any time. Ensuring that your layout and images are flexible enough is very important for normal display on different device screens.
Fortunately, this is easy to do. To put it simply, you need to provide different versions of work for your key resolutions, and then design your layout to adapt to different dimensions. (For example, to avoid using relative layout for hard-coded locations .) If you do that, the rest of the system will handle it. Your application looks great on any device.
8) assume that the network is slow.
Android devices have multiple network connection options. All of them provide data access, although some of them will be faster than others. Among them, the slowest speed is GPRS (non-3G data service of GSM network ). Even a device with 3G capability will spend a lot of time on a non-3G network, low speed will be a long-standing fact.
That is why you should write your applications for minimal network access and bandwidth. You cannot assume that the network is fast, so you should always plan that it is slow. If your users happen to be on a fast network, it's good-their experience will only improve. You need to avoid the opposite: applications are sometimes available, but sometimes slow and frustrating, depending on the time at which the user is, such applications may not be popular.
Do not assume that the touch screen and keyboard
Android may support multiple appearances. That is to say, some Android devices will have a complete "qwerty" keyboard, while others may have 40 keys, 12 keys, or other keyboard settings. Similarly, some devices have touch screens, but many do not.
When building your application, remember not to assume a specific keyboard layout-unless you really like to restrict your application so that it can only run on some devices.
Be sure to save device batteries
If mobile devices are often confined to the house, they are not very "mobile ". Mobile devices are powered by batteries, and if we make the battery usage more persistent, everyone will be happier-especially for users. Two of the largest power consumers are processors and audio, Which is why you should do as little work as possible for applications you write while using the network as frequently as possible.
To minimize the processing time used by your application, it is down to writing efficient code. To minimize the power consumption of audio, make sure that you handle error conditions elegantly and only get what you need. For example, if the network connection fails, do not try again. If the connection fails once, the user may not receive the signal. If you try again immediately, all you do is waste battery energy.
Users are very smart: If your program is high in power consumption, you can believe they will find out. At that point, the only thing that can be confirmed is that your program will not be installed for a long time.

Post address: http://www.getideas.cn /? P = 60. Reprinted. Please keep it.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.