我正在尝试实现Chrome自定义标签并通过LeakCanary检测内存泄漏。

除非我们添加另一个Activity层,否则演示应用程序似乎不会泄漏(即MainActivity启动Activity2,它将绑定(bind)/取消绑定(bind)到自定义选项卡服务并启动url-MainActivitydemo app中所做的所有操作)。

MainActivity看起来像这样:

public class MainActivity extends Activity implements OnClickListener {
    private Button mLaunchButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LeakCanary.install(getApplication());

        setContentView(R.layout.main);

        mLaunchButton = (Button) findViewById(R.id.launch_button);
        mLaunchButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int viewId = v.getId();

        if (viewId == R.id.launch_button) {
            Intent intent = new Intent(getApplicationContext(), Activity2.class);
            startActivity(intent);
        }
    }
}

Activity2返回到MainActivity将导致此泄漏:
09-04 13:49:26.783  10456-12161/org.chromium.customtabsclient.example D/LeakCanary﹕ In org.chromium.customtabsclient.example:1.0:1.
09-04 13:49:26.783  10456-12161/org.chromium.customtabsclient.example D/LeakCanary﹕ * org.chromium.customtabsclient.Activity2 has leaked:
09-04 13:49:26.783  10456-12161/org.chromium.customtabsclient.example D/LeakCanary﹕ * GC ROOT android.support.customtabs.CustomTabsClient$1.val$callback (anonymous class extends android.support.customtabs.ICustomTabsCallback$Stub)
09-04 13:49:26.783  10456-12161/org.chromium.customtabsclient.example D/LeakCanary﹕ * references org.chromium.customtabsclient.Activity2$2.this$0 (anonymous class extends android.support.customtabs.CustomTabsCallback)
09-04 13:49:26.783  10456-12161/org.chromium.customtabsclient.example D/LeakCanary﹕ * leaks org.chromium.customtabsclient.Activity2 instance

https://gist.github.com/abvanpelt/ddbc732f31550b09fc27

我的问题是:这是演示应用程序中的错误吗? (也许unbindCustomTabsService()缺少一些需要的拆卸?)或者这是Chrome“自定义标签页”库本身中的错误?

谢谢你。

最佳答案

该示例中的MainActivity创建了一个CustomTabsServiceConnection和CustomTabsCallback实例作为匿名内部类。

如果将它们更改为静态内部类,则删除对MainActivity的this引用,并将对MainActivity的引用设置为WeakReferences,您将看到LeakCanary停止报告MainActivity泄漏。

现在,如果将其设置为监视该对象,则可能仍会看到有关ServiceConnection泄漏的泄漏黄雀色报告。原因是它已链接到Chrome服务,并且只有在GC也可以在服务器端运行时,GC才能清除它。

我创建了一个测试,该测试以循环方式绑定(bind)和取消绑定(bind)Service,并且我确认一段时间后确实会收集ServiceConnections。

因此,可以改进此演示,以避免ServiceConnection持有对MainActivity的引用,避免在断开服务后很长的时间使诸如Activity之类的重物存活,并且Custom Tabs库不是问题。

09-10 02:27
查看更多