如何正确处理已废弃的Fragment事件onAttach和onInflate?

10

我已经阅读了一些文章和答案(包括这篇),涉及到废弃的代码,但我有些困惑如何处理(具体来说)被弃用的 Fragment 事件处理程序 onInflate

我已经替换了我的实现

public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState)

与,用

public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState)

如果我在小于API23的设备上运行我的应用程序,则不会调用替换代码。

如果我恢复原始已弃用的代码(这样我现在有两种实现方法),则调用已弃用的代码,正确的功能返回,但是现在正在调用已弃用的方法(?)。

当我在API23的设备上运行应用程序时,似乎两个处理程序版本都被调用。

那么问题是,这里发生了什么?如果我编写的代码旨在在API23和更早版本上运行,那么我需要实现已弃用的方法以及新方法吗?

如果是这种情况,我是否需要寻找并实施其他“已弃用”的方法,以防万一?(因此,是否有这些“向后兼容”所需的弃用方法列表?)


更新:

我现在已经从使用android.app.Fragment更改为android.support.v4.app.Fragment(即从本机片段到支持片段),应用程序现在按预期执行,所有版本都运行替换处理程序代码,并且正在按预期遍历android源。

但问题仍然存在:为什么?本机android.app.Fragment 实现出了问题吗?回顾早期的问题,这个问题在2015年9月就被讨论了。所以为什么这仍然是一个问题?为什么应API 11后支持和本地片段的实现会有差异?


感谢将“depreciated”更正为“deprecated”。我从未意识到自己如此的词汇错乱! :) - Simon Hutton
1个回答

4
不,你不应该实现。
public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState)

当一个方法被弃用时,你可以(通常)安全地使用替代函数。请检查Fragment中onInflate的定义:

public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
        mCalled = true;
        final Activity hostActivity = mHost == null ? null : mHost.getActivity();
        if (hostActivity != null) {
            mCalled = false;
            onInflate(hostActivity, attrs, savedInstanceState);
        }
    }

 @Deprecated
    public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
        mCalled = true;
    }

正如您所看到的,onInflate(Context context...)onInflate(Activity activity...)的扩展,并且向后兼容。在覆盖该方法时调用super.onInflate(context, attrs, savedInstanceState);,您可以安全地假设它将在API23和早期版本上工作。

如果我在低于API23的机器上运行我的应用程序,则不会调用替换代码。

这似乎很奇怪,我无法重现它,在非v23的机器上使用类似以下代码的日志记录:

@Override 
public void onInflate(Context context, AttributeSet attrs,
                                    Bundle savedInstanceState) {
        super.onInflate(context, attrs, savedInstanceState);
        Log.w(TAG, "I'm being executed");
    }

请确保:

  1. 您导入的是支持版本的Fragment,android.support.v4.app.Fragment而不是android.app.Fragment,并且使用getSupportFragmentManager()而不是getFragmentManager()
  2. 您在build.gradle中拥有最新的support-v4appcompat-v7库以及compileSdkVersion 23

当我在API23机器上运行应用程序时,似乎同时调用了两个版本的处理程序。

这可以通过onInflate(Context context...)代码来解释,如果它由Activity调用,则调用onInflate(Activity activity...)

编辑

关于更新:

android.app.Fragment的本地实现不应向后兼容。由于这个事实,android.app.Fragment的代码通常比android.support.v4.app.Fragment简单得多。

此外,本地实现中有一些功能无法引入支持库,因为这是设计上很难或开发人员不优先考虑的原因。例如,在本地实现中,onInflate()源代码中使用了Transition来动画显示或退出新片段。在支持库中找不到这个功能。


谢谢您的回答。我能看出为什么v23的两个版本的处理程序都被调用了。但是,对于v23之前的版本,我的替换处理程序仍然没有被调用。奇怪的是,我收到了一条日志信息“ I / dalvikvm:无法找到android.app.Fragment.onInflate方法,引用自OdometerFragment.onInflate方法”,这似乎很奇怪。还有一点,穿过android Fragment代码显示错误的源代码行,让我相信我没有最新版本的某些东西。 - Simon Hutton
1
请确保以下内容:1)导入的Fragment版本为android.support.v4.app.Fragment,而不是android.app.Fragment,并使用getSupportFragmentManager()而不是getFragmentManager()。2)在build.gradle中,您需要具有最新的support-v4和appcompat-v7库以及compileSdkVersion 23。 - Sevle
感谢您的进一步提示。昨晚我尝试更改为“support”片段,并解决了我的问题。我已相应更新了问题。然而,我仍然对原生和支持实现之间的差异感到困惑。在我看来,这似乎是某个地方出了问题。是的 - 我的具体问题得到了解决,但app.android.Fragment并没有。 - Simon Hutton
1
尽管您的编辑问题是原始问题的扩展,可能值得单独发布一个新帖子,但我已经进行了一些编辑,并提供了一些可能回答您问题的要点。您还可以查看此链接:https://dev59.com/jmgu5IYBdhLWcg3wBym1。 - Sevle

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