1. Android應(yīng)用啟動耗時
方法一 通過代碼
adb shell am start -W (包名)/(類全名)
//例如
adb shell am start -W com.guomin.pulse/com.guomin.pulse.mvp.ui.activity.SplashActivity
// TotalTime:就是啟動所需時間
方法二
在Android Studio Logcat中過濾關(guān)鍵字“Displayed”
2.debug關(guān)閉lldb方法
debug的時候如果開啟了NDK在啟動lldb的時候特別慢可以關(guān)閉掉蓬痒,方法如下
選擇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進行垃圾回收亲轨,被弱引用關(guān)聯(lián)的對象必定會被回收掉。不過要注意的是希柿,這里所說的被弱引用關(guān)聯(lián)的對象是指只有弱引用與之關(guān)聯(lián)养筒,如果存在強引用同時與之關(guān)聯(lián),則進行垃圾回收時也不會回收該對象(軟引用也是如此)晕粪。
弱引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對象被JVM回收装悲,這個弱引用就會被加入到與之關(guān)聯(lián)的引用隊列中尚氛。(內(nèi)存泄漏檢測LeakCanary 用到了這個)
WeakReference<Aa> weakReference1 = new WeakReference<>(new Aa());
System.gc();
//報錯空指針
weakReference1.get().print("weakReference1");
//不報錯可以輸出 weakReference2 因為aa還存在如果在 System.gc();之前aa=null那么就會空指針
Aa aa = new Aa();
WeakReference<Aa> weakReference2 = new WeakReference<>(aa);
System.gc();
weakReference2.get().print("weakReference2");
//不報錯可以輸出 weakReference3 和 aa3 因為存在aa2 和 aa3 強引用可以在gc之前手動設(shè)置為null就不會輸出了
WeakReference<Aa> 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 - 無線設(shè)置
adb tcpip 端口號 (adb tcpip 5555) - 連接設(shè)備
adb connect ip地址加端口(adb connect 192.168.10.1:5555) - 查看連接的設(shè)備
adb devices - 端口某個連接的設(shè)備
adb disconnect ip地址(adb disconnect 192.168.10.1)
6.MAT使用相關(guān)
mat轉(zhuǎn)換命令
//hprof-conv 原文件全名 需要生成的文件
hprof-conv 1.hprof 2.hprof
mat 查看內(nèi)存泄漏方法
點開Histogram属瓣,找到文件 選擇一個Class,右鍵選擇List objects > with incoming references
選擇一個對象抡蛙,右鍵選擇Path to GC Roots > ****粗截,通常在排查內(nèi)存泄漏的時候,我們會選擇exclude all phantom/weak/soft etc.references,
詳情如何使用MAT進行內(nèi)存泄露分析
7.Battery Historian使用
分析地址(https://bathist.ef.lc/)需要翻墻
命令
//1恢復(fù)初始化
adb shell dumpsys batterystats --reset
//2開始記錄
adb shell dumpsys batterystats --enable full-wake-history
//3收集
adb bugreport bugreport.zip
8.Android中圖片內(nèi)存計算規(guī)則
每個像素所占用的字節(jié)和圖片設(shè)置的格式有關(guān)绽榛,默認的是ARGB_8888
ARGB_8888 ---4字節(jié)
RGB_565 ---2字節(jié)
- 網(wǎng)絡(luò)加載的圖片
圖片寬度 X圖片高度 X每個像素所占用的字節(jié)數(shù) - res下的圖片
手機的density=(寬度2X高度2)然后開開根號 /尺寸
drawable對應(yīng)的density=密度值/160
縮放比例 scale = 當(dāng)前設(shè)備屏幕密度(density) / 圖片所在 drawable 目錄對應(yīng)屏幕密度(density)
Bitmap 實際大小 = 寬 * scale * 高 * scale * Config 對應(yīng)存儲像素數(shù)
9.導(dǎo)出ANR報錯日志
//adb命令如下
adb pull data/anr/traces.txt
//如果上述命令報錯蒜田,沒有權(quán)限的話改用命令
adb bugreport
10.File的listFiles返回null
解決方法
- targetSdkVersion<29需要動態(tài)申請權(quán)限
android.permission.READ_EXTERNAL_STORAGE冲粤,android.permission.WRITE_EXTERNAL_STORAGE
- targetSdkVersion>29
動態(tài)申請權(quán)限梯捕,并且File的地址不可以為公共地址
不能是這個
Environment.getExternalStorageDirectory()
可以是這個
getFilesDir()
11.adb命令跳轉(zhuǎn)頁面
//adb命令如下
adb shell am start -n 包名/類詳細地址
adb shell am start -n com.guomin.pulse/com.guomin.pulse.mvp.ui.activity.SplashActivity
12.Retrofit動態(tài)更換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<People> 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
15.android studio gradle查看SHA-256、SHA1碌奉、MD5
以此點擊如下,
然后輸入signingReport嫉拐,等待輸出即可
16.mac 配置vscode打開文件
function code {
if [[ $# = 0 ]]
then
open -a "Visual Studio Code"
else
local argPath="$1"
[[ $1 = /* ]] && argPath="$1" || argPath="$PWD/${1#./}"
open -a "Visual Studio Code" "$argPath"
fi
}
17.Retrofit的get請求@Path和@Query
如
@GET("/api/v1/view-record/{id}/detail")
Observable<BaseResponse<Object>> getIsCollect(@Path("id") long id,@Query("source_type") int source_type);
得到
/api/v1/view-record/8/detail?source_type=30
18.手動簽名報錯 Failure [-124: Failed parse during installPackageLI: Targeting R+ (version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary]
先進入 /Users/xxx/Library/Android/sdk/build-tools/30.0.3 路徑中
先刪除了客戶的v1簽名婉徘,即刪除 META-INF目錄(META-INF目錄下存放的是簽名信息,可能報找不到META-INF/* 盖呼,不重要)
zip -d source.apk META-INF/*
獲取4KB對齊apk(source_4.apk 是對齊后的結(jié)果文件)
zipalign -v 4 source.apk source_4.apk
查看是否結(jié)果文件是否對齊 (成功后會報:Verification succesful)
zipalign -c -v 4 source_4.apk
然后通過 apksigner 簽名化撕,不能在使用 jarsigner 簽名
apksigner sign --ks (簽名地址) --ks-key-alias (別名) --out (簽名后的apk地址) (待簽名apk地址)
19.Android設(shè)置scheme
頁面設(shè)置
<activity
android:name=".TestActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.lx.com"
android:path="/home"
android:port="1024"
android:scheme="qwer" />
</intent-filter>
</activity>
啟動設(shè)置
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("qwer://www.lx.com:1024/home"))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
網(wǎng)頁啟動
<a href="qwer://www.lx.com:1024/home?key1=value1&key2=value2">open app with Uri Scheme</a>
Activity取值
Intent intent = getIntent();
if (null != intent && null != intent.getData()) {
Uri uri = intent.getData();
Log.e(TAG, "uri=" +uri);
String scheme = uri.getScheme();
String host = uri.getHost();
int port = uri.getPort();
String path = uri.getPath();
String key1 = uri.getQueryParameter("key1");
String key2 = uri.getQueryParameter("key2");
Log.e(TAG, "scheme=" + scheme + ",host=" + host
+ ",port=" + port + ",path=" + path
+ ",query=" + uri.getQuery()
+ ",key1=" + key1 + "锌仅,key2=" + key2);
}
20 數(shù)據(jù)庫相關(guān)的
加入數(shù)據(jù)表 有 int a,int b, int c
那對應(yīng)的bean 只可以少于或者等于int a,int b,int c, 如果加上d就會報錯