【问题标题】:Android stop onPause from being called in parent classAndroid停止在父类中调用onPause
【发布时间】:2016-08-17 02:51:56
【问题描述】:

在我的应用程序中,我有一个子类,它扩展了 leanback 支持库中名为 SearchFragment支持库 类。我需要扩展这个类,但不幸的是父类 (SearchFragment) 的 onPause() 有一个我无法使用的方法。

每次我离开活动时,父类都会运行onPause(),它会调用我不想要的方法。

有没有办法可以扩展 SearchFragment 类但不允许它运行自己的 onPause()

这是我无法更改的父类中的onPause() 方法。

android.support.v17.leanback.app.SearchFragment

@Override
public void onPause() {
    releaseRecognizer(); //Need to stop this from calling
    super.onPause();
}

private void releaseRecognizer() {
    if (null != mSpeechRecognizer) {
        mSearchBar.setSpeechRecognizer(null);
        mSpeechRecognizer.destroy();
        mSpeechRecognizer = null;
    }
}

另外,我这样做的原因是因为这是一个 Android TV > Fire TV 端口。 Fire TV 没有语音识别器。

【问题讨论】:

  • 您可以在fragment 中覆盖onPause() 方法,而不是在其中调用super.onPause()。该方法不会传播到父类。

标签: java android android-fragments amazon-fire-tv


【解决方案1】:

使用 Proguard assumenosideeffects 选项来消除 SearchFragment 中对 releaseRecognizer() 方法的调用。这将要求您在启用 Proguard 的情况下编译您的代码,但由于相关代码是在某些特定场景中调用的,您可能只在发布版本中使用 Proguard。

请注意,您必须启用优化(dontoptimize 选项不得设置),因为通过 assumenosideeffects 剥离对方法的调用在技术上是一种“优化”。

确保使用 this answer 中的建议将 Proguard 操作限制为您要“优化”的特定类(在您的情况下,为 android.support.v17.leanback.app.SearchFragment)。


这是在不修改 SearchFragment 源代码的情况下解决您的问题的唯一方法。再三考虑,您最好简单地将必要的类复制到您的项目中,或者在最坏的情况下——将整个leanback支持库作为 Gradle 子模块插入并直接修改必要的方法(很有可能,Fire TV 存在其他问题)除了这个)。

【讨论】:

  • 多么痛苦。不幸的是,一旦复制一个类,我就必须复制另一个类,然后再复制一个......
  • @osiris355 我理解你的痛苦,但有时候吃蛋糕是不可能的……另一方面,你总是可以选择遵循that answer中的建议并跟进拦截@ 987654326@s 到处都是。您必须决定是否需要短期“轻松”(捕获异常,使用反射黑客)、可维护性(fork leanback 库)或两者之一的幻觉(基本上任何其他选项,包括此答案中概述的 Proguard 选项)。
【解决方案2】:

onPause 是活动生命周期的一部分,不容忽视,但你可以做一些技巧来做到这一点。它要求您修改 releaseRecognizer() 方法的行为。

代码可以改成如下:

boolean isReleased;

public void releaseRecognizer() {
   if(isReleased) {
      return;
   }
   ...
   //your code go here
   ...
   isReleased = true;
}

//Somewhere else where you acquire the recognizer again you just set it to false:

public void acquireRecognizer(){

   ...
   isReleased = false
}

这样可以确保releaseRecognizer 不会运行代码两次。

【讨论】:

  • 如果 releaseRecognizer 类是私有的怎么办?
  • SearchFragment 类包含 onPause 和 releaseRecognizer 方法,不能修改。这是一个锁定的谷歌图书馆。我只能延长它。
  • 我建议修改 releaseRecognizer 行为。顺便说一句,通过查看您更新的代码,多次调用 releaseRecognizer() 有什么问题?
  • FireTV 在 android tv 等应用程序中不支持语音识别,所以它失败了
  • 我不是 FireTV 方面的专家,但我认为您可以在活动的 onCreate 方法中找到这一点,并设置一个可在整个程序中使用的全局参数,以防止不相关的代码运行跨度>
【解决方案3】:

由于onPause() 在具有public 可访问性的父类SearchFragment 的方法之一中,您可以简单地在子类中覆盖它而不调用super.onPause()。这不会将该方法传播到父类,因此臭名昭著的releaseRecognizer() 不会被调用。

但是,您需要注意实现与SearchFragment 的其他生命周期方法正确绑定的业务逻辑,以免系统资源被滥用。因此,您需要根据您的用例逻辑修改覆盖的代码,以便最终调用onPause()

【讨论】:

  • 当然我现在得到.... SuperNotCalledException: Fragment SearchFragment{86aa5eb #0 id=0x7f10009c} 没有调用 super.onPause()
  • 我明白为什么 google 把它绑起来了,但它也是非常令人沮丧的 amazon 不允许这样做。他们有一个麦克风按钮,但选择不允许开发人员使用它
  • 这可能是个愚蠢的问题,但我不能扩展和扩展类来避免这种情况吗?
  • @osiris355 是的,不会那样工作。但是,如果库是开源的,我们可以尝试修改源代码作为更极端的措施之一。
【解决方案4】:

正如android documents 中提到的,在onpause() 中释放系统资源是一种很好的做法。
我认为您应该在onResume() 中再次获取它。作为

@Override
public void onResume() {
super.onResume();
acquireRecognizer();
}

@Override
public void onPause() {
super.onPause();
releaseRecognizer();
}

或者也许您应该在onStop()onDestroy() 中发布识别器。通过这种方式,它将保留识别器,直到活动处于活动状态。

@Override
protected void onStop() {
super.onStop();
releaseRecognizer();
}

【讨论】:

  • 正如我的问题中提到的,我无法触摸识别器。如果我对识别器做任何事情,它就会失败。亚马逊 FireTV 没有语音识别器。
  • 哎呀!您无法修改 onPause()releaseRecognizer()。我想你应该禁用识别器,
  • 说起来容易做起来难。我什至看不到这样做的全球方式。
  • 很好的发现,但我没有得到任何尝试。它说无论我在哪里使用该代码块,都有一个字段未找到异常。
【解决方案5】:

在我看来,您可以按照其他答案中的建议覆盖 SearchFragment onPause,但是通过删除 super.onPause() 您将面临一些问题。因此,一种安全的解决方案是编写您自己的 SearchFragment 类(复制该类中的所有代码并创建您自己的类) 现在在此类中删除您不想在 onPause() 方法中调用的方法。通过这种方式,您不会删除超级呼叫,因此这种方法将是安全的。

【讨论】:

  • 不幸的是,它并不那么简单,因为 SearchFragment 类调用了来自leanback 支持库的方法,而谷歌在我复制的片段中的 mRowsFragment.getVerticalGridView() 的任何地方都会抛出该错误
  • 基本上该方法在 BaseRowFragment 中是最终的,所以我不能从我的项目中调用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多