我有一个片段(F1)与这样的公共方法

public void asd() {
    if (getActivity() == null) {
        Log.d("yes","it is null");
    }
}

是的,当我调用它(从活动),它是空…

FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();

一定是我做错了什么,但我不知道是什么。


当前回答

Commit调度事务,也就是说,它不会立即发生,而是在下一次主线程准备就绪时在主线程上进行调度。

我建议加一个

onAttach(Activity activity)

方法,并在它上面放一个断点,看看它什么时候相对于你对asd()的调用被调用。您将看到它在您调用asd()退出的方法之后被调用。onAttach调用是片段附加到其活动的地方,从这一点上getActivity()将返回非空(注意还有一个onDetach()调用)。

其他回答

在commit()之后调用回调函数的顺序:

无论你在commit()之后手动调用什么方法 onAttach () onCreateView () onActivityCreated ()

我需要做一些涉及一些视图的工作,所以onAttach()不适合我;它坠毁。所以我移动了我的代码的一部分,设置一些参数在一个方法调用后立即提交()(1.),然后在onCreateView()(3.)内处理视图的代码的另一部分。

自Android API级别23起,onAttach(Activity Activity)已弃用。你需要使用onAttach(Context Context)。http://developer.android.com/reference/android/app/Fragment.html onAttach (android.app.Activity)

Activity是一个上下文,所以如果你可以简单地检查上下文是否是一个Activity,并在必要时强制转换它。

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity a;

    if (context instanceof Activity){
        a=(Activity) context;
    }

}

编写一个通用方法,确保永远不会得到空Activity。

public class BaseFragment extends Fragment {
    private Context contextNullSafe;

     @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
         /*View creation related to this fragment is finished here. So in case if contextNullSafe is null
         * then we can populate it here.In some discussion in - https://stackoverflow.com/questions/6215239/getactivity-returns-null-in-fragment-function
         * and https://stackoverflow.com/questions/47987649/why-getcontext-in-fragment-sometimes-returns-null,
         * there are some recommendations to call getContext() or getActivity() after onCreateView() and
         * onViewCreated() is called after the onCreateView() call every time */
        if (contextNullSafe == null) getContextNullSafety();
    }


   @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        contextNullSafe = context;
    }

    /**CALL THIS IF YOU NEED CONTEXT*/
    public Context getContextNullSafety() {
                if (getContext() != null) return getContext();
                if (getActivity() != null) return getActivity();
                if (contextNullSafe != null) return contextNullSafe;
                if (getView() != null && getView().getContext() != null) return getView().getContext();
                if (requireContext() != null) return requireContext();
                if (requireActivity() != null) return requireActivity();
                if (requireView() != null && requireView().getContext() != null)
                    return requireView().getContext();
                
                return null;
            
        }

    /**CALL THIS IF YOU NEED ACTIVITY*/
    public FragmentActivity getActivityNullSafety() {
        if (getContextNullSafety() != null && getContextNullSafety() instanceof FragmentActivity) {
            /*It is observed that if context it not null then it will be
             * the related host/container activity always*/
            return (FragmentActivity) getContextNullSafety();
        }
        return null;
    }

另一个好的解决方案是使用Android的LiveData和MVVM架构。 你可以在你的ViewModel中定义一个LiveData对象,并在你的片段中观察它,当LiveData值发生变化时,只有当你的片段处于活动状态时,它才会通知你的观察者(在这种情况下是片段),所以这将保证你的UI工作,只有当你的片段处于活动状态时才会访问活动。这是LiveData的一个优势

当然,当这个问题第一次被提出时,还没有LiveData。我把这个答案留在这里,因为在我看来,这个问题仍然存在,它可能会对某些人有所帮助。

在onActivityCreated()中调用getActivity()方法