避免在屏幕方向更改时重新启动Fragment中的异步任务

4
我正在开发一款Android平板应用程序,需要实现屏幕方向(横屏和竖屏)功能。当屏幕方向改变时,片段异步任务将重新启动(有时应用程序会崩溃)。我需要停止重启异步任务并重新请求数据。想要将现有的JSON数据加载到新屏幕中。 非常感谢您的帮助。
解决方案: android:configChanges="keyboardHidden|orientation|screenSize"不能起作用,因为我使用了一个片段类。

屏幕方向变化会导致onCreate()方法被调用。如果你想避免asyncTask重新启动,可以将其放在onResume()方法中,或者尽量避免在屏幕方向变化时调用onCreate()方法。 - phemt.latd
或者保存异步任务的状态,然后在重新启动时,从你离开的地方继续工作。 - Massimo
3个回答

1
您可以通过在片段上使用setRetainInstance方法,轻松避免片段的“重新创建”。

public void setRetainInstance(boolean retain)

控制片段实例是否在Activity重新创建(例如从配置更改)时保留。这仅适用于不在后堆栈中的片段。如果设置,则当Activity重新创建时,片段生命周期将略有不同:
• onDestroy()不会被调用(但onDetach()仍将被调用,因为片段正在从其当前Activity中分离)。
• onCreate(Bundle)不会被调用,因为片段不会被重新创建。
• onAttach(Activity)和onActivityCreated(Bundle)仍将被调用。

参考链接

例如,您可以在onCreateView方法中使用它,如下所示:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    setRetainInstance(true);
    // ... more of your code
}

当包含该片段的 Activity 仍在重新创建时,片段实例将保持不变,并将重新附加到新的 Activity 上。

请注意,即使使用 setRetainInstance,onCreateView 方法仍将始终被调用(在方向更改时),因为片段需要根据新的空间/尺寸填充视图,因此如果您从该方法执行异步任务,则应考虑将其移动到 onCreate 方法中(仅会执行一次),以避免每次方向更改都进行“重新启动”。

希望这有所帮助。


1

看起来这种方法不太推荐。如果你在onCreate()方法中初始化并执行你的AsyncTask,我建议使用this方法。基本上它包括保存你不需要在运行时配置更改时重新启动的数据,这样你可以在onCreate()方法中处理它们,并决定你想从之前的横屏模式中保留哪些信息,哪些应该重新启动。


1

你可能会发现一些技巧(包括静音配置更改或保留实例)以某种方式使其工作,但是AsyncTask非常危险,大多数时候应该尽可能远离它。

如果当前AsyncTask的工作是在Fragment中显示网络加载的某些数据,则建议使用AsyncTaskLoader。 javadoc中的示例应该可以给您一个很好的实现思路。

这将允许网络请求继续进行,同时在准备好处理结果时(例如不在旋转期间),向UI(即LoaderManager.LoaderCallbacks)通知结果,并且还将缓存结果,以便每次需要数据时不会重新发出网络请求。

有很多第三方库试图解决这个非常普遍的问题,Loader也有其复杂性,但如果我正确理解了您的用例,它应该是您需要的。

不要忘记,无论您选择哪种解决方案,都必须考虑在加载数据之前、期间和之后发生的旋转(活动销毁/重新创建)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接