【问题标题】:What is the best place to call getContext()?调用 getContext() 的最佳位置是什么?
【发布时间】:2018-08-09 13:11:21
【问题描述】:

我在阅读片段文档时发现:

注意:如果您需要在 Fragment 中包含 Context 对象,您可以调用 getContext()。但是,请注意仅当片段附加到活动时才调用 getContext()。当片段尚未附加或在其生命周期结束时被分离时,getContext() 返回 null

所以我的问题是在片段中调用 getContext() 的最佳位置是什么。就像我可以在任何其他地方的 onCreateView、onCreate() 或 onAttach() 中调用它一样。

我之所以这么问,是因为最近我在片段中使用 getContext 导致空指针崩溃。所以我想我应该创建一个全局 Context 对象并在片段中访问它。但是后来我从官方文档中看到了这段文字,所以我有点困惑初始化这个 Context 对象的最佳位置是什么。

【问题讨论】:

  • 保存全局上下文实例是错误。您可以通过检查 getContext() 是否返回 null 来避免崩溃。如文档中所述,附加片段后上下文具有值。因此,在调用 onAttach() 之后。顺便说一句,不要将它存储在您的片段中,它可能会导致其他崩溃。
  • 如果您的片段是活动类的一部分,那么您可以使用 getApplicationContext();但是,由于您的问题缺少代码示例,因此很难为您提供可行的解决方案。
  • @LucaNicoletti 那么如果上下文为空,如何处理该特定代码,例如我必须调用 Toast,那么我应该如何获取上下文
  • 为什么这个问题被否决了?
  • @LucaNicoletti 我明白了,保存上下文是错误的,但是当大多数人提出错误的答案时,为什么这个问题会被否决。这不应该被赞成,这样我们大多数人就可以防止自己犯同样的错误吗?

标签: android


【解决方案1】:

这完全取决于您需要 Context 做什么。有时调用getApplicationContext() 就可以了,在其他情况下,可能需要使用onAttach() 中给出的内容,或者如果您使用Fragment 代码,则调用getActivity()。有些还提供了自己的Application 子类,暴露了getAppContext() 等静态方法。

在任何情况下,避免保存上下文,因为它可能导致内存泄漏。仅在需要时动态获取。

【讨论】:

    【解决方案2】:

    由于给出了很多错误的答案,我将提供处理片段内上下文的最佳方法。

    最好的解决方案是在需要时检查上下文是否具有值。 您可以通过以下两种方式包装访问片段的代码来做到这一点:

    if (getContext() != null) { /* code here */ }
    

    或者,如文档中所述,有这种方法:

    isAdded()
    

    which:“如果片段当前已添加到其活动中,则返回 true。” -reference

    再次提醒:请避免将上下文保存在本地片段的变量中。

    【讨论】:

    • 如果您注意该字段已被垃圾回收,并且没有在 Fragment 之外使用,那么它没有任何问题。它只是一个类中的一个简单字段,所以你不需要重新发明轮子,唯一的问题是把它放在正确的地方,不要有 null。
    • 片段分离时会出现问题。你仍然有一个你不应该有的上下文的引用。
    • 对于这个存在事件 onDetach() ,您可以轻松管理实例。就像我说的那样,这没有错,你只是应该知道你在做什么。强制分离是一件非常具体的事情,同样你应该知道你在做什么。
    • 我在这里也没有看到关于该部分的任何答案。我同意你的观点,但是当我可以使用 getContext() 访问它时,为什么还需要另一个变量?
    • 如果您在强制 onDetach() 时遇到这种情况,这通常是在破坏片段,因此 GC 会处理所有变量,这没有区别。但是,如果您将其用作具有正常行为的正常片段,则可以摆脱大量空值检查调用,因为您不能在没有空值检查的情况下使用 getContext()。在此处查看片段 i.stack.imgur.com/1ztBy.png 的生命周期,其中一切都非常清楚,什么时候该做什么。
    【解决方案3】:

    你可以在你的片段中做这样的事情。

    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        // After this point the context is initialized.
        context=activity;
    }
    

    注意:我真的不明白为什么它如此不喜欢这个答案。 首先,取决于 android 的版本(未提及),当然 OnAttach 已被弃用,必须检查它。 下一个: 我认为如果你在某个地方需要 cobntext,你可以在 Fragment 中创建一个私有或受保护的变量,这样上下文在被垃圾收集时就会被破坏。 受保护的 MainActivity 活动;

    确保你非常重视这个变量,并且它的引用不会传递给其他类。

    这应该可以完成工作。

    【讨论】:

    • 看起来真的很破旧,即使你能做到
    • @LucaNicoletti 即使你是对的。尽量善良。
    • 如果你注意上下文是垃圾收集的,它没有错,使用私有字段
    • 将上下文变量定义为静态是错误的,如果将上下文定义为私有,则在 onAttach() 中分配上下文的非静态变量非常好。在 onDestroy 上下文将被垃圾收集后
    【解决方案4】:

    你可以这样实现你的逻辑:

    private Context mContext;
    
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }
    @Override
    public void onDetach() {
        mContext = null;
        super.onDetach();
    }
    

    当你需要使用上下文时,

    if(mContext != null) {
       //Add your logic here
    }
    

    【讨论】:

    • 天啊。保存上下文是错误的。别再推荐了。
    • 没错,你只是应该意识到你在做什么。否则一般使用对象的私有字段是错误的。
    • @LucaNicoletti 我们只需要以正确的方式管理事情。
    • 如果您反对,请在评论中添加适当的理由。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    相关资源
    最近更新 更多