我正在为 Unity3D 游戏创建简单的 Android 插件来显示 toast 和 native 弹出窗口。当我想从 Java 类调用方法时,我使用 AndroidJavaClass 和 AndroidJavaObject,就像在 Unity 文档中一样:

        AndroidJavaObject bridge = new AndroidJavaObject(CLASS_NAME);
        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject act = jc.GetStatic<AndroidJavaObject>("currentActivity");
        act.Call("runOnUiThread", new AndroidJavaRunnable(() =>
        {
            bridge.CallStatic(methodName, args);
        }));

Unity 文档(https://docs.unity3d.com/Manual/AndroidJARPlugins.html“在 Unity 中使用 Java 插件时的最佳实践”)建议使用 using 语句,例如
using (AndroidJavaClass cls = new AndroidJavaClass("java.util.Locale")) {
    using(AndroidJavaObject locale = cls.CallStatic<AndroidJavaObject>("getDefault")) {
        Debug.Log("current lang = " + locale.Call<string>("getDisplayLanguage"));
    }
}

但表示这是“计算成本高的方法”。

问题:我是否应该缓存 AndroidJavaClass 和 AndroidJavaObject 的实例?

感谢您的回答

最佳答案

这取决于使用情况。

如果您需要调用一次或几次方法,请使用 using 语句,以便尽快销毁 AndroidJavaClassAndroidJavaObject 并释放内存。

如果你必须在每一帧或大部分时间调用这个方法,你应该使用 而不是 使用 using 语句。每次在 AndroidJavaClass 语句中使用它时,这将创建 AndroidJavaObjectusing 的新实例,然后销毁它。它会导致垃圾收集器更频繁地发生,并且 GC 运行会导致您的游戏出现打嗝或暂时卡住,尤其是在移动设备上(在这种情况下为 Android)。

例如,如果您的问题中的第一个代码示例需要在每一帧中调用,那么将它们缓存在 Start 函数中并在 Update 函数中使用它们。当场景重新加载或另一个新场景加载时,它会清理:

AndroidJavaObject bridge;
AndroidJavaClass jc;
AndroidJavaObject act;

//Cache
void Start()
{
    bridge = new AndroidJavaObject(CLASS_NAME);
    jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    act = jc.GetStatic<AndroidJavaObject>("currentActivity");
}

void Update()
{
    DoSomething();
}

void DoSomething()
{
    act.Call("runOnUiThread", new AndroidJavaRunnable(() =>
    {
        bridge.CallStatic(methodName, args);
    }));
}

关于c# - Unity3d 我应该缓存 AndroidJavaObject 实例吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51190972/

10-12 03:17