Android如何处理多个实例数据/身份和JNI

Jan*_*röm 9 java java-native-interface android

这是一个良好实践和智能解决方案的问题,我需要一个建议.

我有一个应用程序(据我在Stackoverflow和Google搜索中可以阅读):

  • 该应用程序处理文档类型,我喜欢同时处理多个文档.(我习惯于Win32,其中有一个程序段和每个实例的一段数据,但在Android/Java中显然不是这样.)
  • 我看到一个实例从应用程序存储(平板电脑)启动应用程序,另一个打开带有附加文档文件的Gmail或电子邮件,第三个实例是通过从文件处理应用程序(如ES文件浏览器)打开文件.我喜欢他们都可以在两者之间翻转.用户可能希望一次读取多个文档.(如果我在Android/Java环境中使用错误的单词实例,请更正我)
  • 该应用程序内置于JNI部分,其中包含所有数据和逻辑以及Java Android用户界面.(JNI部分设​​计为独立于OS,用于不同操作系统中的实现,具有粘合c文件.)
  • 每次翻转屏幕或翻转实例时,Android部分都会重新创建
  • 只有一个JNI实例,即使重新创建Android Java部件并且所有Java数据都被清除,它仍然保留,现在它显示了在所有情况下翻转的最后一个读取文件推送正在运行的app按钮
  • 在JNI部分中创建不同的实例没有问题,只要可以将它们绑定到每个Java实例,使用身份或我可以用作与JNI部分交换的参数的东西,但是如何
  • 我无法在每个实例中保存FilePathName以识别Java部分中的实例,因为在重新创建Java部分时将擦除它.

第一个问题是,如果我在阅读Stackoverflow和Googled文章的观察中是对的吗?

第二个问题,解决问题的任何好建议?我需要一个建议

  • 只要它还活着,是否有可能在所有情况下识别实例?
  • 任何其他可能的路径,既包括为每个实例分隔数据的一般问题,也包括识别JNI处理每个实例的数据的实例?

Ars*_*nov 5

一月

我们的应用程序中的JNI对象存在类似的问题.问题是JNI链接不能像普通的Java对象一样工作,必须明确地解决.与此同时,我们的活动可以随时被Android销毁.

我们当前的解决方案是在应用程序级别存储JNI对象,并且只要引用为零,就可以管理引用和删除对象.如果活动将永远被破坏,也会破坏JNI参考.所以这就像你在上一篇文章中所做的那样.

但是,如果您希望在一段时间后使应用程序可扩展,您可能会理解此解决方案并不理想.

Android系统有时会临时破坏活动以节省内存.在您的情况下,所有带文档的JNI对象仍将消耗内存.所以这里最好的解决方案是能够将JNI级别的文档保存到捆绑包中.如果用户可以更改您的文档,这一点尤为重要.在这种情况下,通过在onSaveInstanceState中保存JNI对象的状态,您可以销毁您的JNI对象并在onCreate中重新创建.然而,重要的是分析破坏/创建JNI对象与保存到捆绑文档所需的时间,因为我们必须在某些情况下(例如纵向/横向模式)快速支持活动重建,并使用一些有限的捆绑(不超过1Mb) ).如果进程很长,这个解决方案可能不太好.另外,您希望有一个任务 - 一个文档系统.当您在一个任务中有多个活动时,您应该考虑这种情况.

Android没有调用onDestroy()的第二项.如果你做了一些保存操作,这里的数据有时会丢失.

希望这些信息可以帮助您.

  • 让我们看一下Android文档:_当您的活动收到对onStop()方法的调用时,它不再可见,并且应该释放几乎所有在用户不使用时不需要的资源.一旦您的活动停止,系统可能会在需要恢复系统内存时销毁该实例.在极端情况下,系统可能只是在不调用活动的最终onDestroy()回调的情况下杀死您的应用程序进程,因此使用onStop()释放可能泄漏内存的资源非常重要._ (2认同)

Jan*_*röm 3

我做了一些工作,但我不知道这是否是一个好的做法?

我从 JNI 获取 int-instance-tag 并通过以下方式将其标记在意图上

public void onCreate(Bundle savedInstanceState) {
....
if (savedInstanceState == null) {
    // Creating the JNI task and get the JNI task ID 
    int iInstance = initProgram(...);
    // and store the JNI task ID in the intent
    getIntent().putExtra(Intent.EXTRA_TEXT, iInstance);
    ...
} 
    ...

public void onResume() {
    super.onResume();
    if (JniManagement.resumeInstance(iTask)) {
    ...

public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState); 
    // Restore state members from saved instance 
    iTask =
      savedInstanceState.getInt(AndroidApp.STATE_TASK_ID); 
}
Run Code Online (Sandbox Code Playgroud)

然后我们讨论任务的生命周期,用户使用主页按钮在窗口/任务之间翻转/翻转。问题是如何将JNI数据与Java的任务同步。

再次出现在 if (savedInstanceState == null) { 的 else 部分中,我们从 Intent 中获取 JNI 任务 ID,并将 JNI 任务与其同步。

onDestroy() 和 if(isFinishing()) 释放 JNI 中的实例内存集。

@Override
public void onDestroy() {
    super.onDestroy();  // Always call the superclass
    if(isFinishing())
        Commands.destroyInstance(getIntent().getExtras().getInt(Intent.EXTRA_TEXT, 0));
    // Extinguishing the JNI task started during onCreate()
}
Run Code Online (Sandbox Code Playgroud)

JNI 端

在 JNI 端,实例使用的所有内存都将放在一个结构中。可以在指针数组中指向该结构,以获得正确实例整数的正确数据集。当创建新实例时,指针数组会被重新分配,并且只要有内存留给新实例,指针数组就可以继续分配。

这实际上非常好,总是将正确的数据发送到正确的活动/实例。使用文件管理器应用程序通过调用工作数据文件来启动一个又一个活动,将会有一堆活动/实例。当用户离开时,结束按钮被一一剥落,其记忆被真正平滑地消灭。在 Gmail 中打开文件也可以以同样的方式正常工作,但是通过活动按钮显示为不同的活动。

作为一个旧的 Win32 C-fox,我喜欢我的指针并将它们设置在所有方法/函数中,这感觉有点笨拙(仅处理活动窗口屏幕数据)。但 Android 操作系统没有活动的重叠窗口。

因此,仅以这种方式将 JNI 同步到正确的 Java 活动/实例就可以非常顺利地工作。

但这是好的做法吗?还有其他流畅且美观的解决方案吗?