ใช้บริบทในส่วน


664

ฉันจะรับบริบทเป็นส่วนย่อยได้อย่างไร

ฉันต้องใช้ฐานข้อมูลของฉันซึ่งคอนสตรัคเตอร์ใช้ในบริบท แต่getApplicationContext()และFragmentClass.thisไม่ทำงานฉันต้องทำอย่างไร

ตัวสร้างฐานข้อมูล

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

คำตอบ:


1313

คุณสามารถใช้ซึ่งจะส่งกลับกิจกรรมที่เกี่ยวข้องกับgetActivity() กิจกรรมที่ได้คือ(ตั้งแต่ขยาย )fragment
context ActivityContext


212
getActivity () สามารถคืนค่า null ถ้ามันถูกเรียกก่อน onAttach ของส่วนที่เกี่ยวข้อง
arne.jans

4
ผมอ่านบล็อกนี้ Google ในการรั่วไหลของหน่วยความจำ ... android-developers.blogspot.com/2009/01/... หากฉันใช้เมธอด getActivity () แอปจะไม่เสี่ยงต่อการรั่วไหลของหน่วยความจำหรือไม่? บล็อกแนะนำ "ลองใช้บริบทแอปพลิเคชันแทนบริบทกิจกรรม" ซึ่งเป็นไปไม่ได้จริงๆเนื่องจาก getApplicationContext () ใช้ได้กับคลาสกิจกรรมเท่านั้นไม่ใช่คลาส Fragment
Simon

40
ทางออกสำหรับปัญหาของแฟรกเมนต์เดี่ยวคือการเก็บค่าของgetActivity().getApplicationContext()ตัวแปรอินสแตนซ์เมื่อสร้างแฟรกเมนต์แล้วใช้บริบทนั้นเมื่อใดก็ตามที่คุณต้องการภายในคลาสแฟรกเมนต์ บริบทนั้นจะมีชีวิตรอดได้
Piovezan

8
แทนที่จะส่งผ่านบริบทของแอปพลิเคชันให้สร้างบริบทแบบสแตติกภายในคลาสแอปพลิเคชันของคุณและเริ่มต้นใน onCreate (): MyApplication.sContext = getApplicationContext (); จากนั้นคุณสามารถเข้าถึงได้จากกิจกรรม / ส่วนใด ๆ โดยไม่ต้องกังวลเกี่ยวกับการปลด
Eduko

3
@milaniez: getActivityมีให้ใช้งานเสมอ มันgetContextเพิ่มเข้ามาใน API 23
mhsmith

130

ในการทำตามคำตอบข้างต้นคุณสามารถแทนที่onAttachวิธีการแฟรกเมนต์:

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

3
ฉันจะแนะนำสิ่งนี้เนื่องจาก getActivity () ส่งคืนค่า null หาก onAttach ยังไม่ถูกเรียกใช้
arne.jans

9
แต่โปรดจำไว้ว่าเมื่อเรียกใช้ onAttach () จะไม่มีมุมมอง ดังนั้นคุณไม่สามารถทำอะไรกับมุมมองได้!
Zordid

2
@iambox จะทำอย่างไรถ้าDatabaseHelperต้องการ a FragmentActivityแทนActivity? ตัวอย่างเช่นสำหรับAdapter...
Jago

4
หากคุณเก็บข้อมูลอ้างอิงเกี่ยวกับกิจกรรมของonAttach(Activity activity)คุณคุณควรเผยแพร่ในonDetach()
vovahost

3
onAttachวิธีการได้รับการเลิกOverrides deprecated method in 'android.support.v4.app.Fragment'
มูฮัมหมัด Saqib

24

ควรใช้getActivity ()วิธีการที่จะได้รับบริบทของกิจกรรมที่แนบมาของคุณ แต่จำไว้เสมอว่าสิ่งหนึ่งที่: เศษจะไม่แน่นอนเล็กน้อยและgetActivityผลตอบแทนที่เป็นโมฆะบางครั้งดังนั้นการที่มักจะตรวจสอบisAdded ()getActivity()วิธีการของส่วนก่อนที่จะเดินทางโดยบริบท


15
ฉันจะไม่บอกว่าชิ้นส่วนนั้น "ไม่เสถียรเล็กน้อย" ดูเหมือนว่าเป็นเรื่องปกติสำหรับ getActivity () เพื่อคืนค่าว่างเมื่อชิ้นส่วนไม่ได้เป็นของกิจกรรม สันนิษฐานว่า getActivity () "ไม่ควรคืนค่าว่าง" (ซึ่งผิด) ที่จะทำให้แอปของคุณ (และไม่ใช่คลาส Fragment) ไม่เสถียร
personne3000

3
@ personne3000 ฉันอยากได้ยินมากกว่านี้ ชิ้นส่วนไม่ได้เป็นของกิจกรรมเมื่อใด เหตุการณ์นี้จะเกิดขึ้นเมื่อใดและเพราะเหตุใด เราควรตรวจสอบ isAdded () ในแฟรกเมนต์เพื่อใช้ getActivity () หรือไม่ กฎของหัวแม่มือ?
Sotti

2
@Sotti ฉันขอแนะนำให้คุณสร้างคำถามใหม่สำหรับเรื่องนี้ (หรือมองหาคำถามที่มีอยู่) เนื่องจากหัวเรื่องเฉพาะนี้แตกต่างจากคำถามเดิมเล็กน้อย คุณสามารถดูได้ที่developer.android.com/guide/components/fragments.html#Lifecycleสำหรับข้อมูลทั่วไป โดยทั่วไปก่อน onAttach และหลังจาก onDetach ไม่มีกิจกรรม และระหว่าง onAttach และ onActivityCreated กิจกรรมของ onCreate ยังไม่ถูกเรียกใช้ เมื่อใช้ getActivity () ตรวจสอบให้แน่ใจว่ามีการสร้างกิจกรรมของคุณแล้วและคิดว่าจะเกิดอะไรขึ้นถ้ากิจกรรมถูกทำลายหรือแยกส่วนของคุณออก
personne3000

22

วิธีที่ง่ายและแม่นยำที่สุดในการรับบริบทของแฟรกเมนต์ที่ฉันพบคือรับโดยตรงจากViewGroupเมื่อคุณเรียกonCreateViewใช้เมธอดอย่างน้อยที่นี่คุณแน่ใจว่าจะไม่ได้รับค่าว่างสำหรับ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

3
จริงบน dialogFragments คอนเทนเนอร์สามารถเป็นโมฆะ ระวัง!
ลูคัสเทสก์

ควรใช้โซลูชันนี้ใน onViewCreated ไม่ใช่ onCreateView
Andrea De Simone

13

ก่อนหน้านี้ฉันใช้onAttach (Activity activity)เพื่อcontextเข้าFragment

ปัญหา

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()การได้รับcontextในFragments แต่getActivity()สามารถกลับnullถ้าคุณ fragmentไม่ได้แนบในปัจจุบันผู้ปกครองactivity,



6

นอกจากนี้คุณยังจะได้รับบริบทจากที่พารามิเตอร์เมื่อเอาชนะinflateronCreateView

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()งานคุณสามารถใช้งานได้ แต่ไม่แนะนำให้ทำเพราะจะทำให้หน่วยความจำรั่ว

ฉันคิดว่า aproach ที่ดีกว่าจะต้องได้รับActivityจากonAttach()วิธีการ:

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

คุณไม่ควรใช้ getActivity ในส่วนเพื่อรับมุมมองเว้นแต่ว่ามุมมองนั้นเป็นส่วนหนึ่งของกิจกรรม ทำไมคุณต้องขยายมุมมองในส่วนที่ไม่ได้อ้างอิงอะไรจากมัน?
tyczj

คำตอบนี้เกี่ยวกับสิ่งที่แตกต่างคุณกำลังพูดถึงมุมมอง hiearchy เพื่อค้นหามุมมองActivity.findViewByIdเป็นเพียงวิธีที่สะดวกในการค้นหามุมมองในมุมมองเนื้อหาที่ลงทะเบียนของกิจกรรมนั้น (ตั้งค่าผ่านsetContentView) ในตัวอย่างที่ถูกต้องของคุณคุณโทรView.findViewByIdไม่Activity.findViewByIdและคุณกำลังเรียกใช้วิธีการในมุมมองรากที่ถูกต้อง ปัญหาที่แตกต่างกันโดยสิ้นเชิงและแน่นอนคุณจะไม่สามารถค้นหามุมมองของคุณในมุมมอง hiearchy ที่ไม่ได้เก็บมุมมองนั้น
JHH

3

getContext() มาใน API 23 แทนที่ด้วย getActivity () ทุกที่ในรหัส

ดูว่าจะแก้ไขข้อผิดพลาด ลองใช้วิธีการที่อยู่ระหว่างเป้าหมายและระดับขั้นต่ำของ 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;
}

วิธีนี้คุณสามารถมั่นใจได้ว่าบริบทจะเป็นค่าที่ไม่เป็นศูนย์เสมอ


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 () ด้วยและมันไม่ทำงานฉันได้ลองทุกอย่างที่ทำได้จากตัวอย่างด้านบนและบริบท ที่ดีที่สุดฉันจะได้รับข้อความนี้ - มีข้อโต้แย้งมากมายผ่าน ... โปรดช่วยด้วย val ctx = context?: ส่งคืน Picasso.get (ctx) .load (selectedGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade

@Ade ในส่วนของคุณลองใช้ "กิจกรรม !!" แทนที่จะเป็น "ctx" และแจ้งให้เราทราบว่ามันช่วยได้หรือไม่
Kishan Solanki

@ KishanSolanki124 ขอบคุณมากสำหรับการตอบสนองที่รวดเร็ว ฉันลองใช้คำแนะนำของคุณพร้อมผลลัพธ์เดียวกัน - ยังไม่ทำงาน ข้อความแจ้งข้อผิดพลาดที่แน่นอนคือ - มีการโต้แย้งกันมากเกินไปสำหรับความสนุกแบบเปิดสาธารณะที่ได้รับ (): Picasso! ข้อความนี้ทำให้ฉันคิดว่าอาจมีข้อผิดพลาดอย่างอื่นอีกหรือ แม้ว่าน่ายินดีพบวิธีที่จะไปกับงานของฉันโดยใช้ Picasso โดยไม่ต้องรับบริบท ขอบคุณอีกครั้ง.
Ade



1

เป็นการดีที่คุณไม่จำเป็นต้องใช้ globals แฟรกเมนต์มีการแจ้งเตือนที่แตกต่างกันซึ่งหนึ่งในนั้นอยู่ในแอคทีฟแอคทีฟ คุณสามารถรับอินสแตนซ์ของกิจกรรมในเหตุการณ์วงจรชีวิตของชิ้นส่วนนี้

จากนั้นคุณสามารถแยกส่วนเพื่อรับกิจกรรมบริบทหรือแอปพลิเคชันเนื้อหาตามที่คุณต้องการ:

this.getActivity()จะให้คุณจัดการกับกิจกรรมที่ this.getContext()จะให้คุณจัดการกับบริบทที่ this.getActivity().getApplicationContext()จะให้คุณจัดการกับบริบทของแอพลิเคชัน คุณควรใช้บริบทของแอปพลิเคชันโดยเฉพาะอย่างยิ่งเมื่อส่งผ่านไปยัง db


1

getActivity()วิธีง่ายๆคือการใช้งาน แต่ฉันคิดว่าความสับสนหลักของการใช้getActivity()วิธีการรับบริบทที่นี่เป็นข้อยกเว้นตัวชี้โมฆะ

สำหรับสิ่งนี้ตรวจสอบครั้งแรกด้วยisAdded()วิธีการที่จะกำหนดว่าจะเพิ่มหรือไม่จากนั้นเราสามารถใช้getActivity()เพื่อให้ได้รับบริบทของกิจกรรม


1
สิ่งนี้แตกต่างจากคำตอบของ Ankur Chaudharyอย่างไร?
Peter Mortensen

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

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 ในส่วนเมื่อฉันใช้ข้อผิดพลาด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)เพราะอาจเป็นโมฆะเมื่อไม่ได้ติดแฟรกเมนต์กับกิจกรรม บางครั้งการทำงานเป็นเวลานานในส่วน (เช่นการดึงข้อมูลจากส่วนที่เหลือ API) ใช้เวลาพอสมควร และหากผู้ใช้นำทางไปยังส่วนอื่น จากนั้น getActivity จะเป็นโมฆะ และคุณจะได้รับ NPE หากคุณไม่ได้จัดการ


นี่คือเอกสารของวิธี getActivity () เพียงเพื่อแสดงว่าสิ่งเหล่านี้อาจเป็นโมฆะ ที่นี่ mHost เป็นตัวอย่างของการFragmentHostCallbackเรียน
เขมราฐ

0

เมื่อคุณแยกส่วน

((Name_of_your_Activity) getActivity()).helper

ในกิจกรรม

DbHelper helper = new DbHelper(this);

0

ส่วนในตัวอย่าง kotlin จะช่วยใครซักคน

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

ถ้าคุณใช้ databinding

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)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.