在片段中使用上下文

Posted

技术标签:

【中文标题】在片段中使用上下文【英文标题】: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);

【问题讨论】:

【参考方案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的上下文。

【讨论】:

这与Ankur Chaudhary's answer有何不同?【参考方案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)

【讨论】:

以上是关于在片段中使用上下文的主要内容,如果未能解决你的问题,请参考以下文章

片段未附加到上下文

Android - 在寻呼机中获取片段的上下文

在 recyclerview 片段中实现上下文操作模式的问题

Android:片段无法转换为上下文[重复]

片段未附加到上下文 - 延迟的 UI 更改

传递嵌套在片段中的 AdapterView.OnItemClickListener() 中的活动上下文 - 方法未定义