Sử dụng bối cảnh trong một đoạn


663

Làm thế nào tôi có thể có được bối cảnh trong một mảnh?

Tôi cần phải sử dụng cơ sở dữ liệu của tôi có constructor mất trong bối cảnh, nhưng getApplicationContext()FragmentClass.thiskhông có tác dụng vì vậy những gì tôi có thể làm gì?

Xây dựng cơ sở dữ liệu

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

Câu trả lời:


1312

Bạn có thể sử dụng getActivity(), trả về hoạt động liên quan đến a fragment.
Các hoạt động là một context (kể từ khi Activitymở rộng Context) .


212
getActivity () có thể trả về null nếu nó được gọi trước onAttach của đoạn tương ứng.
arne.jans

4
Tôi đã đọc blog Google này về rò rỉ bộ nhớ ... android-developers.blogspot.com/2009/01/ . Nếu tôi sử dụng phương thức getActivity () thì ứng dụng sẽ không có nguy cơ bị rò rỉ bộ nhớ? Blog gợi ý "Thử sử dụng ứng dụng ngữ cảnh thay vì hoạt động theo ngữ cảnh", điều này thực sự không khả thi vì getApplicationContext () chỉ hoạt động cho lớp Activity chứ không phải lớp Fragment.
Simon

40
Một giải pháp cho vấn đề tách rời là lưu trữ giá trị của getActivity().getApplicationContext()một biến thể hiện khi đoạn được tạo và sau đó sử dụng bối cảnh đó bất cứ khi nào bạn muốn bên trong lớp phân đoạn. Bối cảnh đó sẽ tồn tại những mảnh vỡ
Piovezan

8
Thay vì chuyển qua bối cảnh ứng dụng, hãy tạo một bối cảnh tĩnh bên trong lớp Ứng dụng của bạn và khởi tạo nó onCreate (): MyApplication.sContext = getApplicationContext (); sau đó bạn có thể truy cập nó từ bất kỳ hoạt động / đoạn nào mà không phải lo lắng về sự tách rời.
Eduko

3
@milaniez: getActivityđã luôn có sẵn. Nó getContextđã được thêm vào API 23.
mhsmith

130

Để làm như câu trả lời ở trên, bạn có thể ghi đè onAttachphương thức phân đoạn:

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

3
Tôi muốn giới thiệu điều này, vì getActivity () trả về null nếu onAttach chưa được gọi.
arne.jans

9
Nhưng, hãy nhớ rằng, khi onAttach () được gọi, không có chế độ xem. Vì vậy, bạn không thể làm bất cứ điều gì với quan điểm chưa!
Zordid

2
@iambox nếu DatabaseHelpercần một FragmentActivitythay vì Activity? Ví dụ: đối với một Adapter...
Jago

4
Nếu bạn lưu trữ một tài liệu tham khảo cho hoạt động của mình onAttach(Activity activity)thì bạn nên phát hành nó trongonDetach()
vovahost

3
Các onAttachphương pháp không được dùng nữaOverrides deprecated method in 'android.support.v4.app.Fragment'
Muhammad Saqib

24

Luôn sử dụng phương thức getActivity () để lấy bối cảnh của hoạt động đính kèm của bạn, nhưng luôn nhớ một điều: Các đoạn hơi không ổn định và getActivitytrả về null một số lần, vì vậy, hãy luôn kiểm tra phương thức phân đoạn isAdded () trước khi lấy ngữ cảnh getActivity().


15
Tôi sẽ không nói rằng các đoạn "hơi không ổn định", có vẻ như khá bình thường khi getActivity () trả về null khi đoạn đó không thuộc về một hoạt động. Giả sử getActivity () "không trả về null" (sai) sẽ làm cho ứng dụng của bạn (chứ không phải lớp Fragment) không ổn định.
personne3000

3
@ personne3000 Tôi muốn nghe thêm. Khi nào một mảnh không thuộc về một Hoạt động? Khi nào thì điều này xảy ra và tại sao? Chúng ta có nên kiểm tra isAdded () trong đoạn để sử dụng getActivity () không? Bất kỳ quy tắc của ngón tay cái?
Sotti

2
@Sotti Tôi khuyến khích bạn tạo một câu hỏi mới cho câu hỏi này (hoặc tìm một câu hỏi hiện có), vì chủ đề cụ thể này hơi khác so với câu hỏi ban đầu. Bạn có thể xem qua developer.android.com/guide/components/fragments.html#Lifecycle để biết thông tin chung. Về cơ bản, trước onAttach và sau onDetach, không có hoạt động. Và giữa onAttach và onActivityCreated, onCreate của hoạt động vẫn chưa được gọi. Khi sử dụng getActivity (), hãy đảm bảo rằng hoạt động của bạn đã được tạo và suy nghĩ về những gì sẽ xảy ra nếu nó bị phá hủy hoặc đoạn của bạn bị tách ra.
personne3000

22

Cách dễ nhất và chính xác nhất để có được bối cảnh của đoạn mà tôi tìm thấy là lấy nó trực tiếp từ ViewGroupkhi bạn gọi onCreateViewphương thức ít nhất ở đây, bạn chắc chắn không nhận được null cho getActivity():

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

10
đó là bối cảnh của container, tôi nghĩ ... không phải "bối cảnh này".
Fattie

2
@ AG1 bạn có thể vui lòng giải thích tại sao nó bị lỗi mã của bạn không? Đây là giải pháp tốt nhất mà tôi có
Machado

3
Trên thực tế trên hộp thoạiFragments container có thể là null. Hãy cẩn thận!
Lucas Teske 7/8/2015

Giải pháp này nên được sử dụng trong onViewCreated, không phải onCreateView.
Andrea De Simone

13

Trước đây tôi đang sử dụng onAttach (Activity activity)để contextvàoFragment

Vấn đề

Các onAttach (Activity activity)phương pháp được tán thành trong mức API 23.

Giải pháp

Bây giờ để có được bối cảnh trong Fragmentchúng ta có thể sử dụngonAttach (Context context)

onAttach (Context context)

  • Được gọi khi một mảnh đầu tiên được gắn vào nó context. onCreate(Bundle)sẽ được gọi sau này.

Tài liệu

/**
 * 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);
    }
}

MẪU MÃ

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

}

GHI CHÚ

Chúng tôi cũng có thể sử dụng getActivity()để contextvào Fragments nhưng getActivity()có thể quay lại nullnếu fragmenthiện tại bạn chưa gắn bó với cha mẹ activity,


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

6

Bạn cũng có thể lấy bối cảnh từ inflatertham số, khi ghi đè onCreateView.

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

5

Một cách tiếp cận khác là:

Bạn có thể lấy bối cảnh bằng cách sử dụng:

getActivity().getApplicationContext();

5

để có được bối cảnh bên trong Fragment sẽ có thể sử dụng getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Hãy cẩn thận, để có được Activityliên kết với đoạn sử dụng getActivity(), bạn có thể sử dụng nó nhưng không được khuyến khích nó sẽ gây rò rỉ bộ nhớ.

Tôi nghĩ rằng một aproach tốt hơn phải được lấy Activitytừ onAttach()phương thức:

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

Bạn không nên sử dụng getActivity trong một đoạn để có chế độ xem trừ khi chế độ xem đó là một phần của hoạt động. Tại sao bạn lại thổi phồng một khung nhìn trong một đoạn mà thậm chí không tham chiếu bất cứ thứ gì từ nó?
tyczj

Câu trả lời này là về một cái gì đó khác nhau, bạn đang nói về chế độ xem tìm kiếm để tìm kiếm lượt xem. Activity.findViewByIdĐây chỉ là một phương pháp thuận tiện để tìm kiếm chế độ xem trong chế độ xem nội dung đã đăng ký của hoạt động đó (được đặt qua setContentView). Trong ví dụ đúng của bạn bạn đang gọi View.findViewById, không Activity.findViewById, và bạn đang gọi phương thức trên đúng xem gốc. Vấn đề hoàn toàn khác nhau, và rõ ràng bạn sẽ không thể tìm thấy quan điểm của mình trong chế độ xem hiearchy không giữ quan điểm đó.
JHH

3

getContext() đến trong API 23. Thay thế nó bằng getActivity () ở mọi nơi trong mã.

Xem nếu nó sửa lỗi. Hãy thử sử dụng các phương thức ở giữa mức API mục tiêu và minimun, nếu không, lỗi này sẽ xảy ra.


3

Kể từ mức API 23 có được getContext()nhưng nếu bạn muốn hỗ trợ các phiên bản cũ hơn, bạn có thể sử dụng getActivity().getApplicationContext()trong khi tôi vẫn khuyên bạn nên sử dụng phiên bản hỗ trợ Fragmentđó là android.support.v4.app.Fragment.


2

getActivity() là một đứa trẻ của bối cảnh vì vậy sẽ làm việc cho bạn


2

Sử dụng các đoạn từ Thư viện hỗ trợ -

android.support.v4.app.Fragment

và sau đó ghi đè

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

Bằng cách này, bạn có thể chắc chắn rằng bối cảnh sẽ luôn là một giá trị khác.


2

Bạn có các tùy chọn khác nhau:

  • Nếu minSDK của bạn <= 21, thì bạn có thể sử dụng getActivity(), vì đây là a Context.
  • Nếu minSDK của bạn> = 23, thì bạn có thể sử dụng getContext().

Nếu bạn không cần hỗ trợ các phiên bản cũ thì hãy đi cùng getContext().


2

Đối với Kotlin bạn có thể sử dụng contexttrực tiếp trong các mảnh. Nhưng trong một số trường hợp, bạn sẽ tìm thấy một lỗi như

Kiểu không khớp: kiểu suy ra là Ngữ cảnh? nhưng bối cảnh đã được mong đợi

cho rằng bạn có thể làm điều này

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

Cảm ơn vì đã sử dụng phiên bản Kotlin, hoạt động tốt, tuy nhiên tôi đang cố gắng lấy Ngữ cảnh cho Picasso.get (), với nó và nó không bao giờ hoạt động, tôi đã thử tất cả những gì tôi có thể từ các mẫu ở trên để có được bối cảnh. Tốt nhất tôi nhận được tin nhắn này. Rất nhiều đối số được thông qua ... Xin hãy giúp đỡ. val ctx = bối cảnh ?: return Picasso.get (ctx) .load (chọnGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade

@Ade Trong đoạn của bạn, hãy thử sử dụng "hoạt động !!" thay vì "ctx" và cho tôi biết điều đó có giúp ích hay không
Kishan Solanki

@ KishanSolanki124. Cảm ơn rất nhiều vì đã phản hồi nhanh chóng. Tôi đã thử đề xuất của bạn, với kết quả tương tự - Không hoạt động. Dấu nhắc lỗi chính xác là - Quá nhiều đối số cho niềm vui mở công khai get (): Picasso!. Thông báo này khiến tôi suy nghĩ, có lẽ một cái gì đó khác là lỗi?. Mặc dù vậy, rất vui, đã tìm ra cách để tiếp tục với công việc của tôi bằng cách sử dụng Picasso mà không cần bối cảnh. Cảm ơn một lần nữa.
Ade

2

Trong kotlin chỉ cần sử dụng activitythay vìgetActivity()


2

Với API 29+ trên Kotlin, tôi phải làm

activity?.applicationContext!!

Một ví dụ sẽ là

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

Bối cảnh! = ApplicationContext
Gabriele Mariotti

1

Lý tưởng nhất, bạn không cần phải sử dụng toàn cầu. Đoạn này có các thông báo khác nhau, một trong số chúng là onActivityCreated. Bạn có thể lấy ví dụ của hoạt động trong sự kiện vòng đời này của đoạn.

Sau đó: bạn có thể hủy đăng ký đoạn để có được hoạt động, bối cảnh hoặc nội dung ứng dụng theo ý muốn:

this.getActivity()sẽ cung cấp cho bạn xử lý cho hoạt động this.getContext()sẽ cung cấp cho bạn một xử lý cho bối cảnh this.getActivity().getApplicationContext()sẽ cung cấp cho bạn xử lý cho bối cảnh ứng dụng. Bạn tốt nhất nên sử dụng bối cảnh ứng dụng khi chuyển nó vào db.


1

Cách đơn giản là sử dụng getActivity(). Nhưng tôi nghĩ rằng sự nhầm lẫn lớn của việc sử dụnggetActivity() phương thức để có được bối cảnh ở đây là một ngoại lệ con trỏ null.

Đối với điều này, trước tiên hãy kiểm tra isAdded()phương thức sẽ xác định xem nó có được thêm hay không và sau đó chúng ta có thể sử dụng getActivity()để lấy ngữ cảnh của Hoạt động.


1
Điều này khác với câu trả lời của Ankur Chaudhary như thế nào?
Peter Mortensen

1

Bạn có thể gọi getActivity()hoặc

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

1

Bạn có thể sử dụng phương thức getActivity () để lấy ngữ cảnh hoặc Bạn có thể sử dụng phương thức getContext ().

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

Tôi hy vọng nó sẽ giúp!


1
Có những câu trả lời khác cung cấp câu hỏi của OP và chúng đã được đăng cách đây một thời gian. Khi đăng một câu trả lời xem: Làm thế nào để tôi viết một câu trả lời tốt? , vui lòng đảm bảo bạn thêm một giải pháp mới hoặc giải thích rõ ràng hơn, đặc biệt là khi trả lời các câu hỏi cũ hơn.
help-info.de

0

Phương thức getContext () giúp sử dụng Ngữ cảnh của lớp trong một hoạt động phân đoạn.


0

Tôi nghĩ bạn có thể sử dụng

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

Ngoài ra, bạn có thể sử dụng:

inflater.getContext();

nhưng tôi thích sử dụng

getActivity()

hoặc là

getContext

0

Tôi cần bối cảnh để sử dụng mảng ArrayAd CHƯƠNG IN, khi tôi đang sử dụng lỗi getActivity xảy ra nhưng khi tôi thay thế nó bằng getContext thì nó hoạt động với tôi

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

0

Bạn có thể sử dụng getActivity()hoặcgetContext trong Fragment.

Tài liệu

/**
 * 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();
    }

Mẹo chuyên nghiệp

Luôn luôn kiểm tra if(getActivity!=null)nó có thể là null khi đoạn không được gắn vào hoạt động. Đôi khi thực hiện thao tác dài trong đoạn (như tìm nạp dữ liệu từ phần còn lại api) mất một thời gian. và nếu người dùng điều hướng đến một đoạn khác. Sau đó getActivity sẽ là null. Và bạn sẽ nhận được NPE nếu bạn không xử lý nó.


Đây là một tài liệu về phương thức getActivity (), chỉ để cho thấy rằng những thứ này có thể là null. Ở đây mhost là ví dụ của FragmentHostCallbacklớp.
Khemraj

0

Trên mảnh vỡ của bạn

((Name_of_your_Activity) getActivity()).helper

Hoạt động

DbHelper helper = new DbHelper(this);

0

Mảnh bên trong cho mẫu kotlin sẽ giúp ai đó

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

nếu bạn sử dụng databinding;

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

Trong đó bindView được khởi tạo trong onCreateView như thế này

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

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

0

Phương thức allowContext () là tùy chọn đơn giản nhất

requireContext()

Thí dụ

MyDatabase(requireContext())
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.