Android Best performance Practice (iii)--high-performance coding optimization

Source: Internet
Author: User

In the first two articles, we learned about Android memory, including how to use memory reasonably, and how to locate a problem when a memory leak occurs. So the knowledge of memory is discussed here, and today we will learn some techniques of performance coding optimization.

Here first of all, the coding optimization techniques discussed in this article are all part of "micro-optimization", meaning that even if we follow the techniques of this article to optimize the code, there is no significant improvement in performance. Using the right algorithms and data structures will always be the most important way to optimize your program's performance, but this piece of content will not be discussed in this article. Therefore, what we are going to learn here is not a panacea, but we should consider these techniques as a good coding standard, we can use these coding norms in the normal writing code, not only to improve the performance of the program at the micro level, but also to make our code more professional, Let's take a look at these techniques together.

Avoid creating unnecessary objects

Creating an object should never be a random thing, because creating an object means that the garbage collector needs to reclaim an object, both of which are time consuming. Although the cost of creating an object is really very small, and the Android 2.3 version adds a concurrent garbage collector mechanism (see Android Best Performance Practice (ii)-Analyzing memory usage ), which makes the pause time of the GC operation difficult to detect, But these reasons are not enough to allow us to create objects arbitrarily, we need to create objects we naturally want to create, but unnecessary objects we should try to avoid creating.

Here's a look at some of the scenarios where we can avoid creating objects:

    • If we have a string that needs to be stitched together, then it is preferable to use StringBuffer or StringBuilder for stitching instead of the plus connector, because using the plus sign to connect inode creates extra objects, the longer the concatenated string, the lower the performance of the plus connector.

    • In cases where there are no special reasons to use the basic data class instead of the encapsulated data type, int is more efficient than integer and the other data types are the same.

    • When the return value of a method is a string, it is usually possible to determine what the string does, and if we know explicitly that the caller will re-stitch the returned string, consider returning a StringBuffer object instead, Because it is possible to return a reference to an object, the return string is a temporary object that creates a short life cycle.

    • As previously mentioned, the basic data type is better than the object data type, and similarly an array of basic data types is preferable to an array of object data types. In addition, two parallel arrays are more efficient than a well-encapsulated array of objects, for example, two arrays such as foo[] and bar[], which are much more efficient to use than a custom (Foo,bar) [] array.

Of course, the above is only a few representative examples, we have to abide by a basic principle is to create as few temporary objects as possible, the fewer objects mean less GC operations, but also means the better program performance and user experience.

Static better than abstract

If you do not need to access some of the fields in an object, just want to invoke one of its methods to complete a common function, then you can set this method to a static method, which will increase the speed of the call 15%-20%, but also do not need to call this method to specifically create objects, This also satisfies one of the above principles. This is also a good programming habit, because we can safely invoke a static method without worrying about whether it will change the state of the object after the method is called (the non-static field cannot be accessed in a static method).

Use the static final modifier for constants

Let's take a look at the top of a class. Define the following code:

12 staticint intVal = 42;staticString strVal = "Hello, world!";

The compiler generates an initialization method for the above code, called the <clinit> method, which is called when the class is first used. This method then assigns a value of 42 to the Intval and extracts a reference assignment from the string constant table to Strval. When the assignment is complete, we can access the specific value by the way the field is searched.

But we can also optimize the above code with the final keyword:

12 staticfinal int intVal = 42;static finalString strVal = "Hello, world!";

After this modification, defining the class eliminates the need for a <clinit> method, since all constants are initialized in the initializer of the Dex file. When we call Intval, we can point directly to the value of 42, while calling Strval uses a relatively lightweight string constant, rather than the way the field is searched.

It is also important to note that this optimization method is valid only for basic data types and constants of type string, and is not valid for constants of other data types. However, it is still a good practice for any constant to be declared with a static final keyword.

Using enhanced for-loop syntax

The enhanced for loop (also known as the For-each Loop) can be used to iterate through the collection of implemented iterable interfaces and arrays, which is a new looping pattern in JDK 1.5. Of course, in addition to this new cycle mode, we can still use the original normal loop mode, but they are efficient difference between, we look at the following code:

12345678910111213141516171819202122232425262728 static class Counter { int mCount;}Counter[] mArray = ...public void zero() { int sum = 0; for (int i = 0; i < mArray.length; ++i) { sum += mArray[i].mCount; }}public void one() { int sum = 0; Counter[] localArray = mArray; int len = localArray.length; for (int i = 0; i < len; ++i) { sum += localArray[i].mCount; }}public void two() { int sum = 0; for (Counter a : mArray) { sum += a.mCount; }}

As you can see, in the above code we used three different loops to sum all the elements in the Marray. where the zero () method is the slowest, because it writes Marray.length in the loop, which means that each cycle needs to recalculate the length of the Marray once. The one () method is much faster because it uses a local variable len to record the length of the array, eliminating the time it takes for the field to search for Each loop. The one () method is the fastest on a device without JIT (Just in time Compiler), and the One () method is the same as running on a JIT device, and the only thing to note is that it requires JDK 1.5 to support it.

But here's a special case, for ArrayList this collection, the loop of your own handwriting is faster than the enhanced for loop, which is not the case for other collections. Therefore, for us, the enhanced for loop can be used by default, and the traditional loop is used when traversing ArrayList.

Use a system-encapsulated API

In fact, the Java language provides us with a very rich API interface, we write the program if we can use the system-provided API should be used as far as possible, the system provides the API does not complete the functions we need to write their own, Because the APIs used in the system are much faster than the code we write ourselves, many of their functions are performed through the underlying assembly pattern.

For example, many of the APIs provided in the string class are highly efficient, like the indexof () method and some other related APIs, although we can do the same thing by writing our own algorithms, but the efficiency will be far worse than these methods. Here, for example, if we are going to implement an array copy function, it is certainly possible to use a loop to assign each element to each of the arrays, but if we directly use the System.arraycopy () method provided in the system, it will be more than 9 times times more efficient to execute.

Avoid calling the Getters/setters method internally

When we write code, we are told that we must use object-oriented thinking to write code, and the three main object-oriented features we all know, encapsulation, polymorphism, and inheritance. The basic idea of encapsulation is not to leak the fields inside the class to the outside, but rather to provide a specific method to allow the external operation of the corresponding class's internal fields, thus appearing in the Java language getters/setters this encapsulation technique.

On Android, however, this technique is no longer so respected, because field searches are much more efficient than method invocations, and it may be 3 to 7 times times faster for us to access a field directly than to access the field through the Getters method. However, we must not abandon the encapsulation technique simply because of its efficiency, and write the code in terms of object-oriented thinking, but we can optimize it where it can be optimized, such as avoiding calling the Getters/setters method internally.

What is called the Getters/setters method internally? Here I give a very simple example:

123456789101112131415161718 public class Calculate { private int one = 1; private int two = 2; public int getOne() { return one; } public int getTwo() { return two; } public int getSum() { return getOne() + getTwo(); }}

As you can see, this is a calculate class, the function of this class is very simple, first one and two fields are encapsulated, and then provides the GetOne () method to get the value of the one field, provides the Gettwo () method to get the value of a field, A getsum () method is also provided to get the value of the sum.

Here we notice that the algorithm in the Getsum () method is the addition of the values of one and two to return, but the way it obtains the values of one and two is also obtained through the Getters method, in fact, this is a completely unnecessary way, because Getsum () The method itself is a method inside the Calculate class, which is directly accessible to the encapsulated fields in the Calculate class, so this is not a recommended way to do on Android, and we can make the following changes:

123456789101112 public class Calculate { private int one = 1; private int two = 2; ...... public int getSum() { return one + two; }}

After this is changed, we avoid calling the Getters/setters method internally, while the Calculate class is still well encapsulated externally.

http://www.androidchina.net/1961.html#rd?sukey= fc78a68049a14bb25feaa125f45f038b5eee1640d4fb19c886789710713c8e21474b702046947fc4bc660b2c685cb70a

Android Best performance Practice (iii)--high-performance coding optimization

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.