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


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.