美文网首页
使用Rxswift+Realm实现Livedata+Room的效

使用Rxswift+Realm实现Livedata+Room的效

作者: Openwit | 来源:发表于2020-11-25 08:33 被阅读0次

    原文链接:https://www.openwit.net/archives/iosmvvm

    笔者最近做了一个关于app开发现状的分享,分享中提到了Google推荐的Android官方开发架构,充分肯定了其开发效率的提升,分享结束后有同事问到iOS是否有类似架构,于是便有了此篇博文。

    首先来看一下Android官方推荐的开发架构,架构图如下:


    image

    该架构遵循MVVM开发模式,利用Jetpack中的Room数据库及LiveData能够有效提升开发效率。使用过的同学自然深有体会,这里举个小例子,以群组列表页面为例。首先看一下GroupFragment中部分代码:

    public class GroupFrament extends BaseFragment {
        @BindView(R2.id.rv_contact_group)
        RecyclerView mGroupRv;
        private GroupRvAdapter mGroupRvAdapter;
    
        @Override
        protected void initVariables() {
            mViewModel = ViewModelProviders.of(this).get(GroupViewModel.class);
            mViewModel.loadGroup().observe(this, new Observer<List<GroupEntity>>() {
                @Override
                public void onChanged(@Nullable List<GroupEntity> groupEntities) {
                    mGroupRvAdapter.setItems(groupEntities);
                }
            });
        }
    
      ...
    }
    

    通过调用viewmodel中的loadgroup方法,返回livedata数据,对这些数据进行observe,并实现更新代码。这样一来整个界面的加载逻辑就实现了,如果数据库有更新,比如新建群或者删除群,群列表界面就会自动更新,无需额外代码。

    再来看下viewmodel中的实现:

        public LiveData<List<GroupEntity>> loadGroup() {
            return GroupRepository.getInstance().loadGroup();
        }
    

    这里遵循了该架构的设计,viewmodel中并没有真正的数据库相关操作,而是交给了一个Repository单例来完成。GroupRepository中的相关代码如下:

        /**
         * 到库中查询群组
         */
        public LiveData<List<GroupEntity>> loadGroup() {
            return getGroupDao().findByOwner(CoreModule.getInstance().getCurrentIdentity());
        }
    

    Dao中的实现代码如下:

        @Query("SELECT * FROM groups WHERE owner = :owner")
        LiveData<List<GroupEntity>> findByOwner(String owner);
    

    上面的核心代码严格遵循了谷歌官方推荐的Android开发架构,那么iOS开发中能否实现类似架构呢。答案是肯定的,利用rxswift以及realm数据库可以实现类似效果。

    注:以下代码参考笔者2019年初完成的项目,部分api可能已经过时。

    同样以群组列表为例,首先看一下GroupController的部分代码:

    import UIKit
    import RxSwift
    
    class FEGroupController: UITableViewController {
        var viewModel = FEGroupViewModel()
        var dataSource = [GroupEntity]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.title = "我的群组"
            self.tableView.register(UINib.init(nibName: String(describing: FEContactCell.self), bundle: nil), forCellReuseIdentifier:String(describing: FEContactCell.self))
            viewModel.loadGroup().asDriver().drive(onNext: { [weak self](list) in
                guard let strongSelf = self else {return}
                strongSelf.dataSource.removeAll()
                strongSelf.dataSource.append(contentsOf: list)
                strongSelf.tableView.reloadData()
    
            }, onCompleted: nil, onDisposed: nil).disposed(by: rx.disposeBag)
        }
    
      ...
    }
    

    通过调用viewmodel中的loadgroup方法,返回Variable数据,作为驱动来驱动界面更新。这样一来整个界面的加载逻辑就实现了,如果数据库有更新,比如新建群或者删除群,群列表界面也会自动更新,同样无需额外代码。由于iOS没有Android中提供的Jetpack相关组件(例如LiveData),这里viewmodel中的数据是怎么检测到更新的呢,下面是viewmodel中的部分代码实现:

    import UIKit
    import RxSwift
    import RealmSwift
    
    class FEGroupViewModel: NSObject {
        var mGroupId = ""
        var groupLiveData = Variable<[GroupEntity]>([GroupEntity]())
        var token: NotificationToken? = nil
    
        func loadGroup() ->Variable<[GroupEntity]>{
            let realm = try! Realm()
            let groups = GroupDao.findByOwner(FECoreModule.shared.getCurrentIdentity() ?? "", realm: realm)
            token = groups.observe({ [weak self](change) in
                var list = [GroupEntity]()
                list.append(contentsOf: groups)
                self?.groupLiveData.value = list
            })
            return self.groupLiveData
        }
    
       ...
    }
    

    上述代码,在获取到groups之后的observe操作类似livedata的使用,这里的groups到底是什么类型呢?继续往下看,下面是Dao中的相关实现代码:

    import UIKit
    import RealmSwift
    
    class GroupDao: NSObject {
        static func findByOwner(_ owner: String, realm: Realm) -> Results<GroupEntity>{
            return realm.objects(GroupEntity.self).filter("owner == \'\(owner)\'")
        }
    
      ...
    }
    

    原来realm数据库提供了Results类型的返回值,该类型数据类似LiveData,可以对其进行observe,监听数据集的变化。

    通过上面的一系列代码,同样实现了界面逻辑书写一次,自动更新的效果。不同的是Android中的viewmodel继承自系统级API(Jetpack中的ViewModel),其生命周期系统负责管理,iOS中的viewmodel基于NSObject自定义实现。

    上述iOS代码,viewmodel中并未通过封装Repository来实现,针对这点,笔者认为可以视情况而定,可以根据代码量来评估,视情况封装相应的Repository来达到分层的目的,如果viewmodel比较轻量,直接进行数据库操作也未尝不可。

    内容完。欢迎留言交流学习。

    相关文章

      网友评论

          本文标题:使用Rxswift+Realm实现Livedata+Room的效

          本文链接:https://www.haomeiwen.com/subject/adliiktx.html