Stetho

什么是Stetho

Stetho是Facebook出的一款Android调试工具

我们可以用它在Chrome DevTools下查看应用的布局、网络请求、Sqlite、SharedPreference并能通过js来调试代码(使用js进行调试的时候FB只做了初步封装,使用起来会比较麻烦,需要自己进一步封装)

来点截图(取自官网

Chrome DevTools

Chrome DevTools

查看网络请求

Network Inspection

数据库(可读写)

Database Inspection

查看布局(双向查看)

  1. 用鼠标放在Element面板中的xml节点上,会在应用中高亮对应的布局
  2. 点击Element左边的放大镜,然后点击应用中的布局,会自动跳转到Element面板中的xml节点
    View Hierarchy

Javascript Console

Javascript Console

在代码中配置stetho

build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
android {
// 如果编译的时候出现OutOfMemory,添加以下配置
dexOptions {
incremental true
javaMaxHeapSize "4g"
}
buildTypes {
debug {
// 如果因为加了stetho导致DexIndexOverflowException,需要添加以下配置
multiDexEnabled true
}
}
}
dependencies {
// 只在debug版中加入stetho
debugCompile 'com.facebook.stetho:stetho:1.3.1'
debugCompile 'com.facebook.stetho:stetho-js-rhino:1.3.1'
//debugCompile 'com.facebook.stetho:stetho-urlconnection:1.3.1'
// 如果因为加了stetho导致DexIndexOverflowException,需要添加以下配置
debugCompile 'com.android.support:multidex:1.0.1'
}

YourApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 当前界面显示的Activity,供Console调用
private Activity mAct = null;
// 方便从Console中通过变量名获取mAct对象
public Activity getmAct() {
return mAct;
}
// 从java代码中获取、设置mAct
public Activity getCurrentActivity() {
return mAct;
}
public void setCurrentActivity(Activity act) {
this.mAct = act;
}
@Override
public void onCreate() {
super.onCreate();
DebugUtils.init(context);
//...
}

BaseActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*******************************************************
* 使用的Activity尽量继承自BaseActivity,以减少配置代码
*******************************************************/
// 可以在Console中通过context.mAct.getField()的方式获取私有变量的值
// 把获取的逻辑封装到DebugUtils中,以解除不必要的麻烦
public Object getField(String name) {
return DebugUtils.getActField(this, name);
}
// 取消引用
private void clearReferences() {
YourApplication app = ((YourApplication)getApplicationContext());
Activity currActivity = app.getCurrentActivity();
if(this.equals(currActivity)) {
app.setCurrentActivity(null);
}
}
@Override
protected void onResume() {
// ...
((YourApplication)getApplicationContext()).setCurrentActivity(this);
}
@Override
protected void onPause() {
clearReferences();
// ...
}
@Override
protected void onDestroy() {
clearReferences();
// ...
}

DebugUtils.java

因为不想把stetho添加到release中,所以需要通过gradle的buildType特性,对debug版和release版做不同处理

debug的配置

在src目录下添加debug/java目录,并在java目录中添加相应的package(比如,DebugUtils将添加到com.yourname.tools.util中,那么就在debug/java目录中新建com.yourname.tools.util包,并在util包下新建DebugUtils.java文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.yourname.tools.util;
import android.app.Activity;
import android.content.Context;
import android.support.multidex.MultiDex;
import com.facebook.stetho.Stetho;
import java.lang.reflect.Field;
/**
* Created by Nstd on 2016/3/14.
*/
public class DebugUtils {
public static void init(final Context context) {
// 如果因为加了stetho导致DexIndexOverflowException,需要添加以下配置
MultiDex.install(context);
// 以下是Stetho配置
Stetho.initialize(
Stetho.newInitializerBuilder(context)
.enableDumpapp(
Stetho.defaultDumperPluginsProvider(context))
.enableWebKitInspector(
Stetho.defaultInspectorModulesProvider(context))
.build());
}
// 通过反射获取activity中的私有变量
public static Object getActField(Activity activity, String fieldName) {
try {
Field f = activity.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(activity);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}

release的配置

在src目录下添加release/java目录,并在java目录中添加相应的package(文件名同上,但是里面的函数都是空实现)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.haizitong.minhang.Tool.util;
import android.content.Context;
/**
* Created by Nstd on 2016/3/14.
*/
public class DebugUtils {
public static void init(Context context) {
// release version: empty code
}
public static Object getActField(Activity activity, String fieldName) {
//release version: return null
return null;
}
}

其他buildType的配置(参照debug或release)

PS:网络配置

公司现在用的是HttpUrlConnection,Stetho配置这个的时候侵入性比较强,暂时也用不到,所以不做配置
如果需要HttpUrlConnection的配置,可以参看官网Demo的配置
如果用的是okhttp,可以参看官网的这个配置

编译运行应用

启动dev控制台

在Chrome的地址栏中输入:

1
chrome://inspect

启动以后,在页面上应该会出现对应的包名、应用名称,选择需要调试的应用,点击 inspect ,开始调试

PS:一直加载刷新不出来

如果启动后一直是加载状态,需要使用VPN翻墙,成功加载一次以后就不需要了

调试

Elements面板

  1. 可以查看当前Activity的布局;
  2. Elements显示的xml中,YourApplication是根节点,直属子节点是对应的Activity,如果跳转到新的Activity,新的Activity会堆叠到旧Activity之上,就像栈一样;
  3. 在Elements的xml节点上移动鼠标,会在手机屏幕上高亮显示对应的区域;
  4. 点击Elements旁边的放大镜(变成蓝色),然后点击屏幕,随后xml会自动定位到你点击的节点;
  5. 在Styles面板中可以看到布局元素的属性值.
  • bug?
    查看不了Dialog的布局信息

Resource面板

  1. Web SQL:中可以查看Sqlite的信息
    • 点击数据库名称,可以输入sql语句直接操作数据库
    • 点击表名,可以查看该表的所有数据
  2. Local Storage:中可以查看SharedPreferences的信息

Console面板

  1. context相当于Application对象
  2. 如果加入了之前的封装(DebugUtils等)
    • 通过context.mAct获得当前windows中的Activity
    • 通过context.mAct.公有属性名,可以获取mAct中public属性变量的值
    • 通过context.mAct.getField(fieldName)可以获取到这个Activity中的私有变量值(当然也可以获取public的)
  3. 如果获取的是一个对象,eg:context.mAct.mTvMessage(mTvMessage是个TextView),可能不能直接操作该对象的方法,需要使用importPackage(android.widget),引入该对象所在的包(将包内的所有java对象引入到jsRuntime中);或者使用importClass(android.widget.TextView),只引入TextView对象,此时才能使用context.mAct.mTvMessage.getText()方法

PS:其他

- 代码

前往GitHub

- Android Studio

如果觉得Android Studio卡,可以尝试修改Studio的配置,增加其使用的内存大小
window下:
studio安装目录\bin\sudio64.exe.vmoptions:

1
2
-Xmx4096m
-XX:MaxPermSize=1024m

参考

  1. 官网文档
  2. 官方Github-stetho
  3. 官方Github-stetho-js-rhino
  4. Scripting Java

热评文章