我有一个片段(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();
一定是我做错了什么,但我不知道是什么。
我正在使用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();
}
}
PJL是对的。
我采纳了他的建议,我是这样做的:
为fragment定义的全局变量:
attachingActivityLock = new Object();
private boolean syncVariable = false;
实现
@Override
onAttach(Activity Activity) {
super.onAttach(活动);
synchronized (attachingActivityLock) {
syncVariable = true;
attachingActivityLock.notifyAll ();
}
}
3.我在线程中包装了我的函数,在那里我需要调用getActivity(),因为如果它将在主线程上运行,我将用步骤4阻塞线程。onAttach()将永远不会被调用。
Thread processImage = new Thread(new Runnable() {
@Override
public void run() {
processImage();
}
});
processImage.start();
4所示。在我的函数中,我需要调用getActivity(),我使用这个(在调用getActivity()之前)
synchronized (attachingActivityLock) {
while(!syncVariable){
try {
attachingActivityLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
如果你有一些UI更新,记得在UI线程上运行它们。我需要更新ImgeView,所以我做了:
image.post(new Runnable() {
@Override
public void run() {
image.setImageBitmap(imageToShow);
}
});