IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 内存泄露检测工具:Matrix ResourceCanary 使用 -> 正文阅读

[移动开发]内存泄露检测工具:Matrix ResourceCanary 使用

简介

Resource Canary主要是用来检测Activit级别的内存泄漏、以及重复创建的冗余Bitmap。

地址

使用

1. 项目依赖

  • 在项目根目录下的 gradle.properties中配置要依赖的Matrix版本号
MATRIX_VERSION=2.0.5
  • 在项目根目录下的build.gradle文件添加Matrix依赖
dependencies {
      classpath ("com.tencent.matrix:matrix-gradle-plugin:${MATRIX_VERSION}") { changing = true }
}
  • 在 app/build.gradle 文件中添加 Matrix 各模块的依赖
apply plugin: 'com.tencent.matrix-plugin'

dependencies {
    implementation group: "com.tencent.matrix", name: "matrix-android-lib", version: MATRIX_VERSION, changing: true
    implementation group: "com.tencent.matrix", name: "matrix-android-commons", version: MATRIX_VERSION, changing: true
    implementation group: "com.tencent.matrix", name: "matrix-resource-canary-android", version: MATRIX_VERSION, changing: true
    implementation group: "com.tencent.matrix", name: "matrix-resource-canary-common", version: MATRIX_VERSION, changing: true
}

2. 必要代码 (参考 Matrix中sample-android示例代码)

  • 实现PluginListener,接收Matrix处理后的数据(参考TestPluginListener)
public class PluginListener extends DefaultPluginListener {
    public static final String TAG = "Matrix.PluginListener";
    public SoftReference<Context> softReference;
    private final Handler mHandler = new Handler(Looper.getMainLooper());
    public PluginListener(Context context) {
        super(context);
        softReference = new SoftReference<>(context);
    }

    @Override
    public void onReportIssue(Issue issue) {
        super.onReportIssue(issue);
        MatrixLog.e(TAG, issue.toString());
    }
    
}

Matrix 项目本身是没有可视化页面,onReportIssue()方法会输出解析后数据。

  • 实现动态配置接口,可修改Matrix内部参数(参考DynamicConfigImplDemo类)
public class DynamicConfigImpl implements IDynamicConfig {
    private static final String TAG = "Matrix.DynamicConfigImplDemo";

    public DynamicConfigImpl() {

    }

   
    public boolean isMatrixEnable() {
        return true;
    }

    public boolean isDumpHprof() {  
        return true;
    }
    
    @Override
    public String get(String key, String defStr) {
        //TODO here return default value which is inside sdk, you can change it as you wish. matrix-sdk-key in class MatrixEnum.

        // for Activity leak detect
        if ((ExptEnum.clicfg_matrix_resource_detect_interval_millis.name().equals(key) || ExptEnum.clicfg_matrix_resource_detect_interval_millis_bg.name().equals(key))) {
            Log.d("DynamicConfig", "Matrix.ActivityRefWatcher: clicfg_matrix_resource_detect_interval_millis 10s");
            return String.valueOf(TimeUnit.SECONDS.toMillis(5));
        }

        if (ExptEnum.clicfg_matrix_resource_max_detect_times.name().equals(key)) {
            Log.d("DynamicConfig", "Matrix.ActivityRefWatcher: clicfg_matrix_resource_max_detect_times 5");
            return String.valueOf(3);
        }

        return defStr;
    }


    @Override
    public int get(String key, int defInt) {
        //TODO here return default value which is inside sdk, you can change it as you wish. matrix-sdk-key in class MatrixEnum.

        if (MatrixEnum.clicfg_matrix_resource_max_detect_times.name().equals(key)) {
            MatrixLog.i(TAG, "key:" + key + ", before change:" + defInt + ", after change, value:" + 2);
            return 2;//new value
        }

        if (MatrixEnum.clicfg_matrix_trace_fps_report_threshold.name().equals(key)) {
            return 10000;
        }

        if (MatrixEnum.clicfg_matrix_trace_fps_time_slice.name().equals(key)) {
            return 12000;
        }

        return defInt;

    }

    @Override
    public long get(String key, long defLong) {
        //TODO here return default value which is inside sdk, you can change it as you wish. matrix-sdk-key in class MatrixEnum.
        if (MatrixEnum.clicfg_matrix_trace_fps_report_threshold.name().equals(key)) {
            return 10000L;
        }

        if (MatrixEnum.clicfg_matrix_resource_detect_interval_millis.name().equals(key)) {
            MatrixLog.i(TAG, key + ", before change:" + defLong + ", after change, value:" + 2000);
            return 2000;
        }

        return defLong;
    }


    @Override
    public boolean get(String key, boolean defBool) {
        //TODO here return default value which is inside sdk, you can change it as you wish. matrix-sdk-key in class MatrixEnum.

        return defBool;
    }

    @Override
    public float get(String key, float defFloat) {
        //TODO here return default value which is inside sdk, you can change it as you wish. matrix-sdk-key in class MatrixEnum.

        return defFloat;
    }

}

  • 在Application的继承类中,对Matrix进行初始化(参考MatrixApplication)
public class MyApplication extends Application {
    
     @Override
    public void onCreate() {
        super.onCreate();
        
        // Switch.
        DynamicConfigImpl dynamicConfig = new DynamicConfigImpl();
        
        Matrix.Builder builder = new Matrix.Builder(this);
        
        ResourcePlugin resourcePlugin = configureResourcePlugin(dynamicConfig);
        builder.plugin(resourcePlugin);
        
        Matrix.init(builder.build());
        
        resourcePlugin.start();
    }
    
    private ResourcePlugin configureResourcePlugin(DynamicConfigImplDemo dynamicConfig) {
        Intent intent = new Intent();
        ResourceConfig.DumpMode mode = ResourceConfig.DumpMode.MANUAL_DUMP;
        MatrixLog.i(TAG, "Dump Activity Leak Mode=%s", mode);
        intent.setClassName(this.getPackageName(), "应用包名.ManualDumpActivity");
        ResourceConfig resourceConfig = new ResourceConfig.Builder()
                .dynamicConfig(dynamicConfig)
                .setAutoDumpHprofMode(mode)
                .setManualDumpTargetActivity(ManualDumpActivity.class.getName())
                .setManufacture(Build.MANUFACTURER)
                .build();
        ResourcePlugin.activityLeakFixer(this);

        return new ResourcePlugin(resourceConfig);
    }
}
  • 创建ManualDumpActivity,显示泄露Activity相关信息
public class ManualDumpActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manual_dump);

        TextView leak_activity=findViewById(R.id.leak_activity);
        leak_activity.setText("泄漏的Activity:"+getIntent().getStringExtra(SharePluginInfo.ISSUE_ACTIVITY_NAME));

        TextView leak_process=findViewById(R.id.leak_process);
        leak_process.setText("泄漏的进程:"+getIntent().getStringExtra(SharePluginInfo.ISSUE_LEAK_PROCESS));


        TextView reference_chain=findViewById(R.id.reference_chain);
        ManualDumpProcessor.ManualDumpData data =
                getIntent().getParcelableExtra(SharePluginInfo.ISSUE_DUMP_DATA);
        if (data!=null){
            reference_chain.setText("泄漏的堆栈:"+data.refChain);
        }
    }
}

至此,ResourceCanary就已成功集成到你的项目中,并且开始收集和分析性能相关异常数据。

检测内存泄漏场景

以Handler 内存泄漏为例,Handler的Message被存储在MessageQueue中,有些Message并不能马上处理掉,它们在MessageQueue中存在的时间会很长,这就会导致Handler无法被回收。如果Handler是非静态的,则Handler 也会导致引用它的Activity 或者Service 不能被回收。

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.acttivity_test_resource_trace);

        Button btn=findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mHandler.sendMessageDelayed(Message.obtain(),60000);
                finish();
            }
        });
    }


    Handler mHandler=new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    };

检测效果:
在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 15:53:47  更:2022-05-01 15:54:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 23:48:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码