【问题标题】:Android Volley - orientation changesAndroid Volley - 方向变化
【发布时间】:2013-06-20 16:26:29
【问题描述】:

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

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

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

AFAIK 在Volley 中几乎不支持此功能。我对吗?使用Volley 有没有一种简单的方法来解决上述情况?

【问题讨论】:

  • “我如何获得该请求的响应,或者我如何重新连接到它,如果它仍然挂起?” -- 仅仅因为您的应用程序不再处于前台并不会阻止线程运行。是什么让您认为Request 尚未交付给您?为异步操作使用保留的片段,这样无论方向如何变化,您的异步操作都有一个稳定的基础进行通信。
  • 出于某种原因,我的印象是Volley 不会在我们转到后台时提供响应(如Robospice),但你是对的。我们必须致电requestQueue.cancel(...) 停止送货。在stop/resume 期间,我仍在考虑一种很好的简单方法来正确处理重新传递响应。

标签: android android-networking android-volley


【解决方案1】:

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

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

希望这是有用的。

【讨论】:

  • 这个解决方案听起来很有趣。你有没有实现这个的地方。你有遇到什么问题吗?
  • 不要重新打开一个死问题,但我正在寻找一些 Volley + Otto 的例子来进行请求/响应管理,这个家伙把两者融合在一起的一个非常干净的例子 github.com/tslamic/AndroidExamples/tree/master/HttpBinVolley
  • 使用此解决方案,您将如何处理在活动转换时网络响应返回的可能性(在第一个活动的 onDestroy 和新定向活动的 onCreate 之间)?在这里,任何活动都不会注册到总线并等待事件。 @Producer 方法可能会解决这个问题,但它们似乎并不适合用作通用网络缓存,并且与原始模式不完全一致。
  • @kyle-ivey :我在stackoverflow.com/a/23686294/507339 的回答中有一个解决方案。这是a 解决方案,但可能不是唯一的解决方案。 PS:我首先考虑了Producer-方法,但是因为不符合我的模式而放弃了它。
【解决方案2】:

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

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

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

@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
}

这里是the ResponseBuffer-class的实现。

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

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

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

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

请参阅 github-repository OttoVolleyDoneRight 以获取带有用于测试的 UI 的完整示例。

【讨论】:

    【解决方案3】:

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

    @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;
    }
    

    【讨论】:

    • 很老的话题,但这是最好的模式
    【解决方案4】:

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

    所以我的解决方案是:点击 Btn 时首先锁定屏幕方向,当 Volley 响应到来时解锁屏幕方向...

    ...........这里 on click---lockDeviceRotation(true) //锁定 on Response--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);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-20
      • 1970-01-01
      相关资源
      最近更新 更多