Unity3d我应该缓存AndroidJavaObject实例吗?

时间:2018-07-05 12:09:19

标签: c# unity3d

我正在为Unity3D游戏创建简单的Android插件,以显示吐司和本机弹出窗口。当我想从Java类中调用方法时,可以使用Unity文档中的AndroidJavaClass和AndroidJavaObject:

        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“将Java插件与Unity一起使用时的最佳做法”)建议使用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的实例?

感谢答案

1 个答案:

答案 0 :(得分:2)

这取决于用法。

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

如果必须在每个帧或大多数时间调用此方法,则应该使用using语句。每次在AndroidJavaClass语句中使用AndroidJavaObjectusing实例时,都会创建一个新实例,然后销毁它。这将导致垃圾收集器更频繁地发生,并且GC运行会导致游戏中出现打ic或暂时冻结,尤其是在移动设备(在这种情况下为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);
    }));
}