【问题标题】:Using context in a fragment在片段中使用上下文
【发布时间】:2012-01-03 03:47:59
【问题描述】:

如何获取片段中的上下文?

我需要使用我的数据库,其构造函数接受上下文,但getApplicationContext()FragmentClass.this 不起作用,我该怎么办?

数据库构造函数

public Database(Context ctx)
{
    this.context = ctx;
    DBHelper = new DatabaseHelper(context);
}

【问题讨论】:

    标签: java android android-fragments android-context


    【解决方案1】:

    您可以使用getActivity(),它返回与fragment 关联的活动。
    该活动是context (因为Activity 扩展了Context

    【讨论】:

    • getActivity() 如果在相应片段的 onAttach 之前调用,则可以返回 null。
    • 我正在阅读有关内存泄漏的 Google 博客...android-developers.blogspot.com/2009/01/…。如果我使用 getActivity() 方法,应用程序不会有内存泄漏的风险吗?该博客建议“尝试使用上下文应用程序而不是上下文活动”,这实际上是不可能的,因为 getApplicationContext() 仅适用于 Activity 类而不适用于 Fragment 类。
    • 解决片段分离问题的解决方案是在片段创建时将getActivity().getApplicationContext() 的值存储在实例变量中,然后在片段类中随时使用该上下文。该上下文将在片段分离中幸存下来。
    • 不要传递应用程序上下文,而是在 Application 类中创建一个静态上下文并在 onCreate() 上对其进行初始化: MyApplication.sContext = getApplicationContext();那么您可以从任何活动/片段中访问它,而不必担心分离。
    • @milaniez:getActivity 一直可用。它是在 API 23 中添加的 getContext
    【解决方案2】:

    按照上面的答案,你可以重写片段的onAttach方法:

    public static class DummySectionFragment extends Fragment{
    ...
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            DBHelper = new DatabaseHelper(activity);
        }
    }
    

    【讨论】:

    • 我建议这样做,因为如果尚未调用 onAttach,getActivity() 将返回 null。
    • 但是,请记住,调用 onAttach() 时,没有视图。所以你还不能对视图做任何事情!
    • @iambox 如果DatabaseHelper 需要FragmentActivity 而不是Activity 怎么办?例如,对于Adapter...
    • 如果您在onAttach(Activity activity) 中存储对您的活动的引用,那么您应该在onDetach() 中释放它
    • onAttach 方法已被弃用,Overrides deprecated method in 'android.support.v4.app.Fragment'
    【解决方案3】:

    获取我发现的片段上下文的最简单和最精确的方法是直接从ViewGroup 获取它,当您调用onCreateView 方法时,至少在这里您肯定不会为getActivity() 获得null :

    public class Animal extends Fragment { 
      Context thiscontext;
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
      {
        thiscontext = container.getContext();
    

    【讨论】:

    • 这是容器的上下文,我认为......不是“这个上下文”。
    • @AG1 你能解释一下为什么它会导致你的代码崩溃吗?这是迄今为止我得到的最好的解决方案
    • 实际上在 dialogFragments 上容器可以为空。小心!
    • 这个方案应该用在onViewCreated,而不是onCreateView。
    【解决方案4】:

    始终使用getActivity() 方法来获取附加活动的上下文,但始终记住一件事:Fragment 有点不稳定,getActivity 有时会返回 null,因此,请始终检查 isAdded() 方法通过getActivity()获取上下文之前的片段。

    【讨论】:

    • 我不会说片段“有点不稳定”,当片段不属于活动时 getActivity() 返回 null 似乎很正常。假设 getActivity() “不应该返回 null”(这是错误的)会使您的应用(而不是 Fragment 类)不稳定。
    • @personne3000 我想听更多。片段何时不属于 Activity?这是什么时候发生的,为什么?我们是否应该检查片段中的 isAdded() 以使用 getActivity()?有什么经验法则吗?
    • @Sotti 我鼓励您为此创建一个新问题(或查找现有问题),因为这个特定主题与原始问题略有不同。您可以查看developer.android.com/guide/components/fragments.html#Lifecycle 了解一般信息。基本上,在 onAttach 之前和 onDetach 之后,没有活动。而在onAttach 和onActivityCreated 之间,活动的onCreate 还没有被调用。使用 getActivity() 时,请确保您的 Activity 已经创建,并考虑如果它被销毁或您的 Fragment 被分离会发生什么。
    【解决方案5】:

    以前我使用onAttach (Activity activity)Fragment 中获取context

    问题

    onAttach (Activity activity) 方法在 API 级别 23 中已弃用。

    解决方案

    现在要在Fragment 中获取上下文,我们可以使用onAttach (Context context)

    onAttach (Context context)

    • 在片段首次附加到其context 时调用。 onCreate(Bundle) 将在此之后调用。

    文档

    /**
     * Called when a fragment is first attached to its context.
     * {@link #onCreate(Bundle)} will be called after this.
     */
    @CallSuper
    public void onAttach(Context context) {
        mCalled = true;
        final Activity hostActivity = mHost == null ? null : mHost.getActivity();
        if (hostActivity != null) {
            mCalled = false;
            onAttach(hostActivity);
        }
    }
    

    示例代码

    public class FirstFragment extends Fragment {
    
    
        private Context mContext;
        public FirstFragment() {
            // Required empty public constructor
        }
    
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            mContext=context;
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rooView=inflater.inflate(R.layout.fragment_first, container, false);
    
            Toast.makeText(mContext, "THIS IS SAMPLE TOAST", Toast.LENGTH_SHORT).show();
            // Inflate the layout for this fragment
            return rooView;
        }
    
    }
    

    注意

    我们也可以使用getActivity()Fragments中得到context 但是getActivity() 可以返回null 如果您的fragment 当前未附加到父activity

    【讨论】:

    • 是的,它的解决方案很好,但需要测试各种情况。
    【解决方案6】:
    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        context=activity;
    }
    

    【讨论】:

      【解决方案7】:

      requireContext() 方法是最简单的选择

      requireContext()
      

      例子

      MyDatabase(requireContext())
      

      【讨论】:

        【解决方案8】:

        当覆盖onCreateView 时,您还可以从inflater 参数中获取上下文。

        public static class MyFragment extends Fragment {
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                         Bundle savedInstanceState) {
                /* ... */
                Context context = inflater.getContext();
                /* ... */
            }
        }
        

        【讨论】:

          【解决方案9】:

          正确的方法是使用

          requireContext()
          

          例子

          ContextCompat.getColor(requireContext(), R.color.colorAccent),
          

          原始答案(见答案修订版)

          【讨论】:

          • 上下文 != ApplicationContext
          【解决方案10】:

          另一种替代方法是:

          您可以使用以下方法获取上下文:

          getActivity().getApplicationContext();
          

          【讨论】:

            【解决方案11】:

            可以使用getActivity() 获取片段内的上下文:

            public Database()
            {
                this.context = getActivity();
                DBHelper = new DatabaseHelper(this.context);
            }
            
            • 注意,使用getActivity()获取与fragment关联的Activity,可以使用但不推荐,会导致内存泄漏。

            我认为更好的方法必须是从onAttach() 方法中获取Activity

            @Override
            public void onAttach(Activity activity) {
                super.onAttach(activity);
                context = activity;
            }
            

            【讨论】:

            • 您不应该在片段中使用 getActivity 来获取视图,除非该视图是活动的一部分。为什么要在片段中膨胀视图,然后甚至不引用其中的任何内容?
            • 这个答案是关于不同的东西,你说的是在哪个视图层次结构中搜索视图。Activity.findViewById 只是在该活动的注册内容视图中搜索视图的便捷方法(设置通过setContentView)。在您的正确示例中,您调用的是View.findViewById,而不是Activity.findViewById,并且您在正确 根视图上调用该方法。完全不同的问题,显然您将无法在不包含该视图的视图层次结构中找到您的视图。
            【解决方案12】:

            getContext() 出现在 API 23 中。将其替换为代码中的任何地方的 getActivity()。

            看看它是否修复了错误。尝试使用介于目标和最低 API 级别之间的方法,否则会出现此错误。

            【讨论】:

              【解决方案13】:

              由于 API 级别 23,有 getContext(),但如果您想支持旧版本,您可以使用 getActivity().getApplicationContext(),而我仍然建议使用 Fragment 的支持版本,即 android.support.v4.app.Fragment

              【讨论】:

                【解决方案14】:

                对于 Kotlin,您可以直接在片段中使用 context。但在某些情况下,您会发现类似

                的错误

                类型不匹配:推断类型是上下文?但上下文是预期的

                为此你可以这样做

                val ctx = context ?: return
                textViewABC.setTextColor(ContextCompat.getColor(ctx, android.R.color.black))
                

                【讨论】:

                • 感谢您提供 Kotlin 版本,该版本运行良好,但我正在尝试使用它获取 Picasso.get() 的上下文,但它永远无法正常工作,我已尝试从上面的示例中尽我所能很好地了解上下文。充其量我会收到此消息-传递了太多参数...请帮助。 val ctx = context ?: return Picasso.get(ctx) .load(selectedGallery.imageUrl) .placeholder(R.mipmap.ic_launcher) .into(galleryImage)
                • @Ade 在您的片段中,尝试使用“活动!!”而不是“ctx”,让我知道它是否有帮助
                • @KishanSolanki124。非常感谢您的快速回复。我尝试了您的建议,结果相同 - 仍然无法正常工作。确切的错误提示是 - Too many arguments for public open fun get(): Picasso!。这条消息让我想,也许还有别的错误?不过很高兴,找到了一种方法来继续我的工作,即使用毕加索而无需获取上下文。再次感谢。
                【解决方案15】:

                getActivity() 是 Context 的子级,因此应该适合您

                【讨论】:

                  【解决方案16】:

                  使用支持库中的片段 -

                  android.support.v4.app.Fragment
                  

                  然后覆盖

                  void onAttach (Context context) {
                    this.context = context;
                  }
                  

                  这样可以确保上下文始终是非空值。

                  【讨论】:

                    【解决方案17】:

                    你有不同的选择:

                    • 如果您的 minSDK getActivity(),因为这是 Context
                    • 如果您的 minSDK >=23,那么您可以使用getContext()

                    如果您不需要支持旧版本,请使用getContext()

                    【讨论】:

                      【解决方案18】:

                      kotlin 中只需使用 activity 而不是 getActivity()

                      【讨论】:

                        【解决方案19】:

                        您可以使用 getActivity() 方法获取上下文或 您可以使用 getContext() 方法。

                         View root = inflater.inflate(R.layout.fragment_slideshow, container, false);
                            Context c = root.getContext();
                        

                        希望对你有帮助!

                        【讨论】:

                        • 还有其他答案提供了 OP 的问题,它们是前段时间发布的。发布答案 see: How do I write a good answer? 时,请确保添加新的解决方案或更好的解释,尤其是在回答较老的问题时。
                        【解决方案20】:

                        在片段中获取上下文的安全方法

                        if(isAdded){
                        requireActivit();//this is your context
                        }
                        

                        【讨论】:

                          【解决方案21】:

                          理想情况下,您不需要使用全局变量。该片段有不同的通知,其中之一是 onActivityCreated。可以在fragment的这个生命周期事件中获取activity的实例。

                          然后:您可以根据需要取消引用片段以获取活动、上下文或应用程序上下文:

                          this.getActivity() 将为您提供活动的句柄 this.getContext() 将为您提供上下文句柄 this.getActivity().getApplicationContext() 将为您提供应用程序上下文的句柄。您最好在将应用程序上下文传递给数据库时使用它。

                          【讨论】:

                            【解决方案22】:

                            简单的方法是使用getActivity()。但我认为在这里使用getActivity() 方法获取上下文的主要混淆是空指针异常。

                            为此,首先使用isAdded()方法判断是否添加,然后我们可以使用getActivity()获取Activity的上下文。

                            【讨论】:

                            【解决方案23】:

                            您可以拨打getActivity()或者,

                            public void onAttach(Context context) {
                                super.onAttach(context);
                                this.activity = (CashActivity) context;
                                this.money = this.activity.money;
                            }
                            

                            【讨论】:

                              【解决方案24】:

                              我认为你可以使用

                              public static class MyFragment extends Fragment {
                                @Override
                                public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                                           Bundle savedInstanceState) {
                              
                                    Context context = getActivity.getContext();
                              
                                }
                              }
                              

                              【讨论】:

                                【解决方案25】:
                                public class MenuFragment extends Fragment implements View.OnClickListener {
                                    private Context mContext;
                                    @Override
                                    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                                        FragmentMenuBinding binding=FragmentMenuBinding.inflate(inflater,container,false);
                                        View view=binding.getRoot();
                                        mContext=view.getContext();
                                        return view;
                                    }
                                }
                                

                                【讨论】:

                                  【解决方案26】:

                                  我需要使用 arrayAdapter IN 片段的上下文,当我使用 getActivity 时发生错误,但是当我用 getContext 替换它时它对我有用

                                  listView LV=getView().findViewById(R.id.listOFsensors);
                                  LV.setAdapter(new ArrayAdapter<String>(getContext(),android.R.layout.simple_list_item_1 ,listSensorType));
                                  

                                  【讨论】:

                                    【解决方案27】:

                                    你的片段

                                    ((Name_of_your_Activity) getActivity()).helper
                                    

                                    在活动中

                                    DbHelper helper = new DbHelper(this);
                                    

                                    【讨论】:

                                      【解决方案28】:

                                      kotlin 示例的内部片段会帮助某人

                                      textViewStatus.setTextColor(ContextCompat.getColor(context!!, R.color.red))
                                      

                                      如果您使用数据绑定;

                                      bindingView.textViewStatus.setTextColor(ContextCompat.getColor(context!!, R.color.red))
                                      

                                      像这样在onCreateView中初始化bindingView

                                      private lateinit var bindingView: FragmentBookingHistoryDetailBinding
                                      
                                      bindingView = DataBindingUtil.inflate(inflater, R.layout.your_layout_xml, container, false)
                                      

                                      【讨论】:

                                        猜你喜欢
                                        • 2016-12-12
                                        • 2016-10-19
                                        • 1970-01-01
                                        • 2013-10-24
                                        • 2016-08-19
                                        相关资源
                                        最近更新 更多