How to avoid creating unnecessary objects in Android _android

Source: Internet
Author: User
Tags connection pooling data structures garbage collection readline static class

Objective

As you assign more objects to the app, you have to implement regular garbage collection, which can lead to a small cotton phenomenon in the user experience. Concurrent garbage processors are introduced in Android 2.3, but should always avoid unnecessary work, so you should avoid creating object instances when you don't need to.

In the programming development, the memory occupies is we often to face the reality, the common memory tuning direction is minimizes the memory to occupy.

Android devices don't have as much memory as PCs, and the memory used by a single app is actually relatively small. So avoiding creating unwanted objects is especially important for Android development.

This article will introduce some common scenarios and methods to avoid creating objects, some of which are micro-optimized, some are coding techniques, and of course there are ways to make a difference.

Use a single example

A single example is our commonly used design pattern, in which we can provide only one object for global invocation. So a single example is a way to avoid creating unnecessary objects.

Single case mode is easy to use, but need to pay attention to a lot of problems, the most important thing is multithreading concurrency to ensure the uniqueness of a single case. Of course, there are many ways, such as a hungry man-style, lazy type double-check .

Here's a very geek way to write a single example.

public class SingleInstance {
 private singleinstance () {
 } public

 static SingleInstance getinstance () { return
   singleinstanceholder.sinstance;
 }

 private static class Singleinstanceholder {
   private static singleinstance sinstance = new SingleInstance ();
 }
}

In Java, static initialization of a class is triggered when the class is loaded, and we use this principle to implement this feature, combining the inner class, to implement the code above, and to create an instance of the lazy type.

Avoid implicit boxing

Automatic boxing is an attribute introduced in Java 5 that automatically converts raw data of the original type to the corresponding reference type, such as the conversion to, int Integer and so on.

This feature greatly reduces the trivial work of coding, but a little attention may create unnecessary objects. Like the following code

Integer sum = 0;
for (int i=1000; i<5000; i++) {
  sum+=i;
}

The above code sum+=i can be considered sum = sum + i , but the + this operator does not apply to the integer object, first sum for the automatic unboxing operation, the numerical addition operation, the last occurrence of automatic boxing operation converted to an integer object.

Its internal changes are as follows

int result = Sum.intvalue () + i;
Integer sum = new Integer (result);

Because the sum we declare here is an integer, nearly 4,000 useless integer objects are created in the loop above, and in such a large loop, the performance of the program is reduced and the workload of garbage collection is increased. So when we're programming, we need to be aware of this, declaring variable types correctly, and avoiding performance problems caused by automatic boxing.

Also, automatic boxing occurs when the value of the original data type is added to the collection, so there are also objects created in this procedure. If there is a need to avoid this situation, you can choose SparseArray , SparseBooleanArray and SparseLongArray so on containers.

Careful selection of containers

Java and Android provide many of the edited collection of containers to organize objects. For example, ArrayList ContentValues , and HashMap so on.

However, this container is easy to use, but there are some problems, that is, they will automatically expand, which is not to create new objects, but rather create a larger container object. This means that this will take up a larger memory footprint.

Taking HashMap as an example, when we are put key with value , we will detect if there is a need for expansion, if necessary, double the expansion

@Override Public V-Put (K key, V value) {
    if (key = = null) {return
      Putvaluefornullkey (value);
    }
    Some code here

    //No entry for (Non-null) key is present; create one
    modcount++;
    if (size++ > Threshold) {
      tab = doublecapacity ();
      Index = hash & (tab.length-1);
    }
    Addnewentry (key, value, hash, index);
    return null;
  }

There are usually several ways to expand the problem.

1. Estimate a large capacity value to avoid multiple expansions

2. Looking for alternative data structures to ensure a balance of time and space

Use good launchmode.

Mention of Launchmode must be related to activity. Normally we declare an activity in manifest and use the default standard mode if we do not set Launchmode.

Once set to standard, a new activity instance is created whenever a intent request is made. For example, if there are 10 intent that compose a message, 10 composemailactivity instances will be created to handle the intent. The result is obvious that this pattern creates multiple instances of an activity.

If you actually maintain an activity example for a search function, using the standard pattern can cause too many instances of activity to be created and therefore bad.

Ensure reasonable use of launchmode and reduce the creation of activity.

Activity processing onconfigurationchanged

This is also related to the creation of an activity object because the cost of activity creation is much higher than for other objects.

By default, when we do the screen rotation, the original activity is destroyed, a new activity is created, and the reason for this is to handle the layout adaptation. Of course, this is the default practice of the system, and we can avoid recreating the activity as we develop controllable scenarios.

Take a screen switch, for example, when the activity statement is added

<activity
  android:name= ". Mainactivity "
  android:label=" @string/app_name "
  android:theme=" @style/apptheme.noactionbar "
  Android : configchanges= "Orientation"
>

Then rewrite the method of the activity onConfigurationChanged

public void onconfigurationchanged (Configuration newconfig) {
  super.onconfigurationchanged (newconfig);
  if (newconfig.orientation = = configuration.orientation_portrait) {
    setcontentview (r.layout.portrait_layout);
  } else if (newconfig.orientation = = configuration.orientation_landscape) {
    Setcontentview (r.layout.landscape_ layout);
  }

Note string concatenation

String this is perhaps the most obscure one. This is mainly about the concatenation of strings.

LOG.I (LogTag, "onCreate bundle=" + savedinstancestate);

This should be our most common way of playing log, but the concatenation of strings is actually generating objects and then append them all the way to the StringBuilder final call to the ToString method.

Here is a code loop code, which is obviously bad because it creates a lot of StringBuilder objects.

public void Implicitusestringbuilder (string[] values) {
 String result = "";
 for (int i = 0; i < values.length i + +) {result
   = Values[i];
 }
 SYSTEM.OUT.PRINTLN (result);
}

The way to reduce string concatenation is

1. Replace with String.Format

2. If it is a circular stitching, it is recommended to explicitly create StringBuilder using outside the loop

Reduce layout levels

Too many layout levels, not only lead to inflate process time-consuming, but also create redundant auxiliary layout. Therefore, it is necessary to reduce the auxiliary layout. You can try other layouts or customize views to solve this type of problem.

Check in advance to reduce unnecessary anomalies

Exception for the program, in the usual, and then actually the code is very high, because it needs to collect field data stacktrace. But there are some measures to avoid the exception, that is, to do some early inspection.

For example, we want to print a file for each line of string, do not check the code below, is FileNotFoundException possible to throw out.

private void Printfilebyline (String filePath) {
  try {
    FileInputStream InputStream = new FileInputStream (" Textfile.txt ");
    BufferedReader br = new BufferedReader (new InputStreamReader (InputStream));
    String StrLine;
    Read File line by line while
    ((StrLine = Br.readline ())!= null)  {
      //Print The content
      on the console System.out.println (StrLine);
    }
    Br.close ();
  } catch (FileNotFoundException e) {
    e.printstacktrace ();
  } catch (IOException e) {
    e.printstacktrace ();
  }
}

If we check for the existence of the file, the probability of throwing is FileNotFoundException much reduced,

private void Printfilebyline (String filePath) {
    if (!new File (FilePath). Exists ()) {return
      ;
    }
    try {
      FileInputStream InputStream = new FileInputStream ("Textfile.txt");
      BufferedReader br = new BufferedReader (new InputStreamReader (InputStream));
      String StrLine;
      Read File line by line while
      ((StrLine = Br.readline ())!= null)  {
        //Print The content on the CONSOLE
   system.out.println (StrLine);
      }
      Br.close ();
    } catch (FileNotFoundException e) {
      e.printstacktrace ();
    } catch (IOException e) {
      e.printstacktrace ();
    }
  }

The above check is a good coding technique that is recommended for adoption.

Don't create threads too much

In Android, we should try to avoid time-consuming operations in the main thread, so we need to use other threads.

private void Testthread () {
  new Thread () {
    @Override public
    void Run () {
      super.run ();
      Do some IO work
    }
  }.start ();
}

While these work, the cost of creating threads is much higher than for ordinary objects, suggesting HandlerThread or ThreadPool replacing them.

Use annotations instead of enumerations

Enumerations are often used as a means of value qualification, and enumerations are more reliable than simple constants conventions. The essence of the enumeration is then to create the object. The good news is that Android provides annotations that allow the value to be limited to compile time, thereby reducing the pressure at run time. the relevant annotations are intdef and Stringdef.

The following is an example of Intdef, which describes how to use the

The following declaration in a file

public class Appconstants {public
  static final int state_open = 0;
  public static final int state_close = 1;
  public static final int state_broken = 2;

  @IntDef ({state_open, state_close, State_broken}) public
  @interface doorstate {}
}

Then set the method for writing this

private void Setdoorstate (@AppConstants. doorstate int State) {
  //some code
}

Can only be used when calling STATE_OPEN a method, STATE_CLOSE and STATE_BROKEN . Using a different value causes the compilation of reminders and warnings.

Select Object Pool

There are many pools of concepts in Android, such as thread pooling, connection pooling. Including our very long use of the Handler.Message pool technology.

For example, we want to use handler to send messages, we can use them, and we can use them Message msg = new Message() Message msg = handler.obtainMessage() . Using a pool does not create new objects every time, but instead takes precedence over objects from the pool.

How to use object pooling requires some attention

1. Put the object back into the pool, notice the initialization of the object's data, prevent the presence of dirty data

2. Reasonable control of the pool growth, avoid too large, resulting in a lot of objects in idle state

Careful initialization of application

Android applications can support the opening of multiple processes. The usual practice is this.

<service android:name= ". NetworkService "
  android:process=": Network "
/>

Usually we do a lot of initialization in the application OnCreate method, but each process startup needs to execute to this onCreate method, and in order to avoid unnecessary initialization, it is recommended that the process (by judging the current process name) correspond to initialization.

 public class MyApplication extends application {private static final String LogTag = "Myappli

  Cation ";
    @Override public void OnCreate () {String currentprocessname = Getcurrentprocessname ();
    LOG.I (LogTag, "onCreate currentprocessname=" + currentprocessname);
    Super.oncreate (); if (Getpackagename (). Equals (Currentprocessname)) {//init for default process} else if (currentprocessname.ends With (": Network")) {//init for NETOWRK process}} private string Getcurrentprocessname () {string Curr
    Entprocessname = "";
    int pid = Android.os.Process.myPid ();
    Activitymanager manager = (Activitymanager) this.getsystemservice (Context.activity_service); For (Activitymanager.runningappprocessinfo processInfo:manager.getRunningAppProcesses ()) {if (Processinfo.pid = =
        PID) {currentprocessname = Processinfo.processname;
      Break
  } return currentprocessname; }
}

Summarize

Some of the above knowledge is about how to avoid creating redundant objects in Android. Welcome your comments and opinions and make progress together. I hope the contents of this article can help everyone.

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.