分享好友 移动开发首页 频道列表

野狗 Sync 分析1 -数据监听(Android)

Android开发  2016-11-13 10:410

数据监听方式比较

Wilddog Sync 平台: Android

Wilddog Sync 版本: 2.0.1

数据监听

WilddogSync 提供了三种监听数据的方式:

addListenerForSingleValueEvent(ValueEventListener listener)

addValueEventListener(ValueEventListener listener)

addChildEventListener(ChildEventListener listener)

addListenerForSingleValueEvent 主要用于一次性获取当前节点下数据的场景,触发一次后就会失效。

addValueEventListeneraddChildEventListener 都会为当前节点绑定监听事件,持续的监听当前节点数据的变化情况,那么,这三种方式有什么不同呢?

我们运行一下代码测试两种方式的差异。

测试代码如下:

//SyncReference reference = WilddogSync.getInstance().getReference();
        //设置ListenerForSingleValueEvent
        reference.child("listenerTest").addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.e("single","onDataChange:"+dataSnapshot.toString());
            }

            @Override
            public void onCancelled(SyncError syncError) {
                Log.e("single",syncError.toString());
            }
        });
        //设置ValueEventListener
        reference.child("listenerTest").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.e("value",dataSnapshot.toString());
            }

            @Override
            public void onCancelled(SyncError syncError) {
                Log.e("value",syncError.toString());
            }
        });
        //设置ChildEventListener
        reference.child("listenerTest").addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                Log.e("child","added"+dataSnapshot.toString());
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                Log.e("child","changed"+dataSnapshot.toString());
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                Log.e("child",dataSnapshot.toString());
            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(SyncError syncError) {

            }
        });

获取数据

如果存在历史数据,运行上述代码,则会返回以下的数据:

Logcat日志:

//单次数据获取,addListenerForSingleValueEvent
E/single: onDataChange:DataSnapshot { key = listenerTest, value = {aaa=aaa, bbb={ccc=ccc}, ccc={ddd={eee=eee}}} }
//持续监听节点,addValueEventListener
E/value: onDataChange:DataSnapshot { key = listenerTest, value = {aaa=aaa, bbb={ccc=ccc}, ccc={ddd={eee=eee}}} }
//持续监听节点,addChildEventListener
E/child: onChildAdded:DataSnapshot { key = aaa, value = aaa }
E/child: onChildAdded:DataSnapshot { key = bbb, value = {ccc=ccc} }
E/child: onChildAdded:DataSnapshot { key = ccc, value = {ddd={eee=eee}} }

可以看出:

  • ValueListener会将当前节点下的数据一次性返回;
  • ChildListener将当前节点数据按子节点一个一个返回。

添加数据

当我们为某个节点添加了数据监听之后,就可以在客户端实时同步当前的数据。

现在我们考察一下为节点增加数据时,野狗实时数据同步的行为。

增加一个节点: {aaa=aaa}

E/child: onChildAdded : DataSnapshot { key = aaa, value = aaa }
E/value: onDataChange : DataSnapshot { key = listenerTest, value = {aaa=aaa} }

再增加一个同级节点: {bbb=bbb}

E/child: onChildAdded : DataSnapshot { key = bbb, value = bbb }
E/value: onDataChange : DataSnapshot { key = listenerTest, value = {aaa=aaa, bbb=bbb} }

增加一个带有子节点的节点ccc: {ccc={ddd=ddd}}

E/child: onChildAdded : DataSnapshot { key = ccc, value = {ddd=ddd} }
E/value: onDataChange : DataSnapshot { key = listenerTest, value = {aaa=aaa, bbb=bbb, ccc={ddd=ddd}} }

在ccc节点上增加子节点 {eee=eee}

E/child: onChildChanged : DataSnapshot { key = ccc, value = {ddd=ddd, eee=eee} }
E/value: onDataChange   : DataSnapshot { key = listenerTest, value = {aaa=aaa, bbb=bbb, ccc={ddd=ddd, eee=eee}} }

增加 {fff={ggg={hhh=hhh}}}

E/child: onChildAdded : DataSnapshot { key = fff, value = {ggg={hhh=hhh}} }
E/value: onDataChange : DataSnapshot { key = listenerTest, value = {aaa=aaa, fff={ggg={hhh=hhh}}, bbb=bbb, ccc={ddd=ddd, eee=eee}} }

增加 {fff={iii={jjj={kkk=kkk}}}}

E/child: onChildChanged : DataSnapshot { key = fff, value = {iii={jjj={kkk=kkk}}, ggg={hhh=hhh}} }
E/value: onDataChange   : DataSnapshot { key = listenerTest, value = {aaa=aaa, fff={iii={jjj={kkk=kkk}}, ggg={hhh=hhh}}, bbb=bbb, ccc={ddd=ddd, eee=eee}} }

总结:

1/ addValueEventListener 事件监听返回的 DataSnapshot 的 key 始终为当前节点,value 是当前节点变化后的全部字节点值;

addChildEventListener 事件监听的 key 是当前节点的下一级子节点,注意是下一级子节点,哪个下一级子节点的数据有了变化,key就是哪个子节点。

例如我们在 iii 节点下增加了 jjj 子节点,但是返回的数据依然是 DataSnapshot { key = fff, value = {iii={jjj={kkk=kkk}}, ggg={hhh=hhh}} } ,返回的是 listenerTest 下一级子节点 fff 节点的变化数据。

也就是说value事件关注当前节点的数据变化情况,返回的DataSnapshot中value是当前节点下所有数据的值;

child事件关注的是当前节点的子节点数据变化情况,返回的DataSnapshot中value是当前节点某个子节点所有数据的值。

2/value事件监听时,当前节点有数据增加则会触发onDataChange方法;

child事件监听时,增加下一级子节点时如子节点不存在则触发onChildAdded事件,如果子节点存在则触发onChildChanged事件。

删除数据

直接删除子节点,考察野狗实时数据同步的行为。

删除 aaa

此时 ChildEventListener 触发了 onChildRemoved 事件,返回的 valueaaa 节点被删除的数据。

E/child: onChildRemoved : DataSnapshot { key = aaa, value = aaa }
E/value: onDataChange   : DataSnapshot { key = listenerTest, value = {fff={iii={jjj={kkk=kkk}}, ggg={hhh=hhh}}, bbb=bbb, ccc={ddd=ddd, eee=eee}} }

删除 ddd

在执行删除操作前 ccc 节点下的数据为 ccc={ddd=ddd, eee=eee}} ,执行删除 ddd 节点之后, ccc 节点的数据变为 ccc={eee=eee}}

此时触发了 onChildChanged 事件,返回的值为当前 ccc 节点下的数据。

E/child: onChildChanged : DataSnapshot { key = ccc, value = {eee=eee} }
E/value: onDataChange   : DataSnapshot { key = listenerTest, value = {fff={iii={jjj={kkk=kkk}}, ggg={hhh=hhh}}, bbb=bbb, ccc={eee=eee}} }

删除 eee

再次触发了 onChildRemoved 事件,返回被删除的数据,此时整个 ccc 节点一同被删除。

E/child: onChildRemoved : DataSnapshot { key = ccc, value = {eee=eee} }
E/value: onDataChange   : DataSnapshot { key = listenerTest, value = {fff={iii={jjj={kkk=kkk}}, ggg={hhh=hhh}}, bbb=bbb} }

总结:

1/ addValueEventListener 事件监听始终返回被监听节点的数据;

addChildEventListener 事件监听返回的是变化的子节点的数据,根据不同情况触发不同监听。

2/删除节点时, ChildEventListener 会根据不同情形触发两个不同的事件:

事件 触发条件 结果
onChildRemoved 被删除节点的父节点只有一个子节点 返回被删除的节点数据
onChildChanged 被删除节点的父节点有多个子节点 返回变化后的被删除节点的父节点数据

3/删除节点时,如果被删除节点的父节点只有被删除节点这一个子节点,那么父节点会被同时删除。

应用实践

根据以上实验的结果,我们可以分析这两个不同监听的语义:

ValueEventListener 始终返回被监听节点的数据,所以 Value 指的是当前节点的值,也就是说,Value 关注当前节点值的变化情况。

ChildEventListener 始终返回被监听节点的下一级字节点的数据,那么 Child 指的是当前节点的下一级子节点,或者说直接子节点,其孙节点的变化一样会归为子节点的变化,关注的是当前节点下一级子节点变化情况。

需要注意的是,同一个路径可以重复设置监听,如果多次设置监听之后,每次数据变化都会触发每一个设置的监听,有可能多次处理相同业务,造成逻辑错误。

在一个监听已经失去继续保留的意义的时候,可以使用 removeEventListener() 方法移除不需要的监听。

查看更多关于【Android开发】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
Supporting Multiple Screens
术语和概念Screen size 屏幕尺寸又称「屏幕大小」,是屏幕对角线的物理尺寸。单位英寸 inch,比如 Samsung Note4 是 5.7 英寸。Resolution 屏幕分辨率屏幕纵横方向上物理像素的总数,比如 Samsung Note4 是 2560x1440,表示纵向有 2560 个像素,横向有 1440

0评论2017-02-05363

Android插件化(4):OpenAtlasの插件的卸载与更新
如果看过我的前两篇博客Android插件化(2):OpenAtlas插件安装过程分析和Android插件化(3):OpenAtlas的插件重建以及使用时安装,就知道在插件的安装过程中OpenAtlas做了哪些事,那么插件的卸载就只需要把持久化和内存中的内容移除即可。1.插件的卸载插件卸载的

0评论2017-02-05229

个人简历
吴朝晖/男/1993.1本科/南京师范大学中北学院信息系工作年限:1年以内技术博客:wuzhaohui026.github.ioGitHub:https://github.com/wuzhaohui026期望职位:Android开发(初级Android工程师)期望薪资:税前月薪5.5k~7k期望城市:常州工作经历常州慧展信息科技有

0评论2017-02-05126

Android插件化(五):OpenAtlasの四大组件的Hack
引言到目前为止,我们已经分析了OpenAtlas中插件的安装,卸载,更新,以及安装好插件之后组件类的加载过程,但是对于这些是如何引发的还不知道,比如,在宿主的一个Activit中调用startActivity()跳转到插件中的一个Activity,如何判断这个Activity在的插件是否

0评论2017-02-0598

更多推荐