为啥片段类应该是公开的?

Posted

技术标签:

【中文标题】为啥片段类应该是公开的?【英文标题】:Why fragment class should be public?为什么片段类应该是公开的? 【发布时间】:2018-12-23 20:41:55 【问题描述】:

我发现一些线程解释了为什么 Fragment 类应该是 static(而不是 非静态内部),例如 this。但是无法理解这个错误信息的原因:

这个片段类应该是公共的(...)


我使用 android Studio 3.1.2,这是我的代码的一部分:

public class MainActivity extends android.support.v7.app.AppCompatActivity 
    // ...


class DefaultFragment extends android.support.v4.app.Fragment 
    // ...

片段应该只在MainActivity中使用。


编辑:IDE 消息中还有一些其他信息。但是关于构造函数:

来自片段文档:

每个片段都必须有一个空的构造函数,因此可以在恢复其活动状态时对其进行实例化。强烈建议子类不要有其他带参数的构造函数,因为片段重新实例化时不会调用这些构造函数;相反,参数可以由调用者使用 setArguments(Bundle) 提供,然后由 Fragment 使用 getArguments() 检索。

【问题讨论】:

应该只在 MainActivity 中使用...所以我猜你有答案... 在方向改变时,重新创建 Activity 并且框架在片段上创建新实例(并恢复之前的状态)。所以这里要创建 Fragment 的实例,框架要求提供公共构造函数。 @B001ᛦ; MainActivityDefaultFragment,两者都在同一个文件中(因此在同一个 package 下)。所以可以在MainActivity 中访问,而不必是public @PankajKumar;谢谢。如果您发表评论作为答案,我会接受。 【参考方案1】:

在方向改变时,重新创建 Activity 并且框架在片段上创建新实例(并恢复之前的状态)。 所以这里要创建 Fragment 的实例,框架要求提供公共构造函数。


来自Fragment.Fragment()的文档

Default constructor :

每个片段都必须有一个empty constructor,因此可以在恢复其活动状态时对其进行实例化。强烈建议子类不要有其他带参数的构造函数,因为片段重新实例化时不会调用这些构造函数;相反,调用者可以使用setArguments(Bundle) 提供参数,然后由Fragment 使用getArguments() 检索。


以下是Activity.java类的代码形式,您可以在查看更多FragmentManager.dispatchMoveToState()的代码时进一步分析

@MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) 
    ........
    if (savedInstanceState != null) 
        mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
        mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
                View.LAST_APP_AUTOFILL_ID);
        if (mAutoFillResetNeeded) 
            getAutofillManager().onCreate(savedInstanceState);
        
        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.fragments : null);
    
    mFragments.dispatchCreate();
    .....

【讨论】:

【参考方案2】:

这也是因为内部类持有对其父类的引用,这可能会泄漏 Activity。

非静态内部类确实持有对其父类的引用。使 Fragment 内部类成为非静态的问题在于您始终持有对 Activity 的引用。 GarbageCollector 无法收集您的 Activity。因此,如果例如方向发生变化,您可以“泄漏”活动。因为 Fragment 可能仍然存在并被插入到新的 Activity 中。

检查detailed answer并尝试制作片段

【讨论】:

以上是关于为啥片段类应该是公开的?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 JUnit 中的 @Rule 注释字段必须是公开的?

为啥我的所有 Spring Boot 执行器端点都是公开可用的?

将公共属性和方法公开给 Main Activity 的片段是不是是一种不好的形式?

反序列化为啥要找公开方法

C ++为啥在使用类时应该使用get和set函数[重复]

为啥接口的显式实现不能公开?