【问题标题】:Android - sending SeekBar values via TCPAndroid - 通过 TCP 发送 SeekBar 值
【发布时间】:2014-03-13 04:12:16
【问题描述】:

我目前正在开发一个与其他设备通信的 android 应用程序,它就像一个服务器。基本上要构建应用程序的视图,我首先必须通过 TCP 连接向服务器发送查询以获取信息。我(成功)在异步任务的帮助下执行了这些查询:

    private class TCPQuery extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... params) {
                //connect the socket send the query and receive feedback
        }

        @Override
        protected void onPostExecute(String result) {
                //parse server feedback and build the view
        }
    }

这种方法适用于在应用程序生命周期内仅进行几次的单个查询。我在实施时遇到的问题如下: 应用程序中的某个视图,包含搜索栏。所以基本上,seekbar 值的每次变化(每次 onProgressChange 方法触发)都必须发送到服务器(这次没有反馈),因此它可以跟踪实际值。

您将如何实施?当然,在主线程上可能不做android中的联网。但是这里每次值变化时建立连接、发送消息并关闭连接是不行的。仅将条形滑动一点点就会在瞬间产生十几个这样的调用。

我尝试通过实现服务来解决这个问题。该服务有自己的套接字来与服务器通信。我会将套接字连接到服务器并使其保持打开状态,这样我就可以在搜索栏发生更改时调用服务的发送方法。但这似乎干扰了我之前提到的其他查询(使用异步任务执行的查询)。当另一个处于活动状态时,我无法连接。现在我不确定我的服务实现是否很糟糕,或者我是否在这里误解了一个关键的网络概念。

我曾想过只在StopTrackingTouch 上发送数据,但这并不是我真正想要的。任何帮助将不胜感激!

【问题讨论】:

    标签: android sockets service tcp seekbar


    【解决方案1】:

    使用系统时钟检查最后一个查询的发送时间,并且在特定时间过去之前不要发送另一个查询。 您可以根据需要更改搜索栏的值,但查询将仅每 X 毫秒发送一次。

    static long sendInterval = 600; //milliseconds
    
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
      long nextSend = 0;    
    }
    
    @Override
    public void onProgressChanged(......) {
      if (nextSend < uptimeMillis()) {
      ...send the query and parse feedback...
      nextSend = uptimeMillis() + sendInterval ;
      }
    

    以 nextSend = 0 开头,因此第一次查询将立即发送。 根据服务器的响应时间选择 sendInterval 值。从一个高值开始并减少,直到您看到一切正常。 如果查询本身和响应很小(几个字节)考虑使用 UDP 而不是 TCP,它会更快,您可以使用较小的 sendInterval 值。

    【讨论】:

      【解决方案2】:

      其他方式,不同的,也许更好: 由于响应时间可能会因网络流量、查询复杂性和服务器负载而有很大差异,因此您可以使用布尔标志。在发送查询之前将其设置为 False,在解析响应后将其设置为 True。在 If 语句中使用它:

      @Override
      public void onStartTrackingTouch(SeekBar seekBar) {
        boolean readyForQuery = true;    
      }
      
      @Override
      public void onProgressChanged(......) {
        if (readyForQuery) {
        readyForQuery = false;
        <...asyncronous send the query, parse feedback and set readyForQuery=true;...>
        }
      

      还要考虑最坏的情况:当服务器关闭并且根本不会响应查询时。 请注意在合理的时间后和/或查询代码生成异常时找到一种方法将标志设置为 True,否则即使服务器再次启动,您也不会得到进一步的响应。

      【讨论】:

      • 关于消息延迟的问题:有一个方面我想解决。这样我们可以防止服务器过载和断开连接,但是在快速搜索栏更改的情况下存在缺陷。假设我们每 200 毫秒发送一条消息,以免服务器过载。当用户停止滑动时,UI 中的值通常与发送到服务器的最后一个值不完全同步,因为用户会在发送最后一个查询的同一时刻停止滑动是不可思议的。所以基本上在 onStopTrackingTouch 中发送最后的值变化?
      • 但这可能意味着,我们必须再等几毫秒才能在 onStopTrackingTouch 中发送最后一条消息。假设我们在时间 t 停止滑动,但我们仍然需要额外等待 50 毫秒,直到下一次查询。计算差异并将其延迟一点是我解决这个问题的最佳选择吗?
      • 看handler.postDelayed或者handler.postAtTime,你可以安排代码在一定的毫秒后或者特定的uptimeMillis()时间运行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-28
      • 1970-01-01
      • 2014-01-16
      • 2016-02-20
      • 2016-03-02
      • 1970-01-01
      相关资源
      最近更新 更多