当我在选项卡之间快速移动并快速使用 ViewPager 时,它会崩溃



我在应用程序中使用ViewPagerTabs。当我测试应用程序并在tabs之间快速移动时,它崩溃了。我有一个Fragment和 3 个tabs,每个tabFragment的内容都会发生变化.内容是来自使用Retrofit 2API的数据。我也使用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因此FragmentViewPager可以销毁然后分离(在此处查看我的演示(。
在每个Fragment中,您运行一个异步任务(使用Retrofit(,并在任务完成后更新UI。
如果您更新之前销毁的片段的 UI,您将获得异常

解决 方案

有一些方法可以解决您的问题

取消
  • 接收异步请求的回调或取消请求。
  • 异步任务完成后更新UI前,检查片段是否分离
  • 不要让你的片段被破坏,你可以使用 setOffscreenPageLimit

根据您的情况,您可以选择 1 种方式 3 种

请求完成后,片段已被分离。例如,您可以取消((调用,而不是等待响应然后将其丢弃。

@Override
public void onDestroy() {
connection.cancel();
super.onDestroy();
}

请注意,回调仍将被触发,但会使用onFailure()而不是onResponse()

最新更新