在片段中使用上下文


664

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

我需要用我的数据库其构造函数采用的背景下,但getApplicationContext()FragmentClass.this没有工作,所以我能做些什么?

数据库构造函数

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

Answers:


1313

您可以使用getActivity(),返回与关联的活动fragment
活动是context (自Activity扩展以来Context


212
如果在各个片段的onAttach之前调用getActivity(),则可以返回null。
arne.jans 2013年

4
我正在阅读有关内存泄漏的Google博客... android-developers.blogspot.com/2009/01/…。如果我使用getActivity()方法,该应用程序不会有内存泄漏的风险吗?该博客建议“尝试使用上下文应用程序而不是上下文活动”,因为getApplicationContext()仅适用于Activity类,而不适用于Fragment类,因此这实际上是不可能的。
西蒙

40
解决碎片分离问题的一种方法是,getActivity().getApplicationContext()在创建碎片时将的值存储在实例变量中,然后在需要时在碎片类中使用该上下文。该上下文将在碎片分离中幸存下来。
Piovezan 2014年

8
无需传递应用程序上下文,而在Application类中创建静态上下文,然后在onCreate()上对其进行初始化:MyApplication.sContext = getApplicationContext(); 那么您可以从任何活动/片段访问它,而不必担心分离。
Eduko

3
@milaniez:getActivity一直可用。它getContext是在API 23中添加的
。– mhsmith

130

为此,您可以覆盖onAttachfragment方法:

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

3
我建议这样做,因为如果尚未调用onAttach,则getActivity()返回null。
arne.jans 2013年

9
但是请记住,在调用onAttach()时,没有任何视图。因此,您还无法对视图进行任何操作!
Zordid

2
@iambox如果DatabaseHelper需要a FragmentActivity而不是a Activity怎么办?例如Adapter...
Jago 2013年

4
如果您在其中存储对活动的引用,onAttach(Activity activity)则应在以下位置发布它onDetach()
vovahost 2014年

3
onAttach方法已被弃用,Overrides deprecated method in 'android.support.v4.app.Fragment'
穆罕默德Saqib

24

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


15
我不会说片段是“稍微不稳定的”,当片段不属于活动时,getActivity()返回null似乎很正常。假设getActivity()“不应返回null”(这是错误的)会使您的应用程序(而不是Fragment类)不稳定。
personne3000

3
@ personne3000我想听到更多。片段何时不属于活动?什么时候发生,为什么?为了使用getActivity(),我们是否应该检查片段中的iwego()?有什么经验法则吗?
索提2015年

2
@Sotti我鼓励您为此创建一个新问题(或查找现有问题),因为该特定主题与原始问题有所不同。您可以查看developer.android.com/guide/components/fragments.html#Lifecycle了解一般信息。基本上,在onAttach之前和onDetach之后,没有任何活动。在onAttach和onActivityCreated之间,尚未调用活动的onCreate。使用getActivity()时,请确保已创建您的活动,并考虑如果活动被破坏或片段被分离会发生什么。
personne3000

22

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

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

10
我认为那是容器的上下文,而不是“此上下文”。
Fattie

2
@ AG1您能解释一下为什么它使您的代码崩溃了吗?这是迄今为止我所拥有的最佳解决方案
Machado 2015年

3
实际上,在dialogFragments上,容器可以为null。小心点!
卢卡斯·特斯克

此解决方案应在onViewCreated中使用,而不是在onCreateView中使用。
Andrea De Simone

13

以前我是onAttach (Activity activity)用来进去contextFragment

问题

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

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

onAttach (Context context)

  • 片段首次附加到时调用contextonCreate(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()得到contextFragments ,但getActivity()可以返回null,如果您 fragment当前未连接到父activity


11
@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);
    context=activity;
}

6

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

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

5

另一种替代方法是:

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

getActivity().getApplicationContext();

5

在Fragment中获取上下文可以使用getActivity()

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • 请注意,要Activity使用与片段相关联getActivity(),可以使用它,但不建议这样做会导致内存泄漏。

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

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

您不应该在片段中使用getActivity来获取视图,除非该视图仍然是活动的一部分。为什么要在一个片段中扩大视图,然后甚至不引用其中的任何内容?
tyczj 2014年

答案是不同的,您正在谈论要在哪个视图层次结构中搜索视图。Activity.findViewById这只是在该活动的注册内容视图(通过中设置setContentView)中搜索视图的一种便捷方法。在正确的示例中,您正在调用View.findViewById,而不是Activity.findViewById,并且您正在正确的根视图上调用该方法。完全不同的问题,很明显,您将无法在没有该视图的视图层次结构中找到您的视图。
JHH'3

3

getContext() API 23中附带的代码。在代码中的所有位置均将其替换为getActivity()。

查看它是否解决了错误。尝试使用介于目标API级别和最低API级别之间的方法,否则将发生此错误。


3

从API级别23开始,getContext()但是如果您想支持较旧的版本,可以使用,getActivity().getApplicationContext()尽管我仍然建议使用支持版本Fragmentandroid.support.v4.app.Fragment



2

使用支持库中的片段-

android.support.v4.app.Fragment

然后覆盖

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

这样,您可以确保上下文将始终为非null值。


2

您有不同的选择:

  • 如果您的minSDK <= 21,则可以使用getActivity(),因为这是一个Context
  • 如果您的minSDK> = 23,则可以使用getContext()

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


2

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

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

为此,您可以这样做

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

感谢您使用Kotlin版本,该版本可以正常工作,但是我正尝试使用Picasso.get()获取Context,但是它从未起作用,我还尝试了上述示例中的所有方法来获取上下文。充其量我会收到此消息-传递了太多参数...请帮助。?VAL CTX =方面:回报Picasso.get(CTX).load(selectedGallery.imageUrl).placeholder(R.mipmap.ic_launcher).into(galleryImage)
阿德

@Ade在您的片段中,尝试使用“活动!!” 而不是“ ctx”,让我知道它是否有所帮助
Kishan Solanki

@ KishanSolanki124。非常感谢您的快速回复。我尝试了您的建议,但结果相同-无法正常工作。确切的错误提示是-公共打开乐趣get()的参数太多:毕加索!此消息使我思考,也许是其他原因导致的错误?不过很高兴,找到了一种在不获取上下文的情况下使用毕加索进行创作的方法。再次感谢。
阿德(Ade)


2

使用Kotlin上的API 29+,我不得不

activity?.applicationContext!!

一个例子是

ContextCompat.getColor(activity?.applicationContext!!, R.color.colorAccent),

Context!= ApplicationContext
Gabriele Mariotti

1

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

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

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


1

简单的方法是使用getActivity()。但是我认为使用该getActivity()方法在此处获取上下文的主要困惑是空指针异常。

为此,首先检查isAdded()将确定是否添加了该方法的方法,然后我们可以使用getActivity()获取活动的上下文。


1
这与Ankur Chaudhary的答案有何不同?
彼得·莫滕森

1

您可以致电getActivity()或,

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

1

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

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

希望对您有所帮助!


1
还提供了OP的问题的其他答案,这些答案已在一段时间前发布。发布答案时,请参阅:如何写一个好的答案?,请确保您添加了新的解决方案或实质上更好的解释,尤其是在回答较旧的问题时。
help-info.de


0

我想你可以用

public static class MyFragment extends Fragment {
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

      Context context = getActivity.getContext();

  }
}

0
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;
    }
}

0

您也可以使用:

inflater.getContext();

但我宁愿使用

getActivity()

要么

getContext

0

我需要使用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));

0

您可以使用getActivity()getContext在片段中。

文献资料

/**
 * Return the {@link FragmentActivity} this fragment is currently associated with.
 * May return {@code null} if the fragment is associated with a {@link Context}
 * instead.
 *
 * @see #requireActivity()
 */
@Nullable
final public FragmentActivity getActivity() {
    return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}

 /**
     * Return the {@link Context} this fragment is currently associated with.
     *
     * @see #requireContext()
     */
    @Nullable
    public Context getContext() {
        return mHost == null ? null : mHost.getContext();
    }

专家提示

始终检查一下,if(getActivity!=null)因为如果片段未附加到活动中,则该字段可以为null。有时在片段中进行长时间操作(例如从rest api获取数据)需要一些时间。以及用户是否导航到另一个片段。然后getActivity将为null。如果不处理,您将获得NPE。


这是getActivity()方法的文档,只是为了证明它们可以为null。这里的mHost是FragmentHostCallback类的实例。
Khemraj

0

在你身上

((Name_of_your_Activity) getActivity()).helper

活动中

DbHelper helper = new DbHelper(this);

0

Kotlin样本的内部片段将帮助某人

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

如果您使用数据绑定;

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

凡bindingView在初始化onCreateView这样

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

bindingView = DataBindingUtil.inflate(inflater, R.layout.your_layout_xml, container, false)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.