Android Best performance Practice (i)--manage memory properly

Source: Internet
Author: User

A lot of friends have asked me how to write high-performance applications, how to avoid the application of oom, or when the program memory consumption is too high, how to troubleshoot. Indeed, a good application, not only to perform well, performance issues should also be handled just right. So I read a lot of high-performance programming recommendations from Android, so from this article I'm going to start writing a whole new series of blog posts to sort out and analyze the recommendations to help you write better apps.

Note that the content of this series is basically rooted in Android docs, and if you want to read more detailed information about performance, you can read the official Android documentation directly.

Memory (RAM) is a very valuable resource for any software development environment, and for mobile operating systems, it will be more valuable, because the hardware of the mobile phone compared to the PC after all is relatively backward. While Android virtual machines have a mechanism to recycle garbage automatically, this does not mean that we can ignore when we should allocate and free memory.

In order for the garbage collector to free up the memory used by the program, it is important to avoid memory leaks when writing code (usually due to the fact that global member variables hold object references) and to release object references when appropriate. For most applications, the rest of the application can be left to the garbage collector to complete, and if an object's reference is no longer held by another object, the system will reclaim the memory allocated by the object.

We should take the memory problem into consideration when we develop the software, so that we can develop more high-performance software. And the memory problem is not irregular, the Android system gives us a lot of memory optimization tips, as long as these techniques to write programs, you can let our program in-store performance is very good, let's learn these techniques.

Use the service in moderation

If you need to use service to perform background tasks in your application, be sure to let the service run only when the task is executing. In addition, when the task is finished to stop the service, be careful of the service stop failure resulting in a memory leak.

When we start a service, the system tends to keep the process that the service relies on, which causes the process to become very memory-intensive. Also, the number of processes that the system can cache in the LRU cache is reduced, resulting in more performance when switching applications. Serious, it may even cause a crash, because the system may not be able to maintain the processes on which all running service depends when the memory is very tight.

To be able to control the service lifecycle, the best solution for Android is to use Intentservice, the most important feature of which is that it stops automatically when the background task executes. This avoids the possibility of service memory leaks to a great extent.

Keeping a service running in the background, even if it doesn't do any work, is one of the worst ways to write Android programs. So Android officials highly recommend that developers do not get too greedy and keep service running in the background, which not only may result in very low performance of mobile phones and programs, but also may cause our software to be uninstalled directly after being discovered by the user (I will do this personally).

Free memory when the interface is not visible

When the user opens another program and our program interface is no longer visible, we should release all resources that are related to the interface. Releasing resources in this scenario significantly increases the ability of the system to cache the background process, thus making the user experience even better.

So how do we know if the program interface is already invisible? In fact, it is very simple to rewrite the Ontrimmemory () method in the activity, and then in this method to listen to the level of Trim_memory_ui_hidden, once triggered, it means that the user has left our program, The resource release operation is now available, as follows:

123456789 @Overridepublicvoid onTrimMemory(int level) { super.onTrimMemory(level); switch (level) { caseTRIM_MEMORY_UI_HIDDEN: // 进行资源释放操作 break; }}

Note that the Trim_memory_ui_hidden callback in the Ontrimmemory () method is triggered only when all the UI components in our program are not visible, which is quite different from the OnStop () method, because OnStop () The method is only called when an activity is completely invisible, such as when the user opens another activity in our program. Therefore, we can release some activity-related resources in the OnStop () method, such as canceling the network connection or unregistering the broadcast receiver, but the UI-related resources should wait until ontrimmemory (Trim_memory_ui_hidden) This callback is then released, which ensures that if the user only returns from one activity of our program to another activity, the interface-related resources do not need to be reloaded, thereby increasing the response speed.

Freeing memory when memory is tight

In addition to the Trim_memory_ui_hidden this callback, the Ontrimmemory () method has many other types of callbacks that can be notified when the phone memory is lowered. We should decide how to release the resources of the application based on the level passed in the callback:

    • trim_memory_running_moderate indicates that the application is functioning properly and will not be killed. But now that the phone's memory is a bit low, the system may start to kill the process according to the LRU cache rules.

    • Trim_memory_running_low indicates that the application is functioning properly and will not be killed. But now that the phone's memory is very low, we should release some unnecessary resources to improve the performance of the system, and this will directly affect the performance of our application.

    • trim_memory_running_critical indicates that the application is still working, but the system has killed most of the cached processes according to the LRU cache rules. At this time we should try to release any unnecessary resources, otherwise the system may continue to kill all the processes in the cache, and start to kill some of the processes that should be kept running, such as services running in the background.

The above is the callback when our application is running, so if our program is currently cached, we will receive the following types of callbacks:

    • Trim_memory_background says the phone is currently low on memory and the system is ready to start cleaning up the process based on the LRU cache. This time our program in the LRU cache list of the nearest location, is not likely to be cleaned out, but then to release some of the more easily recovered resources can make the phone's memory more abundant, so that our program is kept in the cache for a longer time, so that when the user returned to our program will feel very smooth, Instead of going through a reboot process.

    • Trim_memory_moderate said the phone is currently low in memory, and our program is in the middle of the LRU cache list, if the phone memory is not further released, then our program has been killed by the system risk.

    • Trim_memory_complete said the phone is currently low in memory, and our program is at the very edge of the LRU cache list, the system will give the highest priority to kill our application, at this time should be as much as possible to release everything that can be released.

Avoid wasting memory on bitmap

When we read a bitmap picture, it is important to note that you should never load the unwanted resolution. Displaying a high-resolution image on a very small imageview does not bring any visual benefit, but it takes up quite a lot of our valuable memory. The only thing to remember is that the memory used to parse a picture into a bitmap object is not the size of the image on the hard disk, maybe a picture is only 100k you don't think it's big, but the memory is calculated by pixel points, for example, this picture is 1500*1000 pixels, Using the argb_8888 color type, then each pixel will occupy 4 bytes, the total memory is 1500*1000*4 bytes, that is, 5.7M, this data looks more scary.

As to how to compress pictures, as well as more memory-saving technology in the picture, we can refer to a blog I wrote earlier on Android high-efficiency loading large map, multi-figure solution, effectively avoid the program Oom .

Using the optimized data collection

The Android API provides a number of optimized data collection tool classes, such as Sparsearray,sparsebooleanarray, and Longsparsearray, which can be used to make our programs more efficient. The HashMap tool class provided in the traditional Java API is relatively inefficient because it requires an object entry for each key-value pair, and Sparsearray avoids the time when the base data type is converted to the object data type.

Know the cost of memory

We should also be aware of the memory expenditure and consumption of the language we use, and should take this information into account throughout the design and development of the software. There may be some seemingly innocuous wording, which results in a large portion of the memory outlay, such as:

    • Using enumerations is usually more than twice times more memory than using static constants, and in Android development we should try not to use enumerations as much as possible.

    • Any Java class, including internal classes, anonymous classes, consumes approximately 500 bytes of memory space.

    • An instance of any class consumes 12-16 bytes of memory overhead, so creating instances frequently can also affect memory on a program.

    • When using HashMap, even if you only set a key for a basic data type, such as int, it allocates memory according to the size of the object, which is about 32 bytes, not 4 bytes. So the best way to do this is to use an optimized set of data, as mentioned above.

Use abstract programming with caution

Many programmers like to use abstractions to program, thinking that this is a good programming habit. Of course, this is undeniable, because the abstract programming approach is more object-oriented and will improve the maintenance and extensibility of the code. However, using abstractions on Android brings additional memory overhead, because abstract programming methods require additional code that is not executed at all, but also mapped into memory, which not only takes up more memory, but also decreases execution efficiency. Of course, I'm not advocating that you don't use abstract programming at all, but use abstract programming with caution, and don't think of it as a cool way to use it and use it only when you think it's necessary.

Try to avoid using the dependency injection framework

Many people now like to use dependency injection frameworks in Android projects, such as Guice or roboguice, because they can simplify some complex coding operations, such as the following code:

123456789101112131415161718 class AndroidWay extends Activity { TextView name; ImageView thumbnail; LocationManager loc; Drawable icon; String myName; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); name = (TextView) findViewById(R.id.name); thumbnail = (ImageView) findViewById(R.id.thumbnail); loc = (LocationManager) getSystemService(Activity.LOCATION_SERVICE); icon = getResources().getDrawable(R.drawable.icon); myName = getString(R.string.app_name); name.setText( "Hello, " + myName ); }}

Simplify it into one of the following:

12345678910111213 @ContentView(R.layout.main)class RoboWay extends RoboActivity { @InjectView(R.id.name) TextView name; @InjectView(R.id.thumbnail) ImageView thumbnail; @InjectResource(R.drawable.icon) Drawable icon; @InjectResource(R.string.app_name) String myName; @Inject LocationManager loc; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); name.setText( "Hello, " + myName ); }}

It looks really tempting, and we can even omit all the tedious operations of Findviewbyid (). But these frameworks often need to go through a long initialization process to search for annotations in the code, and may also load objects that you can't use into memory. These objects will always occupy the memory space, it may take a long time before they will be released, compared to the number of lines of the seemingly cumbersome code is a better choice.

Simplifying code with Proguard

Proguard believe that everyone is not unfamiliar, many people will use this tool to confuse the code, but in addition to confusion, it also has the ability to compress and optimize the code. Proguard will retrieve our code, remove some useless code, and rename classes, fields, methods, and so on, and rename the classes, fields, and method names to be much shorter than they were originally, so that the memory footprint becomes less.

Using multiple processes

This technique is not really recommended, but it is really an advanced technique that can help us save and manage memory. If you want to use it, be sure to use it sparingly, because most applications should not run in more than one process, and if used improperly, it will even add extra memory instead of saving memory for us. This technique is more suitable for those who need to perform a separate task in the background, and the function of the foreground can be completely separated from the scene.

Here is a better way to use multi-process skills, such as we are working on a music player software, which plays the music function should be a separate function, it does not need to have any connection with the UI, even if the software is closed should be able to play the music properly. If we only use one process at this point, then even if the user shuts down the software and the service is completely controlling the music playback, the system will still retain many of the UI memory. This scenario is ideal for use with two processes, one for UI presentation and the other for continuous music playback in the background.

The ability to implement multi-process is also very simple, just need to declare a android:process attribute in the application component of the Androidmanifest file, for example, we want to play music service can run in a separate process, It can be written like this:

12 <service android:name=".PlaybackService" android:process=":background"/>

The process name specified here is background, and you can change it to any name you like. Note that a colon should precede the process name to indicate that the process is a private process for the current application.

http://mp.weixin.qq.com/s?__biz=MzA4NDM2MjAwNw==&mid=206397927&idx=1&sn= F58c2ea610588d49aa21c4f90613f6d6&scene=1#rd

Android Best performance Practice (i)--manage memory properly

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.