Unity3d我应该缓存AndroidJavaObject实例吗?

3

我正在为Unity3D游戏创建一个简单的Android插件,以显示消息和原生弹窗。当我想要从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);
        }));

单位文档推荐使用“using”语句,如https://docs.unity3d.com/Manual/AndroidJARPlugins.html中所述的最佳实践:在Unity中使用Java插件。请注意保留HTML标记。
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的实例?

感谢您的回答。

1个回答

7

这取决于使用情况。

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

如果您必须每帧或大部分时间调用此方法,则不应使用using语句。这将在using语句中每次使用时创建AndroidJavaClassAndroidJavaObject的新实例,然后销毁它。这会导致垃圾回收器更频繁地运行,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);
    }));
}

谢谢回答。我也是这么想的。我会将问题标记为已解决。 - G_B
@程序员 有没有办法手动释放AndroidJavaObject? - Ayyappa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接