1. Android应用启动耗时
方法一 通过代码
adb shell am start -W (包名)/(类全名)
//例如
adb shell am start -W com.guomin.pulse/com.guomin.pulse.mvp.ui.activity.SplashActivity
// TotalTime:就是启动所需时间
方法二
在Android Studio Logcat中过滤关键字“Displayed”
2.debug关闭lldb方法
debug的时候如果开启了NDK在启动lldb的时候特别慢可以关闭掉,方法如下
选择File->Settings->Plugins 然后找到 Android NDK Support把选项勾掉就可以了
3.Flutter配置好了但是NEW的时候没有Flutter选项
选择File->Settings->Plugins 然后找到 Android APK Support把选项选中,如果还是不行把Android NDK Support也选中
4.java引用类型之弱引用(WeakReference)
详细参考https://blog.csdn.net/linzhiqiang0316/article/details/88591907
只要JVM进行垃圾回收,被弱引用关联的对象必定会被回收掉。不过要注意的是,这里所说的被弱引用关联的对象是指只有弱引用与之关联,如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象(软引用也是如此)。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被JVM回收,这个弱引用就会被加入到与之关联的引用队列中。(内存泄漏检测LeakCanary 用到了这个)
WeakReference weakReference1 = new WeakReference<>(new Aa());
System.gc();
//报错空指针
weakReference1.get().print("weakReference1");
//不报错可以输出 weakReference2 因为aa还存在如果在 System.gc();之前aa=null那么就会空指针
Aa aa = new Aa();
WeakReference weakReference2 = new WeakReference<>(aa);
System.gc();
weakReference2.get().print("weakReference2");
//不报错可以输出 weakReference3 和 aa3 因为存在aa2 和 aa3 强引用可以在gc之前手动设置为null就不会输出了
WeakReference weakReference3 = new WeakReference<>(new Aa());
Aa aa2 = weakReference3.get();
aa2.print("weakReference3");
System.gc();
Aa aa3 = weakReference3.get();
aa3.print("aa3");
5. adb 常用命令
- 启动adb
adb start-server - 杀死adb
adb kill-server - 无线设置
adb tcpip 端口号 (adb tcpip 5555) - 连接设备
adb connect ip地址加端口(adb connect 192.168.10.1:5555) - 查看连接的设备
adb devices - 端口某个连接的设备
adb disconnect ip地址(adb disconnect 192.168.10.1)
6.MAT使用相关
mat转换命令
//hprof-conv 原文件全名 需要生成的文件
hprof-conv 1.hprof 2.hprof
mat 查看内存泄漏方法
点开Histogram,找到文件 选择一个Class,右键选择List objects > with incoming references
选择一个对象,右键选择Path to GC Roots > ****,通常在排查内存泄漏的时候,我们会选择exclude all phantom/weak/soft etc.references,
详情如何使用MAT进行内存泄露分析
7.Battery Historian使用
分析地址(https://bathist.ef.lc/)需要翻墙
命令
//1恢复初始化
adb shell dumpsys batterystats --reset
//2开始记录
adb shell dumpsys batterystats --enable full-wake-history
//3收集
adb bugreport bugreport.zip
8.Android中图片内存计算规则
每个像素所占用的字节和图片设置的格式有关,默认的是ARGB_8888
ARGB_8888 ---4字节
RGB_565 ---2字节
- 网络加载的图片
图片宽度 X图片高度 X每个像素所占用的字节数 - res下的图片
手机的density=(宽度2X高度2)然后开开根号 /尺寸
drawable对应的density=密度值/160
缩放比例 scale = 当前设备屏幕密度(density) / 图片所在 drawable 目录对应屏幕密度(density)
Bitmap 实际大小 = 宽 * scale * 高 * scale * Config 对应存储像素数
9.导出ANR报错日志
//adb命令如下
adb pull data/anr/traces.txt
//如果上述命令报错,没有权限的话改用命令
adb bugreport
10.File的listFiles返回null
解决方法
- targetSdkVersion<29需要动态申请权限
android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE
- targetSdkVersion>29
动态申请权限,并且File的地址不可以为公共地址
不能是这个
Environment.getExternalStorageDirectory()
可以是这个
getFilesDir()
11.adb命令跳转页面
//adb命令如下
adb shell am start -n 包名/类详细地址
adb shell am start -n com.guomin.pulse/com.guomin.pulse.mvp.ui.activity.SplashActivity
12.Retrofit动态更换baseurl
https://blog.csdn.net/really_study/article/details/94597466
13.反射常用方法
getMethods 获得父类和自己的所有的方法(包括私有和公开的)
getDeclaredMethods 获得自己的所有的方法(包括私有和公开的)
getFields 获得自己的和父类的public的属性
getDeclaredFields 获得自己的全部的属性
//对象
public class People {
public String sex;
private String name;
private People() {
this.name = "张三";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private void setName1(String name) {
this.name = name;
}
}
//运行如下代码
try {
//Class> aClass = Class.forName("com.example.myapplication.People");
Class aClass = People.class;
Constructor>[] declaredConstructors = aClass.getDeclaredConstructors();
AccessibleObject.setAccessible(declaredConstructors, true);
for (Constructor> declaredConstructor : declaredConstructors) {
if (declaredConstructor.isAccessible()){
Object o = declaredConstructor.newInstance();
Method setName = aClass.getDeclaredMethod("setName", String.class);
setName.invoke(o, "李四");
Method setName1 = aClass.getDeclaredMethod("setName1", String.class);
setName1.setAccessible(true);
setName1.invoke(o, "李四123");
Method getName = aClass.getDeclaredMethod("getName");
Object invoke = getName.invoke(o);
System.out.println(invoke.toString());
}
}
for (Method method : aClass.getMethods()) {
System.out.println("getMethods---->"+method.getName());
}
for (Method method : aClass.getDeclaredMethods()) {
System.out.println(method.getName());
}
for (Field declaredField : aClass.getFields()) {
System.out.println("getFields-->"+declaredField.getName());
}
for (Field declaredField : aClass.getDeclaredFields()) {
System.out.println("getDeclaredFields-->"+declaredField.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
//输入日志
李四123
getMethods---->getName
getMethods---->setName
getMethods---->wait
getMethods---->wait
getMethods---->wait
getMethods---->equals
getMethods---->toString
getMethods---->hashCode
getMethods---->getClass
getMethods---->notify
getMethods---->notifyAll
setName1
getName
setName
getFields-->sex
getDeclaredFields-->sex
getDeclaredFields-->name
14.Flutter 报错 Waiting for another flutter command to release the startup lock...
输入以下命令到终端解决
killall -9 dart