我在一个活动的一个片段中使用AsyncTask。
AsyncTask工作正常,但在屏幕旋转时,它会丢失对activity
的引用,变量返回NullPointerException
,因此应用程序崩溃。
我查看了类似的问题,例如this,this,this和this,但我不认为使用配置更改黑客是解决方案。
可能导致应用程序崩溃的代码(根据LogCat,NullPointerException
位于以下行):
Context context = MyActivity.this.getApplicationContext();
我要在驻留在activity和fragment类之外的另一个函数中传递上下文。
提前谢谢。
更新:我的LogCat
09-29 09:40:53.415: E/AndroidRuntime(21997): FATAL EXCEPTION: AsyncTask #2
09-29 09:40:53.415: E/AndroidRuntime(21997): java.lang.RuntimeException: An error occured while executing doInBackground()
09-29 09:40:53.415: E/AndroidRuntime(21997): at android.os.AsyncTask$3.done(AsyncTask.java:278)
09-29 09:40:53.415: E/AndroidRuntime(21997): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
09-29 09:40:53.415: E/AndroidRuntime(21997): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
09-29 09:40:53.415: E/AndroidRuntime(21997): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
09-29 09:40:53.415: E/AndroidRuntime(21997): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
09-29 09:40:53.415: E/AndroidRuntime(21997): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
09-29 09:40:53.415: E/AndroidRuntime(21997): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
09-29 09:40:53.415: E/AndroidRuntime(21997): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
09-29 09:40:53.415: E/AndroidRuntime(21997): at java.lang.Thread.run(Thread.java:856)
09-29 09:40:53.415: E/AndroidRuntime(21997): Caused by: java.lang.NullPointerException
09-29 09:40:53.415: E/AndroidRuntime(21997): at com.example.CommonClasses.CommonFunctions.readFile(CommonFunctions.java:262)
09-29 09:40:53.415: E/AndroidRuntime(21997): at com.example.CommonClasses.CommonFunctions.readFileContents(CommonFunctions.java:308)
09-29 09:40:53.415: E/AndroidRuntime(21997): at com.example.android.AvailabilityFragment$AvailabilityData.doInBackground(AvailabilityFragment.java:160)
09-29 09:40:53.415: E/AndroidRuntime(21997): at com.example.android.AvailabilityFragment$AvailabilityData.doInBackground(AvailabilityFragment.java:1)
09-29 09:40:53.415: E/AndroidRuntime(21997): at android.os.AsyncTask$2.call(AsyncTask.java:264)
09-29 09:40:53.415: E/AndroidRuntime(21997): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
答案 0 :(得分:0)
试试这种方式
<activity
android:name=".ActivityName"
android:configChanges="orientation|screenSize|keyboardHidden"/>
答案 1 :(得分:0)
有很多解决方案。一个简单的方法就是使用所谓的“保留”片段。这是一种在某些Google示例中使用的方法。保留片段没有UI,并且在方向更改时保持不变。这通常被定义为您的活动的静态内部类,如下所示:
public static class RetainFragment extends Fragment {
private static final String TAG = "RetainFragment";
public RetainFragment() {}
public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
if (fragment == null) {
fragment = new RetainFragment();
}
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
}
然后,将您的AsyncTask放入RetainFragment中。调用onPostExecute
时,您只需使用片段的getActivity()
方法获取附加到的活动。
希望有所帮助,让我知道是否还有一些困惑!
修改 Here是保留片段的Google样本
编辑2:(根据评论)
public class A {
// This class holds a reference to it's outer A instance. It can be
// accessed using A.this.
public class innerClassA {
//...
}
// This class does not hold a reference to it's outer A instance.
public static class innerClassB {
//...
}
}
编辑3:在评论中,我最终还是编写了完整的代码。对于任何感兴趣的人:
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
Button b = (Button) findViewById(R.id.aaa);
b.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
RetainFragment retainFragment =
RetainFragment.findOrCreateRetainFragment(getFragmentManager());
retainFragment.loadAsync();
}
});
}
private void handleResponse(String response) {
// do something with the response...
}
public static class RetainFragment extends Fragment {
private static final String TAG = "RetainFragment";
public RetainFragment() {
}
public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
if (fragment == null) {
fragment = new RetainFragment();
fm.beginTransaction().add(fragment, TAG).commit();
}
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
private void loadAsync() {
new AsyncTask<Void, Void, String>() {
@Override protected String doInBackground(Void... params) {
// Do some work...
return null;
}
@Override protected void onPostExecute(String response) {
MyActivity myActivity = (MyActivity)getActivity();
if (myActivity != null) {
myActivity.handleResponse(response);
}
}
}.execute();
}
}
}