Android Development notes-image caching, gestures, and OOM Analysis,
The three themes of image caching, gestures, and OOM are put together because these three problems are often associated during Android application development. First, you must support operations such as gesture scaling, rotation, and translation to preview a large image. Second, the image needs to be cached locally to avoid frequent network access. Finally, the image (Bitmap) it is a large memory user in Android. When processing large images in high-definition mode, the system reports an OOM error because the memory usage is very high.
Fortunately, these three themes are common issues in Android development, and there are many general open source solutions for this. Therefore, this article mainly describes some third-party open source libraries used in the development process. The main content is as follows:
1. Comparison and use of Universal Image Loader, Picasso, Glide and Fresco
Universal Image Loader (UIL), Picasso, Glide, and Fresco are common third-party libraries for Image loading in Android, it mainly encapsulates methods such as memory cache, disk cache, network request cache, and thread pool, abstracts the image loading process, and largely avoids memory overflow caused by image loading, this improves image loading efficiency. Is the information I recently found from the github pages of various libraries:
The github address of each database is attached:
Universal Image Loader:Https://github.com/nostra13/Android-Universal-Image-Loader.git
Picasso:Https://github.com/square/picasso.git
Glide:Https://github.com/bumptech/glide.git
Fresco:Https://github.com/facebook/fresco.git
The basic usage of the four image cache libraries (HelloWorld) can be implemented through a code statement, as follows:
UIL:
ImageLoader.getInstance().displayImage(url, imageView);
Picasso:
Picasso.with(context).load(url).into(imageView);
Glide:
Glide.with(context).load(url).into(imageView);
Fresco:
simpleDraweeView.setImageURI(uri);
Careful friends can see that Picasso and Glide APIs are very similar. In fact, these four libraries share similar core concepts and can be abstracted into the following five modules:
After having mastered the core idea of implementing various open-source libraries, we will find that one thing software engineering has in common is to normalize and abstract processes to improve efficiency. Whether it is business efficiency or development efficiency, this may also be the core idea of software as a science.
ImageLoader design and advantages
The ImageLoader loading process is as follows. (You need to declare that the following three Flowcharts are from Trinea and respect the copyright of the original author)
Dependencies {compile 'com. bm. photoview: library: 1.3.6 '}
(You can also download the project and copy the Info. java and PhotoView. java files to your project. It is not recommended)-This method is applicable to Eclipse.
2. Add xml
<com.bm.library.PhotoView android:id="@+id/img" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerInside" android:src="@drawable/bitmap1" />
3. java code
PhotoView photoView = (PhotoView) findViewById (R. id. img); // enable the image zoom function photoView. enable (); // disable the image scaling function (disabled by default, which is the same as the normal ImageView. You must manually call enable () to enable the scaling function) photoView. disenable (); // obtain the image information Info = photoView. getInfo (); // the image that changes from the information of an image to the current image. It is used to zoom in after the image is clicked. For details, refer to the use of photoView in the demo. animaFrom (info); // changes from the current image to the given image information. It is used to zoom in the image and zoom in to the original position. For details, refer to the use of photoView in demo. animaTo (info, new Runnable () {@ Override public void run () {// animation completion listener}); // get the animation duration int d = PhotoView. getDefaultAnimaDuring ();
The basic principle of PhotoView implementation is that the scaled Matrix and gesture listener are used in the PhotoView inherited from ImageView.
public class PhotoView extends ImageView { …… private Matrix mBaseMatrix = new Matrix(); private Matrix mAnimaMatrix = new Matrix(); private Matrix mSynthesisMatrix = new Matrix(); private Matrix mTmpMatrix = new Matrix(); private RotateGestureDetector mRotateDetector; private GestureDetector mDetector; private ScaleGestureDetector mScaleDetector; private OnClickListener mClickListener; private ScaleType mScaleType; ……}
The implementation of PhotoView is basically the same as the above principle. We will not go into details here. The implementation of custom controls will be analyzed in detail in subsequent articles.
GestureImageView is described as follows:
1. Configured as View in layout. xml
Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:gesture-image="http://schemas.polites.com/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.polites.android.GestureImageView android:id="@+id/image" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/image" gesture-image:min-scale="0.1" gesture-image:max-scale="10.0" gesture-image:strict="false"/></LinearLayout>
2. Configured Programmatically
Code:
import com.polites.android.GestureImageView;import android.app.Activity;import android.os.Bundle;import android.view.ViewGroup;import android.widget.LinearLayout.LayoutParams;public class SampleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); GestureImageView view = new GestureImageView(this); view.setImageResource(R.drawable.image); view.setLayoutParams(params); ViewGroup layout = (ViewGroup) findViewById(R.id.layout); layout.addView(view); }}
The principle is basically the same as that of PhotoView.
Iii. OOM analysis tool-LeakCanary
LeakCanary introduction:
A memory leak detection library for Android and Java.
It can be seen that LeakCanary is mainly used to detect the leakage of various memory which cannot be GC.
LeakCanary address https://github.com/square/leakcanary.git
Demo address:
Https://github.com/liaohuqiu/leakcanary-demo.git)
A https://github.com/teffy/LeakcanarySample-Eclipse.git (Eclipse)
In the demo, The TextView in TestActivity is referenced by static variables, leading to memory leakage caused by unrecoverable variables.
LeakCanary is easy to use. First, add the dependency project:
dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3' }
Second, perform initialization in the onCreate () method of the application.
public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); }}
After these two steps, you can use them. LeakCanary. install (this) returns a pre-defined RefWatcher and enables ActivityRefWatcher to automatically monitor the Activity leaked after activity. onDestroy () is called. If you need to listen to fragment, register it in the onDestroy () method of fragment:
public abstract class BaseFragment extends Fragment { @Override public void onDestroy() { super.onDestroy(); RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity()); refWatcher.watch(this); }}
Of course, you need to monitor a variable and watch it directly.
RefWatcher refWatcher = {...};// We expect schrodingerCat to be gone soon (or not), let's watch it.refWatcher.watch(schrodingerCat);
Note that to use LeakCanary in eclipse, you must declare the heap occupation analysis and the displayed Service in the AndroidManifest file:
<service android:name="com.squareup.leakcanary.internal.HeapAnalyzerService" android:enabled="false" android:process=":leakcanary" /> <service android:name="com.squareup.leakcanary.DisplayLeakService" android:enabled="false" /> <activity android:name="com.squareup.leakcanary.internal.DisplayLeakActivity" android:enabled="false" android:icon="@drawable/leak_canary_icon" android:label="@string/leak_canary_display_activity_label" android:taskAffinity="com.squareup.leakcanary" android:theme="@style/leak_canary_LeakCanary.Base" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Note: HeapAnalyzerService uses the multi-process android: process = ": leakcanary ".
The above open-source tools are easy to use. For details, refer to its github address.
Iv. Summary of Some clutter
Common Causes of Memory leakage:
- Static object: Listener, broadcast, webview;
- This $0: thread, timer, Handler;
- System: TextLine, input method, audio
Back-to-Back memory:
Activity leakage may cause the Bitmap/DrawingCache referenced by the Activity to be released. full-disclosure recycling refers to trying to recycle the leaked Activity's resources. In onDestroy, resources such as images, backgrounds, DrawingCache, and listeners are recursively released from rootview.
How to Reduce the Runtime memory: