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