Chrome自定义标签中检测到内存泄漏

All*_*son 12 android memory-leaks google-chrome chrome-custom-tabs

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

演示应用程序不会出现泄漏,除非我们添加另一个活动层(即MainActivity发射Activity2,结合/解除绑定到自定义选项卡服务并启动URL -一切MainActivity确实在演示应用程序).

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

从返回Activity2MainActivity将导致此泄漏:

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
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢.

Man*_*sha 5

找到了这个问题的答案-

如果您按照以下方式启动customTab

private void launchChromeCustomTab(final Context context, final Uri uri) {

     mServiceConnection = new CustomTabsServiceConnection() {
        @Override
        public void onCustomTabsServiceConnected(ComponentName componentName, CustomTabsClient client) {
            client.warmup(0L);
            final CustomTabsIntent intent = new CustomTabsIntent.Builder().build();
            intent.launchUrl(context, uri);
            mIsCustomTabsLaunched = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };
    CustomTabsClient.bindCustomTabsService(context, "com.android.chrome", mServiceConnection);
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要将此mServiceConnection onDestroy方法解除绑定为-

@Override
protected void onDestroy() {
    super.onDestroy();
    this.unbindService(mServiceConnection);
    mServiceConnection = null;
}
Run Code Online (Sandbox Code Playgroud)

那将停止扔

android.app.ServiceConnectionLeaked: Activity <Your_Activity> has leaked ServiceConnection 
Run Code Online (Sandbox Code Playgroud)

  • 理想情况下,您希望在 onCreate 或 onStart 上连接到 CustomTabs 服务,以便在打开选项卡之前 Chrome 在后台旋转。当选项卡打开时,launchChromeCustomTab 上的实现似乎会连接到服务。这可能会抵消连接到服务的好处,并且会产生与仅创建 Intent 并直接调用 launchUrl 类似的结果。 (3认同)

and*_*ban 1

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

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

现在,如果您将其设置为监视该对象,您仍然可能会看到有关 ServiceConnection 泄漏的泄漏金丝雀报告。原因是它链接到Chrome服务,无法被GC清理,直到GC也运行在服务器端。

我创建了一个在循环中绑定和取消绑定服务的测试,并且我已经确认 ServiceConnections 确实在一段时间后被收集。

所以,可以对Demo进行改进,以避免ServiceConnection持有对MainActivity的引用,避免像Activity这样的重对象在服务断开后长时间存活,而这对于Custom Tabs库来说不是问题。