Android 的 StrictMode 的生命周期是多少?

发布于 2024-10-12 21:49:28 字数 1809 浏览 2 评论 0原文

我正在尝试最大程度地减少代码中需要设置 StrictMode 的位置数量。但我不确定以下内容是否正确。

Android 的 StrictMode 文档表示您可以将其用于应用程序、活动和其他组件。我读到,扩展 Application 类是不可取的,并且我不希望仅仅为了启用 StrictMode 而扩展 Application 类。但我不认为我必须这样做。

您可以使用两种策略:ThreadPolicy(针对线程)和 VmPolicy(针对所有线程)。因此,如果我在一个线程上设置 StrictMode 一次,那么从哪里执行此操作并不重要,并且无论其他调用是否在 StrictMode 上,此后都会在该线程上报告违规行为。我只需要在发生我想要检测的违规行为之前从某个地方调用它即可。并且需要为我也想检查的应用程序中创建的任何新线程进行设置。

我认为我想要避免的是调用 build() 方法超过我需要的次数。在我的所有活动中将 StrictMode 放在 onCreate() 的开头意味着 build() 将在该线程上被多次调用。如果我的应用程序中有一个 Launcher 活动,则在该活动的 onCreate() 中设置 StrictMode 对于应用程序的其余部分来说应该足够了。这是真的吗?

其次,如果我的主要活动重新启动,即使应用程序没有终止,技术上是否有必要再次调用 StrictMode?或者我的线程是否仍设置为报告违规行为?我认为围绕 StrictMode 做一个包装类型的类可能会有一些价值,如下所示:

public class MyStrictModeSettings {
    static private List<Long> setThreads = new ArrayList<Long>();

    // Prevent instantiation of this class
    private MyStrictModeSettings() {}

    static public synchronized void init() {
        try {
            Long tid = Thread.currentThread().getId();
            if(!setThreads.contains(tid)) {
                setThreads.add(tid);
                Class sMode = Class.forName("android.os.StrictMode");
                Method enableDefaults = sMode.getMethod("enableDefaults");
                enableDefaults.invoke(null);
            }
        }
        catch(Exception e) {
            // StrictMode not supported on this device, punt
            Log.v("StrictMode", "... not supported. Skipping...");
        }
    }
}

这样,在我的主要活动的 onCreate() 中,我可以简单地调用 MyStrictModeSettings.init() 并完成它。它也应该适用于 2.3 之前的 Android 版本。但这可能不值得。布拉德,你在吗?谢谢。

编辑:由于 VmPolicy 适用于所有线程,从技术上讲,我只需要为每个应用程序设置一次,对吧?那么,当第二次、第三次等调用时,enableDefaults() 会浪费精力重做 VmPolicy 吗?同样,尝试避免额外的调用可能会带来更多麻烦,而不是值得的。

I'm trying to minimize the number of places in my code where I need to setup StrictMode. But I'm not sure if I'm right or not about the following.

The documentation for Android's StrictMode says you can use it for Applications, Activities and other components. I've read that it is not desirable to extend the Application class, and I'd prefer not to extend Application just to enable StrictMode. But I don't think I have to.

There are two policies you can use: ThreadPolicy (for a thread) and VmPolicy (for all threads). So it would seem that if I setup StrictMode on a thread once, it doesn't matter from where I do that, and violations will be reported thereafter on that thread regardless of other calls or not on StrictMode. I just need to call it from somewhere before violations could occur that I want to detect. And it needs to be setup for any new threads that get created in my application that I also want to check.

What I think I want to avoid is calling the build() methods more than I need to. Putting StrictMode at the beginning of onCreate() in all my activities means that build() is going to get called more than once on that thread. If I have one Launcher activity in my application, setting up StrictMode in that activity's onCreate() should be sufficient for the rest of the application. Is that true?

Secondly, if my main activity gets restarted even though the application did not die, is it technically necessary to call StrictMode again? Or is my thread still setup to report violations? I was thinking there might be some value in doing a wrapper-type of class around StrictMode like so:

public class MyStrictModeSettings {
    static private List<Long> setThreads = new ArrayList<Long>();

    // Prevent instantiation of this class
    private MyStrictModeSettings() {}

    static public synchronized void init() {
        try {
            Long tid = Thread.currentThread().getId();
            if(!setThreads.contains(tid)) {
                setThreads.add(tid);
                Class sMode = Class.forName("android.os.StrictMode");
                Method enableDefaults = sMode.getMethod("enableDefaults");
                enableDefaults.invoke(null);
            }
        }
        catch(Exception e) {
            // StrictMode not supported on this device, punt
            Log.v("StrictMode", "... not supported. Skipping...");
        }
    }
}

That way, in my main activity's onCreate(), I can simply call MyStrictModeSettings.init() and be done with it. And it should work on Android versions prior to 2.3 too. But it may not be worth it. Brad, are you there? Thanks.

Edit: Since VmPolicy is for all threads, technically I only need to set that up once per application, right? So enableDefaults() is wasting effort to redo the VmPolicy when it gets called a second, third, etc time? Again, maybe it's more trouble than it's worth to try to avoid the extra calls.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

慈悲佛祖 2024-10-19 21:49:28

是的,VmPolicy 是针对整个过程的,所以执行一次就可以了。不过,更多次数很便宜,所以不用担心。

是的,您只需要在主/启动器活动的 onCreate() 中执行此操作 - 这是与所有其他组件相同的“主”线程。

Yes, VmPolicy is for the whole process so doing it once is fine. More times is cheap, though, so don't wory about it.

And yes, you only need to do it in your main/launcher activity's onCreate() --- that's the same "main" thread as all your other components.

久光 2024-10-19 21:49:28

查看源代码,您可以看到它是静态调用的:

public static void setVmPolicy(final VmPolicy policy) {
    synchronized (StrictMode.class) {
        sVmPolicy = policy;
        sVmPolicyMask = policy.mask;
        setCloseGuardEnabled(vmClosableObjectLeaksEnabled());

        Looper looper = Looper.getMainLooper();
        if (looper != null) {
            MessageQueue mq = looper.mQueue;
            if (policy.classInstanceLimit.size() == 0 ||
                (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
                mq.removeIdleHandler(sProcessIdleHandler);
                sIsIdlerRegistered = false;
            } else if (!sIsIdlerRegistered) {
                mq.addIdleHandler(sProcessIdleHandler);
                sIsIdlerRegistered = true;
            }
        }
    }
}

并且策略本身也是静态存储的 - 类中没有非静态成员变量。

    private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;

这意味着您只需为每个应用程序执行一次,例如在应用程序的启动/进入活动中。

Looking at the source code, you can see that it is being called statically:

public static void setVmPolicy(final VmPolicy policy) {
    synchronized (StrictMode.class) {
        sVmPolicy = policy;
        sVmPolicyMask = policy.mask;
        setCloseGuardEnabled(vmClosableObjectLeaksEnabled());

        Looper looper = Looper.getMainLooper();
        if (looper != null) {
            MessageQueue mq = looper.mQueue;
            if (policy.classInstanceLimit.size() == 0 ||
                (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
                mq.removeIdleHandler(sProcessIdleHandler);
                sIsIdlerRegistered = false;
            } else if (!sIsIdlerRegistered) {
                mq.addIdleHandler(sProcessIdleHandler);
                sIsIdlerRegistered = true;
            }
        }
    }
}

And the policy itself is also stored statically - there are no non-static member variables in the class.

    private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;

This means you only need to do it once per application such as in the launch/entry activity for your application.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文