我在应用程序中使用ViewPager
和Tabs
。当我测试应用程序并在tabs
之间快速移动时,它崩溃了。我有一个Fragment
和 3 个tabs
,每个tab
Fragment
的内容都会发生变化.内容是来自使用Retrofit 2
的API
的数据。我也使用FragmentStatePagerAdapter
.
这是我的Logs
.
java.lang.IllegalStateException: Fragment MainFragment{423155d0} not attached to Activity
at android.support.v4.app.Fragment.getResources(Fragment.java:715)
at com.webstore.footballscores.Fragments.MainFragment$4.onResponse(MainFragment.java:393)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5641)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1288)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1104)
at dalvik.system.NativeStart.main(Native Method)
此行中的此错误
res = getResources();
其余代码.
connection.enqueue(new Callback<List<FixturesObject>>() {
@Override
public void onResponse(Call<List<FixturesObject>> call, Response<List<FixturesObject>> response) {
if (!response.isSuccessful()) {
progressDoalog.dismiss();
Toast.makeText(getActivity(), "Something went wrong , Please refresh again", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
}, 4000);
} else if (response.isSuccessful()) {
i=1;
imageView.setVisibility(View.GONE);
progressDoalog.dismiss();
if (isAdded()) {
res = getResources();
String[] teamEngList = res.getStringArray(R.array.team_english);
String[] teamArabList = res.getStringArray(R.array.team_arabic);
}
if (response.body().get(i).getLeagueId().equals("109")) {
for (int j = 0; j < teamEngList.length; j++) {
if (teamEngList[j].equals(response.body().get(i).getMatchAwayteamName())) {
response.body().get(i).setMatchAwayteamName(teamArabList[j]);
} else if (teamEngList[j].equals(response.body().get(i).getMatchHometeamName())) {
response.body().get(i).setMatchHometeamName(teamArabList[j]);
}
}
spainObject.add(response.body().get(i));
listDataChild.put(listDataHeader.get(listDataHeader.size() - 1), spainObject);
}
adapter.clearData();
adapter.addData(listDataHeader, listDataChild);
}
我该如何修复此错误。 谢谢
当您滑动时,ViewPager
会为可见页面创建片段,并为不可见的页面创建片段。您的网络请求独立于该进程。当网络请求完成并且相应的片段被销毁时,您正在尝试调用getResources()
但此调用需要具有上下文。如果片段已被销毁,则片段不再具有上下文,因此,您会出现崩溃。
若要解决此问题,需要在进行该调用之前确保上下文可用。试试这个:
if (!isAdded()) return;
res = getResources();
//...
一些文档: https://developer.android.com/reference/android/support/v4/app/Fragment#isAdded((
您收到异常的原因
您正在使用FragmentStatePagerAdapter
因此Fragment
ViewPager
可以销毁然后分离(在此处查看我的演示(。
在每个Fragment
中,您运行一个异步任务(使用Retrofit(,并在任务完成后更新UI。
如果您更新之前销毁的片段的 UI,您将获得异常
解决 方案
有一些方法可以解决您的问题
取消- 接收异步请求的回调或取消请求。
- 异步任务完成后更新UI前,检查片段是否分离
- 不要让你的片段被破坏,你可以使用 setOffscreenPageLimit
根据您的情况,您可以选择 1 种方式 3 种
请求完成后,片段已被分离。例如,您可以取消((调用,而不是等待响应然后将其丢弃。
@Override
public void onDestroy() {
connection.cancel();
super.onDestroy();
}
请注意,回调仍将被触发,但会使用onFailure()
而不是onResponse()