17

我们如何处理方向变化,Activities/Fragments停止/恢复使用Volley

我知道对于GET请求,响应将被缓存,并且我们第二次尝试发出该请求时,我们将获得缓存响应。(如果服务器发送正确的 HTTP 标头)

但是呢POST?假设我提出了一个POST请求(即注册,我只想发生一次),我的应用程序进入后台,请求在应用程序仍在后台时完成,然后我回到应用程序。如果它仍然挂起,我如何获得ResponseRequest,或者我如何重新连接它?

AFAIK 中几乎没有对此的支持Volley。我对吗?有没有一种简单的方法来解决上述场景,使用Volley

4

4 回答 4

8

Volley 没有为此提供开箱即用的机制,但是您可以查看 Square 的 Android Otto 库,它可以优雅地处理您的情况。

为 Volley 请求实现侦听器,以便它将成功的响应发布到总线上,并包装在诸如“RegisterEventSuccess”之类的事件对象中(您自己定义)。让您的活动或片段使用 Otto 的 @Subscribe 机制订阅此事件类型。如果 - 例如 - 一个 Activity 启动 Volley 请求并由于屏幕方向更改而死,另一个 Activity 实例(也注册到 Otto 总线)然后可以接收包含 Volley 请求响应的事件。

希望这很有用。

于 2013-08-05T11:53:17.007 回答
4

我现在试图解决@kyle-ivey 的担忧,因为响应到达两者之间onPause()并被onResume()丢弃。这是一个真正的问题,因为我在实时应用程序中经历过。

我的方法建立在 Thomas Moerman 的答案中实现的事件总线模式之上,尽管我已经从头开始重新实现了一个示例应用程序。它依赖于Otto 事件总线库GsonVolley。它是在 IntelliJ 13 Ultimate 中使用 Maven 解决依赖关系实现的。

解决方案:我在前面的答案中添加了一个充当 HTTP 响应缓冲区的类,它负责在 Activity 转换时监听事件。完成后,活动会主动轮询在活动与事件总线断开连接时可能已经到达的任何响应。它以如下方式在事件总线注册旁边的onPause和事件中挂接/关闭:onResume

@Override
protected void onPause() {
    super.onPause();
    ServiceLocator.ResponseBuffer.startSaving(); // The buffer takes over
    ServiceLocator.EventBus.unregister(this);    // Unregistering with Otto
}

@Override
protected void onResume() {
    ServiceLocator.EventBus.register(this);         // Re-registering
    ServiceLocator.ResponseBuffer.stopAndProcess(); // Process any responses buffered
}

这是ResponseBuffer-class的实现。

警告 1:如果该活动从未恢复,并且在任何未来的活动中都stopAndProcess()没有stopAndPurge()被调用,则缓冲区可能是内存泄漏的来源。请注意您如何使用它。一个安全的模式是stopAndProcess()在 你onResume()所有活动中都有。

警告 2:它不是线程安全的。如果在它开始保存和取消注册事件总线之间的线路上发生上下文切换,它可能会收到两次或零次事件。

该示例包含一些 UI 和支持类形式的测试代码,但如果您想在单独的项目中使用此模式,则需要的主要类是以下包中的类:

  • nilzor.ottovolley.core
  • nilzor.ottovolley.messages

有关用于测试的 UI 的完整示例,请参阅 github-repository OttoVolleyDoneRight 。

于 2014-05-15T18:44:49.050 回答
1

有一个简单的解决方案可以解决我使用 Volley 库从网络下载数据的问题。如果您的应用由于 Google 的建议而使用了 Fragment,那么如果用户在加载数据时旋转屏幕,您应该采取一切措施来防止崩溃,并将其放入Fragment(-s)setRetainInstance(true);的方法中。onCreateView

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View theView = inflater.inflate(R.layout.fragment_studios, container, false);
    setRetainInstance(true);
    lvStudios = (ListView) theView.findViewById(R.id.lvStudios);
  return theView;
}
于 2015-09-13T12:43:33.920 回答
0

假设你有登录按钮,通过 volley 点击 Btn 你的调用服务器,突然如果屏幕方向改变,volley 重启,应用程序崩溃..

所以我的解决方案是:点击 Btn 第一次锁定屏幕方向,当 Volley 响应来你解锁屏幕方向...

......点击此处---lockDeviceRotation(true) //锁定响应--lockDeviceRotation(false) //解锁

public void lockDeviceRotation(boolean value) {
    if (value) {
        int currentOrientation = getResources().getConfiguration().orientation;
        if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
        }
    } else {
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        }
    }
}
于 2019-09-18T07:37:50.063 回答