├── .gitignore
├── Bitmap内存优化
├── README
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wangshuai
│ │ └── androidperformanceoptimation
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── wangshuai
│ │ │ └── androidperformanceoptimation
│ │ │ ├── Consumer.java
│ │ │ ├── MainActivity.java
│ │ │ ├── MyApp.java
│ │ │ ├── Person.java
│ │ │ ├── Producer.java
│ │ │ ├── ThreadTest.java
│ │ │ ├── bitmapoptimation
│ │ │ └── BitmapActivity.java
│ │ │ ├── memoryleakage
│ │ │ ├── CommonUtils.java
│ │ │ └── MemoryLeakageActivity.java
│ │ │ ├── network
│ │ │ └── NetWorkActivity.java
│ │ │ └── threadoptimation
│ │ │ └── ThreadTest1.java
│ └── res
│ │ ├── layout
│ │ ├── activity_bitmap.xml
│ │ ├── activity_main.xml
│ │ ├── activity_memory_leakage.xml
│ │ └── activity_net_work.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── wangshuai
│ └── androidperformanceoptimation
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── note
├── Java基本数据类型.txt
├── Java概述笔记.txt
├── android面试题.txt
├── 多线程.txt
├── 数据结构与算法.txt
├── 流与文件.txt
├── 网络编程.txt
├── 集合.txt
└── 面向对象.txt
├── settings.gradle
├── 内存泄漏笔记
├── 多线程优化
├── 安装包优化
├── 数据传输效率优化
└── 渲染机制以及优化
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/Bitmap内存优化:
--------------------------------------------------------------------------------
1 | #### 网络优化
2 |
3 | 1、请求缓存
4 |
5 | 三级缓存,外部缓存,LruCache,Sqlite缓存
6 |
7 |
8 | #### Bitmap优化
9 |
10 | 1)、图片压缩
11 |
12 | BitmapFactory Option参数:
13 |
14 | inDensity:bitmap的像素密度
15 |
16 | inTargetDensity:bitmap最终像素密度
17 |
18 | 质量压缩
19 |
20 | 尺寸压缩
21 |
22 | 采样率压缩
23 |
24 | #### 终极压缩方案
25 | 1、图像处理引擎
26 |
27 | android上使用的是skia引擎的阉割版(基于JPEG的图像引擎)
28 |
29 | 去掉了里面的一个算法--哈弗曼算法,采用定长编码算法,导致图片处理后的文件变大了
30 |
31 | 哈弗曼算法非常吃CPU,被迫使用了其他算法。但是解码还是保留了哈弗曼算法
32 |
33 | 2、实现方案
34 |
35 | 绕过安卓Bitmap API层,来自己实现编码,从而达到无损压缩数据的目的
36 |
37 | 用三位来表示一个字符信息,属于定长编码的最优
38 |
39 | 加权信息编码
40 |
41 | 哈弗曼编码:需要去扫描整个图片的信息(图片每一个像素包括ARGB),需要大量计算,非常耗CPU性能
42 |
43 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | ## android性能优化
2 | 1、内存泄漏
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "26.0.0"
6 | defaultConfig {
7 | applicationId "com.wangshuai.androidperformanceoptimation"
8 | minSdkVersion 15
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 |
28 | compile 'com.android.support:appcompat-v7:25.3.1'
29 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
30 | testCompile 'junit:junit:4.12'
31 | debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
32 | releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
33 | }
34 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\android-sdk-windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/wangshuai/androidperformanceoptimation/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.wangshuai.androidperformanceoptimation", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/Consumer.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation;
2 |
3 | /**
4 | * Created by 王帅 on 2017/12/14.
5 | */
6 |
7 | public class Consumer implements Runnable {
8 |
9 | Person person = null;
10 |
11 | public Consumer(Person person) {
12 | this.person = person;
13 | }
14 |
15 | @Override
16 | public void run() {
17 | while (true){
18 | // System.out.println(person.getName()+"------"+person.getSex());
19 | person.get();
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation;
2 |
3 | import android.content.Intent;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.support.v7.widget.AppCompatButton;
7 | import android.view.View;
8 |
9 | import com.wangshuai.androidperformanceoptimation.memoryleakage.MemoryLeakageActivity;
10 |
11 | public class MainActivity extends AppCompatActivity implements View.OnClickListener {
12 |
13 | private AppCompatButton btnMemoryLeakage;
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.activity_main);
19 |
20 | initViews();
21 | }
22 |
23 | private void initViews() {
24 | btnMemoryLeakage = (AppCompatButton) findViewById(R.id.btn_memory_leakage);
25 | btnMemoryLeakage.setOnClickListener(this);
26 | }
27 |
28 | @Override
29 | public void onClick(View v) {
30 | switch (v.getId()){
31 | case R.id.btn_memory_leakage:
32 | startActivity(new Intent(MainActivity.this, MemoryLeakageActivity.class));
33 | break;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/MyApp.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation;
2 |
3 | import android.app.Application;
4 |
5 | import com.squareup.leakcanary.LeakCanary;
6 | import com.squareup.leakcanary.RefWatcher;
7 |
8 | /**
9 | * Created by 王帅 on 2017/12/12.
10 | */
11 |
12 | public class MyApp extends Application {
13 |
14 | private RefWatcher refWatcher;
15 |
16 | @Override
17 | public void onCreate() {
18 | super.onCreate();
19 |
20 | if (LeakCanary.isInAnalyzerProcess(this)) {
21 | // This process is dedicated to LeakCanary for heap analysis.
22 | // You should not init your app in this process.
23 | return;
24 | }
25 | refWatcher = LeakCanary.install(this);
26 | }
27 |
28 | // public static RefWatcher getRefWatcher(){
29 | // return refWatcher;
30 | // }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/Person.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation;
2 |
3 | /**
4 | * Created by 王帅 on 2017/12/14.
5 | */
6 |
7 | public class Person {
8 | private String name;
9 | private String sex;
10 | private boolean bFull = false;//是否完成赋值
11 |
12 | public String getName() {
13 | return name;
14 | }
15 |
16 | public void setName(String name) {
17 | this.name = name;
18 | }
19 |
20 | public String getSex() {
21 | return sex;
22 | }
23 |
24 | public void setSex(String sex) {
25 | this.sex = sex;
26 | }
27 |
28 | public synchronized void set(String name,String sex){
29 |
30 | if (bFull){
31 | try {
32 | wait();
33 | } catch (InterruptedException e) {
34 | e.printStackTrace();
35 | }
36 | }
37 | this.name = name;
38 | try {
39 | Thread.sleep(10);
40 | } catch (InterruptedException e) {
41 | e.printStackTrace();
42 | }
43 | this.sex = sex;
44 | bFull = true;
45 | notify();
46 | }
47 |
48 | public synchronized void get(){
49 | if (!bFull){
50 | try {
51 | wait();
52 | } catch (InterruptedException e) {
53 | e.printStackTrace();
54 | }
55 | }
56 | System.out.println(this.name+"-------------"+this.sex);
57 | bFull = false;
58 | notify();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/Producer.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation;
2 |
3 | /**
4 | * Created by 王帅 on 2017/12/14.
5 | */
6 |
7 | public class Producer implements Runnable {
8 |
9 | Person person = null;
10 |
11 | public Producer(Person person) {
12 | this.person = person;
13 | }
14 |
15 | @Override
16 | public void run() {
17 | int i = 0;
18 | while (true){
19 | if (i == 0){
20 | // person.setName("张三");
21 | // person.setSex("男");
22 | person.set("张三","男");
23 | }else {
24 | // person.setName("小红");
25 | // person.setSex("女");
26 | person.set("小红","女");
27 | }
28 | i= (i+1)%2;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/ThreadTest.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation;
2 |
3 | /**
4 | * Created by 王帅 on 2017/12/14.
5 | */
6 |
7 | public class ThreadTest {
8 |
9 | public static void main(String[] srgs){
10 | Person person = new Person();
11 | new Thread(new Producer(person)).start();
12 | new Thread(new Consumer(person)).start();
13 | }
14 |
15 | static class MyThread implements Runnable{
16 |
17 | @Override
18 | public void run() {
19 | System.out.print("thread");
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/bitmapoptimation/BitmapActivity.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation.bitmapoptimation;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.Canvas;
6 | import android.graphics.RectF;
7 | import android.os.Environment;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.os.Bundle;
10 |
11 | import com.wangshuai.androidperformanceoptimation.R;
12 |
13 | import java.io.ByteArrayOutputStream;
14 | import java.io.File;
15 | import java.io.FileNotFoundException;
16 | import java.io.FileOutputStream;
17 | import java.io.IOException;
18 | import java.util.HashMap;
19 |
20 | public class BitmapActivity extends AppCompatActivity {
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_bitmap);
26 |
27 | }
28 |
29 | /**
30 | * 质量压缩:通过算法扣掉了图片中的一些某个些点附近相近的像素,达到降低质量文件大小的目的
31 | *
32 | * 他只能实现对file的影响,对加载这个图片出来的bitmap内存是无法节省的,还是那么大
33 | * 因为bitmap在内存中的大小是按照像素计算的,也就是width*height,对于质量压缩,并不会改变图片的真实的像素
34 | *
35 | * 使用场景:将图片压缩后保存到本地,或者将图片上传的服务器。
36 | */
37 | private void qualityCompress(){
38 | File imgFile = new File(Environment.getExternalStorageDirectory(),"img.png");
39 | BitmapFactory.Options options = new BitmapFactory.Options();
40 | Bitmap bitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(),options);
41 |
42 | compressImageToFile(bitmap,new File("","质量压缩.jpeg"));
43 | }
44 |
45 | /**
46 | * 尺寸压缩:
47 | * 通过减少单位尺寸的像素值,真正意义上降低像素
48 | * 使用场景:缓存缩略图,头像
49 | * @param bitmap
50 | * @param file
51 | */
52 | private void compressImageToFileBySize(Bitmap bitmap,File file){
53 | //压缩尺寸倍数:值越大,图片的尺寸就越小
54 | int ratio = 4;
55 | Bitmap result = Bitmap.createBitmap(bitmap.getWidth()/ratio,bitmap.getHeight()/ratio,Bitmap.Config.ARGB_8888);
56 |
57 | Canvas canvas = new Canvas(result);
58 | RectF rect = new RectF(0,0,bitmap.getWidth()/ratio,bitmap.getHeight()/ratio);
59 | canvas.drawBitmap(bitmap,null,rect,null);
60 |
61 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
62 | result.compress(Bitmap.CompressFormat.JPEG,100,baos);
63 |
64 | try {
65 | FileOutputStream outputStream = new FileOutputStream(file);
66 | outputStream.write(baos.toByteArray());
67 | outputStream.flush();
68 | outputStream.close();
69 |
70 | } catch (FileNotFoundException e) {
71 | e.printStackTrace();
72 | }catch (IOException e) {
73 | e.printStackTrace();
74 | }
75 |
76 | }
77 |
78 | /**
79 | * 采样率压缩:
80 | * 改变了图片的像素,他是通过先读取图片的边,然后在自己设定图片的边,然后根据设定,读取图片的像素。在读取的时候,并不是所有的像素都读取,
81 | * 而是由选择的。所以这种方式减少了像素的个数,能改变图片在内存中的占用大小。
82 | *
83 | * 采样率压缩,的的确确的改变了图片占用内存问题,但是由于像素改变,压缩容易造成失真问题。使用采样率压缩,不需要一开始把图片完全读取到内存,
84 | * 而是先读取图片的边,然后设置图片的尺寸,然后再根据尺寸,选择的读取像素。这种方法避免了一开始就吧图片读入内存而造成的oom异常。
85 | * @param filePath
86 | * @param file
87 | */
88 | private void compreseImageToFileBySamplingRate(String filePath,File file){
89 | //数值越高,图片像素越低,必须是2的倍数
90 | int inSampleSize = 8;
91 | BitmapFactory.Options options = new BitmapFactory.Options();
92 | options.inJustDecodeBounds = false;//true:不会真正加载图片,二十得到图片的宽高信息
93 | options.inSampleSize = inSampleSize;
94 | Bitmap bitmap = BitmapFactory.decodeFile(filePath,options);
95 |
96 | }
97 |
98 | private void compressImageToFile(Bitmap bitmap, File file) {
99 | int quality = 50;//0-100
100 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
101 | bitmap.compress(Bitmap.CompressFormat.JPEG,quality,baos);
102 | try {
103 | FileOutputStream outputStream = new FileOutputStream(file);
104 | try {
105 | outputStream.write(baos.toByteArray());
106 | outputStream.flush();
107 | outputStream.close();
108 | } catch (IOException e) {
109 | e.printStackTrace();
110 | }
111 |
112 | } catch (FileNotFoundException e) {
113 | e.printStackTrace();
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/memoryleakage/CommonUtils.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation.memoryleakage;
2 |
3 | import android.content.Context;
4 |
5 | import java.util.ArrayList;
6 |
7 | /**
8 | * Created by 王帅 on 2017/12/11.
9 | */
10 |
11 | public class CommonUtils {
12 | private Context context;
13 | private static CommonUtils instance;
14 |
15 | public CommonUtils(Context context) {
16 | this.context = context;
17 | }
18 |
19 | public static CommonUtils getInstance(Context context){
20 | if (instance == null){
21 | instance = new CommonUtils(context);
22 | }
23 |
24 | return instance;
25 | }
26 |
27 | /**
28 | * 正确用法:
29 | *
30 | * public CommonUtils(Context context){
31 | * this.context = context.getApplicationContext();
32 | * }
33 | * 保证context生命周期和Application的一样长
34 | */
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/memoryleakage/MemoryLeakageActivity.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation.memoryleakage;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 |
8 | import com.wangshuai.androidperformanceoptimation.R;
9 |
10 | import java.lang.ref.WeakReference;
11 |
12 | /**
13 | * 内存泄漏
14 | */
15 | public class MemoryLeakageActivity extends AppCompatActivity {
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_memory_leakage);
21 |
22 | CommonUtils commonUtils = CommonUtils.getInstance(this);//单例导致内存泄漏例子
23 |
24 | // loadData();
25 | //
26 | // mHandler.sendEmptyMessage(0);
27 |
28 |
29 | }
30 |
31 | /**
32 | * 错误写法(匿名内部类持外部引用造成内存泄漏问题)
33 | * 隐式持有Activity实例
34 | * 解决方案:将非静态内部类改为静态内部类(静态内部类不会隐式持有外部类)
35 | */
36 | int a = 0;
37 | public void loadData(){
38 | new Thread(new Runnable() {
39 | @Override
40 | public void run() {
41 | //进行操作
42 | int b = a;
43 | }
44 | }).start();
45 | }
46 |
47 | //匿名内部类的实例,也会引用外部对象MainActivity.this
48 | private Handler mHandler = new Handler(){
49 | @Override
50 | public void handleMessage(Message msg) {
51 | super.handleMessage(msg);
52 | //
53 | }
54 | };
55 |
56 | //解决方案2:改成静态类,集成Handler
57 | private static class MyHandler extends Handler{
58 | //如果需要持有一个外部类的强引用
59 | private WeakReference memoryReference;//设置软引用,当内存发生GC时候就会回收
60 |
61 | public MyHandler(MemoryLeakageActivity leakageActivity){
62 | this.memoryReference = new WeakReference(leakageActivity);
63 | }
64 |
65 | @Override
66 | public void handleMessage(Message msg) {
67 | super.handleMessage(msg);
68 | //
69 | MemoryLeakageActivity memoryLeakageActivity = memoryReference.get();
70 | if (memoryLeakageActivity == null || memoryLeakageActivity.isFinishing()){
71 | return;
72 | }
73 | switch (msg.what){
74 | case 0:
75 | break;
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/network/NetWorkActivity.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation.network;
2 |
3 | import android.net.http.HttpResponseCache;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 |
7 | import com.wangshuai.androidperformanceoptimation.R;
8 |
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.net.HttpURLConnection;
12 | import java.net.URL;
13 |
14 | public class NetWorkActivity extends AppCompatActivity {
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_net_work);
20 |
21 |
22 | }
23 |
24 | private void openCache(){
25 |
26 | try {
27 | //Android系统默认的HttpRe(网络请求相应缓存)是关闭的
28 | File cacheDir = new File(getCacheDir(),"http");
29 | long maxSize = 10*1024*1024;//缓存大小,单位byte
30 | HttpResponseCache.install(cacheDir,maxSize);
31 | } catch (IOException e) {
32 | e.printStackTrace();
33 | }
34 | }
35 |
36 | private void request(){
37 | new Thread(new Runnable() {
38 | @Override
39 | public void run() {
40 | try {
41 | HttpURLConnection connection = (HttpURLConnection) new URL("").openConnection();
42 | connection.setDoInput(true);
43 |
44 | } catch (IOException e) {
45 | e.printStackTrace();
46 | }
47 | }
48 | }).start();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wangshuai/androidperformanceoptimation/threadoptimation/ThreadTest1.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation.threadoptimation;
2 |
3 | import android.os.AsyncTask;
4 |
5 | import java.util.ArrayList;
6 | import java.util.concurrent.Callable;
7 | import java.util.concurrent.ExecutionException;
8 | import java.util.concurrent.ExecutorService;
9 | import java.util.concurrent.Executors;
10 | import java.util.concurrent.FutureTask;
11 |
12 | /**
13 | * Created by 王帅 on 2017/12/14.
14 | */
15 |
16 | public class ThreadTest1 {
17 |
18 | static class ProduceObject{
19 | private String value = "";
20 | }
21 |
22 | public static void main(String[] args){
23 | // Handler
24 | Task work = new Task();
25 | FutureTask futureTask = new FutureTask(work){
26 | @Override
27 | protected void done() {
28 |
29 | }
30 | };
31 | ExecutorService executorService = Executors.newCachedThreadPool();
32 | executorService.execute(futureTask);
33 |
34 | try {
35 | futureTask.get();
36 | } catch (InterruptedException e) {
37 | e.printStackTrace();
38 | } catch (ExecutionException e) {
39 | e.printStackTrace();
40 | }
41 | }
42 |
43 | static class Producer extends Thread{
44 | @Override
45 | public void run() {
46 | while (true){
47 |
48 | }
49 | }
50 | }
51 |
52 | static class Task implements Callable{
53 |
54 | @Override
55 | public Integer call() throws Exception {
56 | return null;
57 | }
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_bitmap.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_memory_leakage.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_net_work.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AndroidPerformanceOptimation
3 | 内存泄漏
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/wangshuai/androidperformanceoptimation/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.wangshuai.androidperformanceoptimation;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 11 11:14:39 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/note/Java基本数据类型.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/Java基本数据类型.txt
--------------------------------------------------------------------------------
/note/Java概述笔记.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/Java概述笔记.txt
--------------------------------------------------------------------------------
/note/android面试题.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/android面试题.txt
--------------------------------------------------------------------------------
/note/多线程.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/多线程.txt
--------------------------------------------------------------------------------
/note/数据结构与算法.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/数据结构与算法.txt
--------------------------------------------------------------------------------
/note/流与文件.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/流与文件.txt
--------------------------------------------------------------------------------
/note/网络编程.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/网络编程.txt
--------------------------------------------------------------------------------
/note/集合.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/集合.txt
--------------------------------------------------------------------------------
/note/面向对象.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ws614054446/AndroidPerformanceOptimation/5d6a8414ff2b419c33a465a075fc8370ff34ea2d/note/面向对象.txt
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/内存泄漏笔记:
--------------------------------------------------------------------------------
1 | #### 1、什么是内存泄漏
2 | 当一个对象已经不需要使用了,本该被回收时,但是另外一个使用的对象持有它的应引用,从而导致对象不能被回收。这种导致了本该被回收的对象不能被回收而停留在堆内存中,就叫内存泄漏。
3 | (GC只有在对象不再有任何的引用的时候才会进行回收)
4 |
5 | 内存溢出(OOM):当应用占用的heap资源超过了Dalvik虚拟机分配的内存就会内存溢出。
6 | 当内存泄漏过多的时候,再加上应用本身占用的内存,最终就会导致内存溢出。
7 | #### 2、内存分配的几种策略
8 | - 静态的:内存在程序编译的时候就已经分配好了。这块的内存在程序整个运行期间都一直存在。
9 |
10 | - 栈式的:在执行函数时,函数的一些内部变量的存储都可以放在栈上创建,函数执行结束的时候,
11 | 这些存储单元就会自动被释放掉。
12 |
13 | - 堆式的:也叫动态分配内存。如创建数组和对象。
14 |
15 | - 常量池:在编译期被确定,并被保存在已编译的.class文件中的一些数据。
16 |
17 | 栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的。
18 |
19 | #### 3、对象引用的四种级别
20 | - 强引用(StrongReference):GC绝不会回收它。当内存空间不足,JVM宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。
21 | - 软引用(SoftReference):如果内存空间足够,GC就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要GC没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
22 | - 弱引用(WeakReference):弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在GC扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
23 | - 虚引用(PhatomReference):虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用必须和引用队列(ReferenceQueue)联合使用。
24 |
25 | 开发时,为了防治内存溢出,处理一些比较占用内存大并且生命周期长的对象的时候,可以尽量使用软引用和弱引用。
26 |
27 | #### 使用MAT(Memory Analyzer Tool)
28 |
29 | [MAT下载地址](http://www.eclipse.org/mat/downloads.php)
30 |
31 | 查看内存泄漏的类,查看其被哪些类引用。
32 |
33 | #### 如何找到项目中存在的内存泄漏
34 | 1、确定是否存在内存泄漏
35 | 1)、Android Monitors分析内存
36 | 记录动作发生之前GC完的内存大小,然后记录动作发生之后GC完后的内存大小,两个比较大小,如果内存变大的话,则可能存在内存泄漏。
37 |
38 | 使用MAT内存分析工具
39 | MAT分析heap的总内存占用大小来初步判断是否存在内存泄漏
40 | Heap视图中有一个Type叫data object,即数据对象,也就是我们程序中大量存在的类型的对象。
41 | 在data object中有一项“Total Size”,其值就是当前进程中所有Java数据对象的内存总来过。
42 | 进行操作前和操作后的内存的大小比较。正常情况下Total Size值都会稳定在一个有限的范围内,
43 | 也就是没有内存泄漏。如果值不断增大,则可以初步判断这个操作导致了内存泄漏。
44 |
45 | 2、先找到怀疑对象(哪些对象属于泄漏的)
46 | MAT对比操作前后的hprof来定位内存泄漏了什么数据对象。(这样做可以排除一些对象,不用后面去查看所有被引用的对象是否有嫌疑)。
47 | 快速定位到操作前后所持有的对象哪些是增加了的(GC后还是比之前多出来的对象就可能是内存泄漏的源头)。
48 | 技巧:Histogram中还可以对对象进行Grpup By Package更方便查看自己包里的对象信息。
49 |
50 | 3、MAT分析hprof来定位内存泄漏的原因(哪个对象持有了上面怀疑出来的发生泄漏的对象)
51 |
52 | 1)Dump出内存泄露“当时”的内存镜像hprof,分析怀疑泄露的类;
53 |
54 | 2)把上面2得出的这些嫌疑犯一个一个排查个遍。
55 |
56 | 步骤:
57 | (1)进入Histogram,过滤出某一个嫌疑对象类
58 |
59 | (2)然后分析持有此类对象引用的外部对象(在该类上面点击右键List Objects--->with incoming references)
60 |
61 | (3)再过滤掉一些弱引用、软引用、虚引用,因为它们迟早可以被GC干掉不属于内存泄露
62 | (在类上面点击右键Merge Shortest Paths to GC Roots--->exclude all phantom/soft etc.references)
63 | (4)逐个分析每个对象的GC路径是否正常
64 |
65 | ###### 退出app后,GC后,产看系统进程里的所有的View和Activity对象是否为0,
66 | Android Monitors--System Information--Memory Usage查看
67 |
68 | #### 常见的内存泄漏
69 | 1、静态变量引起的内存泄漏
70 |
71 | 2、非静态内部类引起内存泄漏(包括匿名内部类)
72 | ```
73 | /**
74 | * 错误写法(匿名内部类持外部引用造成内存泄漏问题)
75 | * 隐式持有Activity实例
76 | * 解决方案:将非静态内部类改为静态内部类(静态内部类不会隐式持有外部类)
77 | */
78 | int a = 0;
79 | public void loadData(){
80 | new Thread(new Runnable() {
81 | @Override
82 | public void run() {
83 | //进行操作
84 | int b = a;
85 | }
86 | }).start();
87 | }
88 |
89 | //匿名内部类的实例,也会引用外部对象MainActivity.this
90 | //解决方案:改成静态的
91 | private Handler mHandler = new Handler(){
92 | @Override
93 | public void handleMessage(Message msg) {
94 | super.handleMessage(msg);
95 | //
96 | }
97 | };
98 |
99 | //解决方案2:改成静态类,集成Handler
100 | private static class MyHandler extends Handler{
101 | //如果需要持有一个外部类的强引用
102 |
103 |
104 |
105 | @Override
106 | public void handleMessage(Message msg) {
107 | super.handleMessage(msg);
108 | //
109 | }
110 | }
111 |
112 | ```
113 |
114 |
115 | 3、资源未关闭引起的内存泄漏情况:
116 |
117 | 比如:BroadCastReceiver,Cursor,Bitmap,IO流,自定义属性(attr.recycle)
118 |
119 | 4、无限循环
120 |
121 | 在onDestory中停止
122 |
123 | 5、WebView内存泄漏
124 | 解决办法是通过把使用了WebView的Activity(或者Service)放在单独的进程里。
125 | 然后在检测到应用占用内存过大有可能被系统干掉或者它所在的Activity(或者Service)结束后,
126 | 调用android.os.Process.killProcess(android.os.Process.myPid());,主动Kill掉进程。
127 | 由于系统的内存分配是以进程为准的,进程关闭后,系统会自动回收所有内存。
128 | ```
129 |
132 | ```
133 |
134 |
135 | #### 性能优化工具
136 |
137 | 常用的有:MAT,Memory Monitor,HeapTool,Allaction Tracking,LeakCanary,Lint工具
138 |
139 | 1、Allaction Tracking
140 |
141 | 追踪内存分配信息。可以直观地看到某个操作的内存是如何一步一步地分配的
142 |
143 |
144 | 2、LeakCanary
145 |
146 | [github地址](https://github.com/square/leakcanary)
147 |
148 | 可以直接在手机端查看内存泄漏的工具。
149 |
150 | 3、Lint工具
151 |
152 | 可以检测常见的内存泄漏
153 |
154 | 可以检测资源文件是否用到
155 |
156 | 可以检测代码规范
157 |
158 | 可以检测android版本安全问题
159 |
160 | 没用的导包
161 |
162 | 可能的bug
163 |
--------------------------------------------------------------------------------
/多线程优化:
--------------------------------------------------------------------------------
1 | volatile//线程操作变量可见
2 |
3 | #### AsyncTask源码分析
4 |
5 | public AsyncTask() {
6 | mWorker = new WorkerRunnable() {
7 | public Result call() throws Exception {
8 | mTaskInvoked.set(true);
9 | Result result = null;
10 | try {
11 | Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
12 | //noinspection unchecked
13 | result = doInBackground(mParams);
14 | Binder.flushPendingCommands();
15 | } catch (Throwable tr) {
16 | mCancelled.set(true);
17 | throw tr;
18 | } finally {
19 | postResult(result);
20 | }
21 | return result;
22 | }
23 | };
24 |
25 | mFuture = new FutureTask(mWorker) {
26 | @Override
27 | protected void done() {
28 | try {
29 | postResultIfNotInvoked(get());
30 | } catch (InterruptedException e) {
31 | android.util.Log.w(LOG_TAG, e);
32 | } catch (ExecutionException e) {
33 | throw new RuntimeException("An error occurred while executing doInBackground()",
34 | e.getCause());
35 | } catch (CancellationException e) {
36 | postResultIfNotInvoked(null);
37 | }
38 | }
39 | };
40 | }
41 |
42 |
43 | WorkerRunnable实现Callable,传给FutureTask;FutureTask由线程池执行这个异步任务。
44 |
45 | WorkerRunnable中call方法执行doInBackground()
46 |
47 | FutureTask中get()方法获取子线程中的返回值,等待异步任务执行完毕。
48 |
49 | 当子线程执行完毕之后,执行done()方法,通过Handler发送信息将返回值发送到主线程。
50 |
51 | 所有异步任务都是通过excute执行FutureTask;
52 |
53 | SerialExecutor implements Executor
54 |
55 | exec.execute(mFuture);
56 |
57 |
58 | FutureTask异步操作提供了便利性:
59 |
60 | 1、获取异步任务的返回值
61 |
62 | 2、监听异步任务的执行完毕
63 |
64 | 3、取消异步任务
65 |
66 | static {
67 | ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
68 | CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
69 | sPoolWorkQueue, sThreadFactory);
70 | threadPoolExecutor.allowCoreThreadTimeOut(true);
71 | THREAD_POOL_EXECUTOR = threadPoolExecutor;
72 | }
73 |
74 | CORE_POOL_SIZE:核心线程数
75 |
76 | MAXIMUM_POOL_SIZE:最大线程数
77 |
78 | KEEP_ALIVE_SECONDS:闲置回收
79 |
80 | TimeUnit.SECONDS:时间单位
81 |
82 | sPoolWorkQueue:异步任务队列
83 |
84 | sThreadFactory:线程工厂
85 |
86 | 添加到线程池是串行,添加到线程池后执行是并行;
87 |
88 | 1、线程池容量不够抛出异常;
89 | 2、内存泄漏;
90 | 3、
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/安装包优化:
--------------------------------------------------------------------------------
1 | #### 图片压缩
2 | 1、svg图片:一些图片的描述,牺牲CPU的计算能力,节省空间
3 |
4 | 使用原则:简单的图标
5 |
6 | 2、webp图片
7 |
8 | Google提倡使用,保存图片比较小。webp的无损压缩比PNG文件小45%左右
9 |
10 | 缺点:
11 |
12 | 相比加载PNG要慢很多,但是配置比较高。
13 |
14 | http://isparta.github.io/
15 |
16 |
17 | #### 资源动态加载
18 |
19 | 比如:表情,换肤;动态下载的资源;一些模块的插件化。
20 |
21 | #### Lint工具建议优化的点
22 |
23 | 检测没有用的布局,未使用到的布局等
24 |
25 |
26 | #### Proguard混淆
27 |
28 | 能删除注释和不用的代码;可以将Java文件名或者方法名改成短名
29 |
30 |
31 | #### 7zZip极限压缩
32 |
33 | 在常规的安装包优化之外继续压缩(资源文件再压缩)
34 |
35 | 实现将res/drawable/ic_lanchuer.png改成a.png
36 |
37 | drawable文件名字,string文件的名字。layout的名字
38 |
39 | 可以将res/drawable/ic_lanchuer.png改成r/d/a.png
40 |
41 | 解决方法:
42 |
43 | 读取resources.arsc二进制文件,然后修改某一段的字节
44 |
45 | 有一段叫做res/drawable/ic_lanchuer.png在自己的数组当中的第800位-810位
46 | 将这一段第800位-810位替换成r/d/a.png的字节码
--------------------------------------------------------------------------------
/数据传输效率优化:
--------------------------------------------------------------------------------
1 | #### 概述
2 | JSON是最常用的数据序列化技术。JSON的可读性很强,但是序列化和反序列化性能是最差
3 | 的。解析的时候,JSON解析器首先需要在内存中初始化一个对应的数据结构,解析的过程中,
4 | 要产生大量的临时变量,造成JAVA虚拟机的GC和内存抖动。
5 |
6 | #### FlatBuffers
7 | 基本原理:
8 |
9 | 把结构化的对象,用一个扁平化(Flat)的缓冲区,简单的来说就是把对象数据,
10 | 保存在一个一维数组中。FlatBuffers通过自己分配和管理对象的存储,使对象在内存中就是
11 | 线性结构化的,可以直接把内存内容保存或者发送出去。解析数据只需要把
12 | byte数组加载到内存中,不需要任何解析,也不产生任何中间变量。
13 |
14 | 优点:
15 |
16 | 1、直接读取序列化数据,不需要解析。
17 |
18 | 2、高效的内存使用和速度:不需要额外的内存,几乎接近原始数据在内存中的大小
19 |
20 | 3、灵活:数据能够向前后兼容,并且能够灵活控制你的数据结构
21 |
22 | 5、强类型,易于使用,跨平台,几乎与语言无关
23 |
24 | 缺点:
25 |
26 | 1、需要生成代码,对代码有侵入性
27 |
28 | 2、数据序列化没有可读性,不方便Debug;
29 |
30 | 3、构建FlatBuffers对象比较麻烦,不直观,特别是如果对象比较复杂的情况下需要写
31 | 大段的代码;
32 |
33 | 4、数据所有内容需要schema严格定义,灵活性不如JSON
--------------------------------------------------------------------------------
/渲染机制以及优化:
--------------------------------------------------------------------------------
1 | #### 卡顿是如何造成的
2 |
3 | 1、外部原因
4 |
5 | 在主线程里进行网络访问或者IO操作
6 |
7 | 2、View本身的卡顿
8 |
9 | 可以使用Allocation Tracing来定位大致的情况
10 | 然后可以使用TraceView来确定详细的问题所在
11 |
12 | #### 内存抖动
13 |
14 | 在短时间内分配大量内存并经行大量GC操作
15 |
16 | #### 渲染机制
17 |
18 | 屏幕理想帧率:60fps:每秒绘制帧数;
19 |
20 | 在60fps帧率下,每一秒只能停留16ms;
21 |
22 | VSYNC(垂直刷新/绘制):
23 | - Refresh Rate:屏幕在一秒内刷新屏幕的次数--由硬件参数决定,比如60Hz
24 | - Frame Rate:GPU一秒内绘制操作的帧数,如:60fps
25 |
26 | GPU刷新:GPU帮助我们将UI组件等计算成纹理Texture和三维图形Polygons,同时
27 | 会使用OpenGL--会将纹理和三维图形缓存在GPU内存里面
28 |
29 | 在渲染机制里比较耗时的操作:
30 |
31 | 1、cpu计算时间:
32 | 从减轻加工View对象成Polyons和Texture下手优化。很多无用的View不会显示在屏幕上面,
33 | 一旦触发测量和布局操作,就会拖累应用的性能表现。
34 |
35 | 2、CPU将计算好的Texture和Polygons传递到GPU
36 |
37 | OpenGL ES API允许数据到GPU后,可以对数据进行保存,做了缓存
38 |
39 | 3、GPU进行栅格化
40 |
41 | 渲染性能优化就是尽可能地上传数据到GPU,然后尽可能长地在不修改的情况下保存数据。
42 |
43 | #### 渲染优化
44 |
45 | 1、尽可能避免过度绘制
46 | - 背景经常造成过度绘制:
47 | 由于背景设置了颜色,同时又用到了MeterialDesign的主题会默认给一个背景(将主题添加的背景去掉)
48 | getWindow().setBackgroundDrawable(null)
49 | - 自定义控件如何处理过度绘制:
50 | 通过裁剪来处理
51 |
52 | - 布局优化:
53 |
54 | 1)、当我们的布局是用FrameLayout的时候,可以改成merge
55 |
56 | 可以避免自己的帧布局和系统的ContentFrameLayout布局重叠造成重复计算(measure和layout)
57 |
58 | 2)、
59 |
60 | #### Hierarchy View
61 |
62 | Android Device Monitor
63 |
64 | 可以查看页面布局层级以及查看每个布局的measure,layout,draw的时间。
65 | 三个原点分别代表测量,布局,绘制这三个阶段的性能表现:
66 |
67 | 1)、绿色:渲染的管道阶段,这个视图的渲染速度至少快于一半的其他视图
68 |
69 | 2)、黄色:渲染速度比较慢的50%
70 |
71 | 3)、红色:渲染速度非常慢
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------