首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

高效率Android代码

2012-08-25 
高效Android代码Theres no way around it: Android-powered devices are embedded devices. Modern hands

高效Android代码

There's no way around it: Android-powered devices are embedded devices. Modern handsets may be more like small handheld computers than mere phones these days, but even the fastest, highest-end handset doesn't even come close to the capabilities of even a modest desktop system.That's why it's very important to consider performance when you write Android applications. These systems are not that fast to begin with and they are also constrained by their battery life. This means that there's not a lot of horsepower to spare, so when you write Android code it's important to write it as efficiently as possible.This page describes a number of things that developers can do to make their Android code run more efficiently. By following the tips on this page, you can help make sure your code runs as efficiently as possible.Contents

  • Introduction
  • Avoid Creating Objects
  • Use Native Methods
  • Prefer Virtual Over Interface
  • Prefer Static Over Virtual
  • Avoid Internal Getters/Setters
  • Cache Field Lookups
  • Declare Constants Final
  • Use Enhanced For Loop Syntax With Caution
  • Avoid Enums
  • Use Package Scope with Inner Classes
  • Avoid Float
  • Some Sample Performance Numbers
  • Closing Notes

    IntroductionThere are two basic rules for resource-constrained systems:
    • Don't do work that you don't need to do.
    • Don't allocate memory if you can avoid it.All the tips below follow from these two basic tenets.Some would argue that much of the advice on this page amounts to "premature optimization." While it's true that micro-optimizations sometimes make it harder to develop efficient data structures and algorithms, on embedded devices like handsets you often simply have no choice. For instance, if you bring your assumptions about VM performance on desktop machines to Android, you're quite likely to write code that exhausts system memory. This will bring your application to a crawl — let alone what it will do to other programs running on the system!That's why these guidelines are important. Android's success depends on the user experience that your applications provide, and that user experience depends in part on whether your code is responsive and snappy, or slow and aggravating. Since all our applications will run on the same devices, we're all in this together, in a way. Think of this document as like the rules of the road you had to learn when you got your driver's license: things run smoothly when everybody follows them, but when you don't, you get your car smashed up.Before we get down to brass tacks, a brief observation: nearly all issues described below are valid whether or not the VM features a JIT compiler. If I have two methods that accomplish the same thing, and the interpreted execution of foo() is faster than bar(), then the compiled version of foo() will probably be as fast or faster than compiled bar(). It is unwise to rely on a compiler to "save" you and make your code fast enough.

      Avoid Creating ObjectsObject creation is never free. A generational GC with per-thread allocation pools for temporary objects can make allocation cheaper, but allocating memory is always more expensive than not allocating memory.If you allocate objects in a user interface loop, you will force a periodic garbage collection, creating little "hiccups" in the user experience.Thus, you should avoid creating object instances you don't need to. Some examples of things that can help:
      • 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.
      • If you have a method returning a string, and you know that its result will always be appended to a StringBuffer anyway, change your signature and implementation so that the function does the append directly, instead of creating a short-lived temporary object.A somewhat more radical idea is to slice up multidimensional arrays into parallel single one-dimension arrays:
        • An array of ints is a much better than an array of Integers, but this also generalizes to the fact that 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.
        • If you need to implement a container that stores tuples of (Foo,Bar) objects, try to remember that two parallel Foo[] and Bar[] arrays are generally much better than a single array of custom (Foo,Bar) objects. (The exception to this, of course, is when you're designing an API for other code to access; in those cases, it's usually better to trade correct API design for a small hit in speed. But in your own internal code, you should try and be as efficient as possible.)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.

          Use Native MethodsWhen processing strings, don't hesitate to use specialty methods like String.indexOf(), String.lastIndexOf(), and their cousins. These are typically implemented in C/C++ code that easily runs 10-100x faster than doing the same thing in a Java loop.The flip side of that advice is that punching through to a native method is more expensive than calling an interpreted method. Don't use native methods for trivial computation, if you can avoid it.

          Prefer Virtual Over InterfaceSuppose you have a HashMap object. You can declare it as a HashMap or as a generic Map:
          Use Enhanced For Loop Syntax With CautionThe enhanced for loop (also sometimes known as "for-each" loop) can be used for collections that implement the Iterable interface. With these objects, an iterator is allocated to make interface calls to hasNext() and next(). With an ArrayList, you're better off walking through it directly, but for other collections the enhanced for loop syntax will be equivalent to explicit iterator usage.Nevertheless, the following code shows an acceptable use of the enhanced for loop:
          ordinal()?method. For example, replace:
              }

          private class Inner {
          void stuff() {
          Foo.this.doStuff(Foo.this.mValue);
          }
          }
          }
          The key things to note here are that we define an inner class (Foo$Inner) that directly accesses a private method and a private instance field in the outer class. This is legal, and the code prints "Value is 27" as expected.The problem is that Foo$Inner is technically (behind the scenes) a totally separate class, which makes direct access to Foo's private members illegal. To bridge that gap, the compiler generates a couple of synthetic methods:
          Avoid FloatBefore the release of the Pentium CPU, it was common for game authors to do as much as possible with integer math. With the Pentium, the floating point math co-processor became a built-in feature, and by interleaving integer and floating-point operations your game would actually go faster than it would with purely integer math. The common practice on desktop systems is to use floating point freely.Unfortunately, embedded processors frequently do not have hardware floating point support, so all operations on "float" and "double" are performed in software. Some basic floating point operations can take on the order of a millisecond to complete.Also, even for integers, some chips have hardware multiply but lack hardware divide. In such cases, integer division and modulus operations are performed in software — something to think about if you're designing a hash table or doing lots of math.

          Some Sample Performance NumbersTo illustrate some of our ideas, here is a table listing the approximate run times for a few basic actions. Note that these values should NOT be taken as absolute numbers: they are a combination of CPU and wall clock time, and will change as improvements are made to the system. However, it is worth noting how these values apply relative to each other — for example, adding a member variable currently takes about four times as long as adding a local variable.ActionTimeAdd a local variable1Launch an empty activity3,000,000

          Closing NotesThe best way to write good, efficient code for embedded systems is to understand what the code you write really does. If you really want to allocate an iterator, by all means use enhanced for loop syntax on a List; just make it a deliberate choice, not an inadvertent side effect.Forewarned is forearmed! Know what you're getting into! Insert your favorite maxim here, but always think carefully about what your code is doing, and be on the lookout for ways to speed it up.

热点排行