我有一个片段(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();

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


当前回答

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

}

其他回答

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

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

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

最好的办法是在onAttach被调用时保持活动引用,并在任何需要的地方使用活动引用。

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

@Override
public void onDetach() {
    super.onDetach();
    mContext = null;
}

在哪里调用这个函数?如果在Fragment的构造函数中调用它,它将返回null。

当onCreateView()方法被执行时,只需调用getActivity()。

请按照以下步骤操作。我想这会对你有帮助。

private boolean isVisibleToUser = false;
private boolean isExecutedOnce = false;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_my, container, false);
    if (isVisibleToUser && !isExecutedOnce) {
        executeWithActivity(getActivity());
    }
    return root;
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    this.isVisibleToUser = isVisibleToUser;
    if (isVisibleToUser && getActivity()!=null) {
        isExecutedOnce =true;
        executeWithActivity(getActivity());
    }
}


private void executeWithActivity(Activity activity){
    //Do what you have to do when page is loaded with activity

}

我正在使用OkHttp,我刚刚遇到了这个问题。


@thucnguyen的第一部分是正确的。

这发生在您在另一个线程中调用getActivity()时,该线程在片段被删除后结束。典型的情况是在HTTP请求完成时调用getActivity()(例如Toast)(例如onResponse)。

一些HTTP调用甚至在活动关闭后仍在执行(因为完成HTTP请求可能需要一段时间)。然后,我通过HttpCallback试图更新一些片段字段,并在尝试getActivity()时得到一个空异常。

http.newCall(request).enqueue(new Callback(...
  onResponse(Call call, Response response) {
    ...
    getActivity().runOnUiThread(...) // <-- getActivity() was null when it had been destroyed already

IMO的解决方案是防止当片段不再活跃时发生回调(不仅仅是Okhttp)。

解决办法:预防。

如果你看一下片段的生命周期(更多信息在这里),你会注意到有onAttach(Context Context)和onDetach()方法。它们分别在Fragment属于一个活动之后和停止之前被调用。

这意味着我们可以通过在onDetach方法中控制它来防止回调的发生。

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

    // Initialize HTTP we're going to use later.
    http = new OkHttpClient.Builder().build();
}

@Override
public void onDetach() {
    super.onDetach();

    // We don't want to receive any more information about the current HTTP calls after this point.
    // With Okhttp we can simply cancel the on-going ones (credits to https://github.com/square/okhttp/issues/2205#issuecomment-169363942).
    for (Call call : http.dispatcher().queuedCalls()) {
        call.cancel();
    }
    for (Call call : http.dispatcher().runningCalls()) {
        call.cancel();
    }
}