1. How to ensure the response speed of messages in the case of weak networks

Weak network

Weak network about the user experience of the problem: into a chat window, has been circling, the experience is very poor.

scenario

  1. There is no network

The state of no network can be judged, the network is not normal only the DB has what to show, maybe the message fault. But it’s understandable.

  1. The network is good

In this case, the message is perfectly fine to display, even if every time you enter the session, it is ok. But to consider for throttling, save electricity.

  1. Weak network

This time may be the client problem: such as 2G network, 3G network, clearly is 4G but only one, two cell signal; Wifi is connected, but the Internet is not good.

The solution

If there is a network: Ensure that data is in order and not lost or duplicated. We can eliminate or reduce requests for requested messages.

The scheme idea of this paper is based on algorithm: merge interval

A message model

For example: our current chat display message is [100-200], after a long time now the message is 300, then we enter the session back to pull 20, namely [280-300], then our local block has two [100-200],[280-300]. Slide up to load 20 pieces of history data, and the second block becomes [260-300]. If you continue loading history data, the second becomes [200-300]. At this point, the second is merged with the first, and the local block has only one, [100-300] message.

The next time you look at the history message, the message in [100-300] does not need to request the network.

We keep merging with the original interval, making the local confidence interval bigger and bigger for us to use.

The actual scene

  1. Push: The server will push 10 messages when the APP is started or the network is disconnected and reconnected. At this time, it also needs to merge with the largest local block.
  2. Go into the chat window, if it is merged, directly display. If not, you need to pull the network to display and merge the blocks.
  3. Pull history messages: Needs to be merged with the memory list as well as with the previous DB block.

The effect

  1. Read the message, no longer need to rely on the network. Reduce network interaction.
  2. The experience is very good when the network is weak or there is a network in the local confidence interval.

Ii. How to ensure that the messages on the interface are not lost, repeated and displayed in an orderly manner

scenario

  1. After entering the session, the DB message is displayed first (it may be less than one screen), and then the server message is pulled (it may coincide with the message displayed by the DB, or it may be the latest 20 messages). After the normal display, the historical message can be loaded
  2. The messages entered by the search are intermediate messages, which can be loaded down from the top with history messages, or up from the bottom with new messages.
  3. After the network is disconnected and reconnected, the server pushes 10 messages.

What we did before

There’s a variable that determines whether to pull from the top, or whether to pull from the bottom. The pulled message needs to be merged with the message displayed on the interface. If it is pulled from the top, it is inserted into the first position of the original array; If it’s a bottom pull, it appends to the end of the array.

The actual situation

Duplicate messages are possible. For example, WHEN I pull 10 pieces of DB, there are 20 pieces of network back. The 20 pieces of network back may contain 10 pieces of DB, may not include 10 pieces that coincide with DB, or may have no intersection. By inserting to the first position or appending to the last position, no longer reliable. The end is appended only if the inserted message is greater than the largest one in the cache. The message is lost.

An occasional bug appears

  1. Re-install login, open the message, found that part of the message is not pulled, exit and re-enter the good
  2. User A calls user B (user B is online on the desktop) and hangs up. User B clicks the notification message to enter the session box, but finds that the message is not pulled and the page is blank
  3. Kill the process, enter the APP, and quickly click a session. The message will be lost on the interface and cannot be pulled. The list is displayed again.
  4. In iOS 14.3 system, click the notification message in the lock screen and enter the security password to enter the session box, but the message is not pulled (occasionally).

thinking

Both the original message and the pull message are ordered. The double pointer algorithm is used to combine two ordered arrays. Do not worry about message duplication, overlap, concatenation whether there is a problem.

/* Merge two ordered messages: if there are duplicates, take one and discard the other */
- (void)mergeCacheMsgs:(BLConversation *)conversation newMsgs:(NSArray *)newMsgs{
    NSMutableArray * cacheMsgs = conversation.messages;
    
    NSMutableArray * resultMsgs = [[NSMutableArray alloc] initWithCapacity:cacheMsgs.count+newMsgs.count];
    
    NSInteger i = 0;
    NSInteger j = 0;
    NSInteger k = 0;
    
    while (i<cacheMsgs.count && j<newMsgs.count) {
        NSInteger cacheMsgId = [[cacheMsgs[i] messageId] integerValue];
        NSInteger newMsgId = [[newMsgs[j] messageId] integerValue];
        if (cacheMsgId<newMsgId) {
            resultMsgs[k] = cacheMsgs[i++];
        }else if (cacheMsgId>newMsgId){
            resultMsgs[k] = newMsgs[j++];
        }else{
            resultMsgs[k] = cacheMsgs[i];
            i ++;
            j ++;
        }
        k ++;
    }
    
    while (i<cacheMsgs.count) {
        resultMsgs[k++] = cacheMsgs[i++];
    }
    
    while (j<newMsgs.count) {
        resultMsgs[k++] = newMsgs[j++];
    }
    
    [conversation.messages removeAllObjects];
    [conversation.messages addObjectsFromArray:resultMsgs];
    [self reloadConversationMessagesTimeline:conversation];
}
Copy the code

conclusion

  1. Ordered array merge application, the code is clear, easy to read.
  2. There will be no duplication of messages, no need to rely on dictionaries.
  3. There is no variable to determine whether to concatenate to the first position or append to the end.
  4. Time complexity: Generally, there are about 20 new messages, and the time complexity is O(N +20), without any performance problems.

Three, using dichotomous algorithm to achieve fast message search

scenario

The message has been read, heard, and withdrawn. You need to find the message object in memory and modify its properties.

Use a dictionary for message lookup

Arrays combined with dictionaries enable fast lookup of messages, but require the maintenance of an additional dictionary. The message returns, sends the message, receives the push message, synchronizes the message needs to plug into the dictionary first; Exiting the current session requires removing messages from the dictionary.

thinking

Careful analysis shows that the array displays messages in order, using binary lookup, very efficient, no need to maintain additional dictionaries.

- (BLMessage *)binSearchMsgWithMsgId:(NSString *)messageId{
    NSInteger mid = 0;
    
    NSInteger l = 0;
    NSInteger r = self.messages.count-1;

    while (l<=r) {
        mid = (l+r)>>1;
        if ([messageId integerValue]>[[self.messages[mid] messageId] integerValue]) {
            l = mid+1;
        }else if ([messageId integerValue]<[[self.messages[mid] messageId] integerValue]){
            r = mid-1;
        }else{
            return self.messages[mid];
        }
    }
    
    return nil;
}
Copy the code

summary

In complex scenarios, maintaining one less global variable makes the code much less complex.