Programming Tips
There are two basic rules for writing efficient code:
- Don't do work that you don't need to do
- Don't allocate memory if you can avoid it
Avoid Creating Unnecessary Objects
Generally speaking, avoid creating short-term temporary objects if you can. Fewer objects created mean less-frequent garbage collection, which has a direct impact on user experience.
If you have a method returning a string, and you know that its result will always be appended to a
StringBuffer
anyway.public String makeFileName(int chapter) { return new StringBuffer(BASE_FILE_NAME).append("_").append(chapter).append(FILE_FORMART).toString(); } ... String path = new StringBuffer(BASE_PATH).append(makeFileName(chapter)).toString();
Change your signature and implementation so that the function does the append directly, instead of creating a short-lived temporary object.
public String makeFilePath(int chapter) { return new StringBuffer(BASE_PATH).append(BASE_FILE_NAME).append("_").append(chapter).append(FILE_FORMART).toString(); }
When extracting strings from a set of input data, try to return a substring of the original data, instead of creating a copy. You will create a new String object, but it will share the char[] with the data. (The trade-off being that if you're only using a small part of the original input, you'll be keeping it all around in memory anyway if you go this route.)
Need some sample code here.
An array of ints is a much better than an array of
Integer
objects.Two parallel arrays of ints are also a lot more efficient than an array of (int,int) objects.
The same goes for any combination of primitive types.
Prefer Static Over Virtual
If you don't need to access an object's fields, make your method static.
Invocations will be about 15%-20% faster. It's also good practice, because you can tell from the method signature that calling the method can't alter the object's state.
Use Static Final For Constants
This optimization applies only to primitive types and String constants, not arbitrary reference types.
static int intVal = 42;
static String strVal = "Hello, world!";
The compiler generates a class initializer method, called
<clinit>
, that is executed when the class is first used. When these values are referenced later on, they are accessed with field lookups.
We can improve matters with the "final" keyword:
static final int intVal = 42;
static final String strVal = "Hello, world!";
The class no longer requires a
<clinit>
method, because the constants go into static field initializers in thedex
file.
Avoid Internal Getters/Setters
Virtual method calls are expensive than instance field look-ups on Android. We can have getters and setters in the public interface, but within a class we should always access fields directly.
Use Enhanced For Loop Syntax
static class Foo {
int mSplat;
}
Foo[] mArray = ...
public void slowest() {
int sum = 0;
for (int i = 0; i < mArray.length; ++i) {
sum += mArray[i].mSplat;
}
}
The JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop inslowest()
.
public void faster() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray[i].mSplat;
}
}
faster()
pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit.
public void fastest() {
int sum = 0;
for (Foo a : mArray) {
sum += a.mSplat;
}
}
fastest()
uses the enhanced for loop syntax introduced in version 1.5 of the Java programming language.
Also see Joshua Bloch's Effective Java, item 46.
Consider Package Instead of Private Access with Private Inner Classes
public class Foo {
private class Inner {
void stuff() {
Foo.this.doStuff(Foo.this.mValue);
}
}
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);
}
}
The compiler generates a couple of synthetic methods:
/*package*/ static int Foo.access$100(Foo foo) {
return foo.mValue;
}
/*package*/ static void Foo.access$200(Foo foo, int value) {
foo.doStuff(value);
}
The inner class code calls these static methods whenever it needs to access themValue
field or invoke thedoStuff()
method in the outer class.
Avoid Using Floating-Point
Assuming space isn't an issue, you should prefer double to float.
Know and Use the Libraries
Dalvik replaces with an inlined intrinsic forString.indexOf()
. Similarly, theSystem.arraycopy()
method is about 9x faster than a hand-coded loop on a Nexus One with the JIT.
Also see Joshua Bloch's Effective Java, item 47.
23 May 2016