背景
我们在设计聊天类 APP 都会有一套完整的用户信息存储机制,用来保存我们的通讯录列表,以及每个用户的头像、昵称、姓名、等等一系列的用户信息,防止我们过多的进行服务器请求,对用户体验很差。这篇文章就简单的给大家创建一套用户信息机制来提供一个简单的思路。
场景如下: 目前我们集成了融云的 IMLib SDK , 融云 IMLib SDK 仅提供了消息数据的存储与查询。用户信息和 UI 界面需要我们自己来维护,而融云的 IMKit 虽然提供了用户信息的管理,但是部分 UI 还是和我们产品设计不符的,那么如何设计一套类似于 IMKit 的用户信息管理机制,就是我们面临的问题。
融云SDK: https://docs.rongcloud.cn/v4/
思考
我们在实现这套机制的时候都需要哪些内容?
- 首先我们要进行存储,存储那就需要维护一个数据库。参考融云 IMKit 发现有下面一个配置
/*!
是否将用户信息和群组信息在本地持久化存储,默认值为NO
@discussion
如果设置为NO,则SDK在需要显示用户信息时,会调用用户信息提供者获取用户信息并缓存到Cache,此Cache在App生命周期结束时会被移除,下次启动时会再次通过用户信息提供者获取信息。
如果设置为YES,则会将获取到的用户信息持久化存储在本地,App下次启动时Cache会仍然有效。
*/
@property (nonatomic, assign) BOOL enablePersistentUserInfoCache;
经过测试以及融云专业技术人员的回答,发现这个配置起到的作用就是本次的用户信息是否会进行数据库存储。
这里的数据库存储是指当此配置生效时,会在本地进行数据库文件的创建。而不生效的时候,是不创建的。如果不创建的话还需要存储的话,那应该就是存储到内存了。 而我们是需要每次登陆都有一些用户信息的,那不需要使用内存了,需要我们进行数据库存储,所以我们需要准备一个 db 的管理类,处理所有的数据库操作。
- 需要一个整体管理用户信息的入口 manager ,用来整理一些基本信息。以及提供用户信息管理的代理入口。
- 需要存储哪些用户信息以及准备对用的 model 类。
- 准备每种对象的缓存类。
实现
以 融云 SDK 为例,以一个用户的 userinfo 为例大体来绘制一下整个流程图。
首先整理一些各个类的用处,大体内容如下:
UserInfoDBHelper: 数据库管理
import <Foundation/Foundation.h>
import "UserInfo.h"
NS_ASSUME_NONNULL_BEGIN
@interface UserInfoDBHelper : NSObject
- (void)createDB;
- (UserInfo )getUserInfo:(NSString )userId;
- (void)refreshUserInfo:(UserInfo *)userInfo;
@end
NS_ASSUME_NONNULL_END
UserInfo: 用户信息模型
import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface UserInfo : NSObject
/**
id
name
url
*/
@end
NS_ASSUME_NONNULL_END
UserInfoCache: 用户信息读取类
import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface UserInfoCache : NSObject
- (UserInfo )getUserInfo:(NSString )userId;
- (void)refreshUserInfo:(UserInfo *)userInfo;
@end
NS_ASSUME_NONNULL_END
UserInfoManager: 对外入口
import <Foundation/Foundation.h>
import "UserInfo.h"
NS_ASSUME_NONNULL_BEGIN
@protocol UserInfoDelegate <NSObject>
- (void)getServerUserInfo:(NSString *)userid;
@end
@interface UserInfoManager : NSObject
@property (nonatomic, weak) id<UserInfoDelegate> delegate;
- (UserInfo )getUserInfo:(NSString )userid;
- (void)refreshUserInfo:(UserInfo *)userInfo;
@end
NS_ASSUME_NONNULL_END
此处提供了一个简单的流程图,供大家参考
解析:
- 首先用户登录,
- 绘制 UI,同时根据用户的 id 来调用 manager.getuserinfo。
- manager 会调用用户的 cache 类来获取 db 内的用户信息。
- 在 cache 调用的时候如果你进行了内存缓存则先在内存缓存中进行查找,然后调用 db.get 进行查找
- db 在首次使用的时候会进行数据库文件检查,不存在则创建并直接用户信息返回空。然后调用 manager 的 delegate 获取用户信息,再拿到用户信息后发送通知来刷新 UI。 6.如果已创建的直接调用 db 的 get。然后刷新 UI。
整体先只提供了一个思路,具体里面的一些内部优化还需实践。
可能用到的技术点:
- SQL 的使用
- 单例类的使用
- GCD 队列
- 通知
- 代理
- 如果使用内存缓存的话还需要保证线程安全。
整体的一个简单思路就是上面供大家参考,待我写完再分享整体代码给大家。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。