有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

ios通过使用查询而不是重复观察单个事件来加速获取我的社交网络应用程序的帖子

我有一组键,这些键指向我的社交网络的post对象,如so/posts/id/(post info)

当我加载posts时,我使用observeSingleEventOfType(.Value)方法加载/posts/0,然后加载/posts/1等

我使用lazyTableView一次加载30个,速度非常慢。是否有任何方法可以使用其中一种查询方法或另一种方法使其更快,即使我必须重新构造JSON树中的数据

我正在重新实现我的应用程序,到目前为止,体验相当不错。就这件事我有点迷恋。提前感谢您的帮助

编辑:

func loadNext(i: Int) { 

    // check if exhists
    let ideaPostsRef = Firebase(url: "https://APPURL")

    ideaPostsRef.childByAppendingPath(i.description).observeSingleEventOfType(.Value, withBlock: {
        (snapshot) in

        if i % 29 == 0 && i != 0 && !self.hitNull { return }
            // false if nil
            // true if not nil
        if !(snapshot.value is NSNull) {
            let postJSON  = snapshot.value as! [String: AnyObject]
            print("GOT VALID \(postJSON)")
            let post = IdeaPost(message: postJSON["message"] as! String, byUser: postJSON["user"] as! String, withId: i.description)
            post.upvotes = postJSON["upvotes"] as! Int
            self.ideaPostDataSource.append(post)
            self.loadNext(i + 1)
        } else {
            // doesn't exhist
            print("GOT NULL RETURNING AT \(i)")
            self.doneLoading = true
            self.hitNull = true
            return
        }
    }
}

该递归函数本质上是从firebase获取键号i的值。如果它是NSNULL,它知道这是最后一个可能加载的post,并且不再加载。如果NSNULL没有被命中,但是i % 29 == 0,那么它将作为基本情况返回,因此一次只加载30篇文章(0篇索引)。当我将doneLoading设置为true时,使用属性观察器调用tableView.reloadData()

下面是我正在获取的数组的示例

"ideaPosts" : [ {
    "id" : 0,
    "message" : "Test",
    "upvotes" : 1,
    "user" : "Anonymous"
  }, {
    "id" : 1,
    "message" : "Test2",
    "upvotes" : 1,
    "user" : "Anonymous"
  } ]

共 (1) 个答案

  1. # 1 楼答案

    更新:我们现在也在AskFirebase episode中讨论这个问题

    从Firebase加载许多项目并不一定要慢,因为您可以通过管道处理请求。但是您的代码使这变得不可能,这确实会导致性能不理想

    在代码中,您从服务器请求一个项目,等待该项目返回,然后加载下一个项目。在简化的序列图中,如下所示:

    Your app                     Firebase 
                                 Database
    
              request item 1  >
                                   S  L
                                   e  o
                                   r  a
                                   v  d
                                   e  i
            <-  return item  1    r  n
                                      g
              request item 2  >
                                   S  L
                                   e  o
                                   r  a
                                   v  d
                                   e  i
                                   r  n
            <-  return item  2       g
              request item 3  >
                     .
                     .
                     .
              request item 30 >
                                   S  L
                                   e  o
                                   r  a
                                   v  d
                                   e  i
                                   r  n
                                      g
            <-  return item 30  
    

    在这种情况下,您将等待往返时间的30倍+从磁盘加载数据所需时间的30倍。如果(为了简单起见)我们说往返需要1秒,从磁盘加载项目也需要1秒,至少需要30*(1+1)=60秒

    在Firebase应用程序中,如果一次性发送所有请求(或至少发送合理数量的请求),您将获得更好的性能:

    Your app                     Firebase 
                                 Database
    
              request item 1  >
              request item 2  >  S  L
              request item 3  >  e  o
                     .             r  a
                     .             v  d
                     .             e  i
              request item 30 >  r  n
                                      g
            <-  return item  1       
            <-  return item  2        
            <-  return item  3  
                     .
                     .
                     .
            <-  return item 30  
    

    如果我们再次假设往返时间为1秒,加载时间为1秒,则等待时间为30*1+1=31秒

    所以:所有请求都通过相同的连接。鉴于此,get(1)get(2)get(3)getAll([1,2,3])之间的唯一区别是帧的一些开销

    我建立了一个jsbin to demonstrate the behavior。数据模型非常简单,但它显示了差异

    function loadVideosSequential(videoIds) {
      if (videoIds.length > 0) {
        db.child('videos').child(videoIds[0]).once('value', snapshot => {
          if (videoIds.length > 1) {
            loadVideosSequential(videoIds.splice(1), callback)
          }
        });
      }
    }
    
    function loadVideosParallel(videoIds) {
      Promise.all(
        videoIds.map(id => db.child('videos').child(id).once('value'))
      );
    }
    

    比较:在我的系统上顺序加载64个项目需要3.8秒,而管道加载(就像Firebase客户端本机那样)需要600毫秒。确切的数字将取决于您的连接(延迟和带宽),但流水线版本应始终显著更快