Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách sử dụng Context trong Fragment Android

Giới thiệu

Fragment không kế thừa từ Context, nhưng cần Context để truy cập tài nguyên, hệ thống,inflate layout, v.v. Có nhiều cách lấy Context trong Fragment, mỗi cách có vòng đời và rủi ro khác nhau.

Các cách lấy Context

Phương thứcTrả vềVòng đờiRủi ro
getContext()Context của Activity chứa (API 23+)Gắn với Fragment lifecycleNull nếu Fragment chưa attach/detached
getActivity()Activity chứa (là Context)Gắn với Activity lifecycleNull nếu detached, leak nếu giữ reference lâu
requireContext()Non-null Context (API 23+)Giống getContext()Ném IllegalStateException nếu null
requireActivity()Non-null ActivityGiống getActivity()Ném IllegalStateException nếu null

Ví dụ minh họa

Layout Activity chứa 2 Fragment (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <fragment
        android:name="com.example.myapplication.FirstFragment"
        android:id="@+id/fragment_first"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <fragment
        android:name="com.example.myapplication.SecondFragment"
        android:id="@+id/fragment_second"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

FirstFragment - Hiển thị Context (src/FirstFragment.java)

package com.example.myapplication;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FirstFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_context, container, false);
        TextView tv = view.findViewById(R.id.tvContextInfo);

        // Cách 1: getContext() - có thể null
        Context context = getContext();
        String info = "getContext(): " + (context != null ? context.getClass().getSimpleName() : "null");

        // Cách 2: getActivity() - có thể null
        info += "\ngetActivity(): " + (getActivity() != null ? getActivity().getClass().getSimpleName() : "null");

        // Cách 3: requireContext() - crash nếu null (an toàn hơn cho logic bắt buộc)
        try {
            info += "\nrequireContext(): " + requireContext().getClass().getSimpleName();
        } catch (IllegalStateException e) {
            info += "\nrequireContext(): IllegalStateException";
        }

        tv.setText(info);
        return view;
    }
}

Layout Fragment (res/layout/fragment_context.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/tvContextInfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp" />

</LinearLayout>

SecondFragment (src/SecondFragment.java)

package com.example.myapplication;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SecondFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_context, container, false);
    }
}

MainActivity.java

package com.example.myapplication;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

Best Practices

  • Ưu tiên requireContext()/requireActivity() khi Context/Activity là bắt buộc cho logic (crash sớm thay vì NullPointerException sau).
  • Không giữ reference Context/Activity trong field lâu dài → memory leak.
  • Dùng getContext() cho việc inflate layout, truy cập resource, SharedPreferences.
  • Dùng getActivity() khi cần gọi phương thức Activity (startActivity, finish, getSupportFragmentManager).
  • Trong onAttach(), onCreate(), onViewCreated(): Context đã sẵn sàng.
  • Trong onDetach(), onDestroy(): Context có thể null.

Chạy ứng dụng

Nhấn Run. Fragment đầu hiển thị thông tin Context lấy được bằng các cách khác nhau.

Cách sử dụng Context trong Fragment Android

Lưu ý AndroidX Fragment 1.3+

// Fragment ktx extensions
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentKt;

// requireContext(), requireActivity(), requireFragmentManager(), requireArguments()
// Tất cả đều ném IllegalStateException với message rõ ràng nếu null