bugreport查看 链接
// cpu占用
adb shell top -b -n 1 -H -s 6 -o pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name
# Android recyclerView滑动到底部,适用于短信、微信聊天内容界面
# When stack from bottom is set to true, the list fills its content starting from the bottom of the view.
LayoutManager#setStackFromEnd(true);
# gradle下载 超快
https://mirrors.cloud.tencent.com/gradle/
# 查看安装的app
adb shell pm list packages
# 查看service情况
adb shell dumpsys activity services -p com.xiaomi.aiasst.service
# 查看activity情况 任务栈(ActivityStackSupervisor)
adb shell dumpsys activity activities
# 查看内存情况 内存泄漏
adb shell dumpsys meminfo -p com.xiaomi.aiasst.service
# 查看wake lock
adb shell dumpsys power | grep WAKE
adb shell dumpsys power | grep PROXIMITY_SCREEN_OFF_WAKE_LOCK
// 透明状态栏和虚拟导航键
Window window = getWindow();
// 状态栏
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 虚拟导航键
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
# adb 启动应用,带参数的,参考 http://gityuan.com/2016/02/27/am-command/
adb shell am start -n com.xxx/.AppWeekActivity -a xx_action --ei KEY_xx 5
// 删除空元素
Collection nuCon = new Vector();
nuCon.add(null);
list.removeAll(nuCon);
// 判断是否为主线程
public static void assertUiThread() {
if (Thread.currentThread().getId() == Looper.getMainLooper().getThread().getId()) {
android.util.Log.v("assertUiThread", "assertUiThread");
new Throwable().printStackTrace();
}
}
Joiner.on(",").skipNulls().join(tags)));
Splitter.on(",").trimResults().split(tags))
# 查看文件修改记录
git log -p filename
@OnCheckedChanged(R.id.wifistatus)
void wifiChecked(CompoundButton buttonView, boolean isChecked) {
Logger.i(TAG, "wifiChecked() isChecked:%B", isChecked);
if (!buttonView.isPressed()) {
Logger.i(TAG, "wifiChecked() buttonView not pressed");
return;
}
// ...
}
/** 取数据先检查缓存的场景
取数据,首先检查内存是否有缓存
然后检查文件缓存中是否有
最后才从网络中取
前面任何一个条件满足,就不会执行后面的
*/
final Observable<String> memory = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
if (memoryCache != null) {
subscriber.onNext(memoryCache);
} else {
subscriber.onCompleted();
}
}
});
Observable<String> disk = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
String cachePref = rxPreferences.getString("cache").get();
if (!TextUtils.isEmpty(cachePref)) {
subscriber.onNext(cachePref);
} else {
subscriber.onCompleted();
}
}
});
Observable<String> network = Observable.just("network");
//主要就是靠concat operator来实现
Observable.concat(memory, disk, network)
.first()
.subscribeOn(Schedulers.newThread())
.subscribe(s -> {
memoryCache = "memory";
System.out.println("--------------subscribe: " + s);
});
/** 界面需要等到多个接口并发取完数据,再更新
*/
//拼接两个Observable的输出,不保证顺序,按照事件产生的顺序发送给订阅者
private void testMerge() {
Observable<String> observable1 = DemoUtils.createObservable1().subscribeOn(Schedulers.newThread());
Observable<String> observable2 = DemoUtils.createObservable2().subscribeOn(Schedulers.newThread());
Observable.merge(observable1, observable2)
.subscribeOn(Schedulers.newThread())
.subscribe(System.out::println);
}
/** 一个接口的请求依赖另一个API请求返回的数据
举个例子,我们经常在需要登陆之后,根据拿到的token去获取消息列表。
这里用RxJava主要解决嵌套回调的问题,有一个专有名词叫Callback hell
*/
NetworkService.getToken("username", "password")
.flatMap(s -> NetworkService.getMessage(s))
.subscribe(s -> {
System.out.println("message: " + s);
});
/** 界面按钮需要防止连续点击的情况
*/
RxView.clicks(findViewById(R.id.btn_throttle))
.throttleFirst(1, TimeUnit.SECONDS)
.subscribe(aVoid -> {
System.out.println("click");
});
/** 响应式的界面
比如勾选了某个checkbox,自动更新对应的preference
*/
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
RxSharedPreferences rxPreferences = RxSharedPreferences.create(preferences);
Preference<Boolean> checked = rxPreferences.getBoolean("checked", true);
CheckBox checkBox = (CheckBox) findViewById(R.id.cb_test);
RxCompoundButton.checkedChanges(checkBox)
.subscribe(checked.asAction());
/** 复杂的数据变换
*/
Observable.just("1", "2", "2", "3", "4", "5")
.map(Integer::parseInt)
.filter(s -> s > 1)
.distinct()
.take(3)
.reduce((integer, integer2) -> integer.intValue() + integer2.intValue())
.subscribe(System.out::println);//9
// powerful guava!
FluentIterable.from(groups).transform(new Function<String, CustomObject>() {
@Override
public CustomObject apply(String input) {
String[] split = Iterables.toArray(
Splitter.on(':').trimResults().omitEmptyStrings().split(input),
String.class);
if(split.length!=2) return null; // bad input data
String one = split[0];
String two = split[1];
return new CustomObject(one, two);
}
}).filter(notNull()).toImmutableList();
# adb 重新挂载某个目录为可写
mount -o remount, rw /system
# 对apk再次签名
jarsigner -verbose -keystore xxxxx.keystore -storepass xxxxx -signedjar xxxxed.apk xxxxxx.apk release
# 设置时间
adb shell date -s "yyyymmdd.[[[hh]mm]ss]"
# 如 adb shell date -s "20120801.120503"
# 可以不加引号
ping www.baidu.com -s 1024
trace route
mtr
arping
arp
telnet
host www.baidu.com
nslookup www.baidu.com
dig www.baidu.com
ab -c 100 -n 100 http:/www.baidu.com/
# 挂载服务器目录到本机
sudo mount -t nfs -o resvport,rw server_address:/some_dir /some_dir
# git 放弃本地修改 强制更新
git fetch --all
git reset --hard origin/master
# 获取Android屏幕适配信息
adb shell dumpsys window displays
# 查找大于100M的文件
find . -type f -size +1000000k