家庭管理业务实现

更新时间:2024-01-12 06:29:09下载pdf

家庭管理业务主要包括家庭信息、家庭房间和家庭成员三个部分。登录成功以后,需要确认当前家庭,因为设备必须添加在家庭维度下。参考如下逻辑实现流程:

家庭管理业务实现

全局变量设置如下:

private var mFamilyUseCase: IFamilyUseCase = FamilyManagerCoreKit.getFamilyUseCase()
private var mMemberUseCase: IMemberUseCase = FamilyManagerCoreKit.getMemberUseCase()
private var mRoomUseCase: IFamilyRoomUseCase = FamilyManagerCoreKit.getRoomUseCase()

刷新家庭信息

登录成功,获取当前默认家庭,完成刷新家庭信息和数据逻辑。

  1. 获取当前默认家庭。

    新用户一般在第一次登录成功以后,是没有家庭的。如果没有,getHomeDefaultDetail() 方法将返回空数据,此时需要创建一个默认家庭。成功创建一个默认家庭以后,只需要调用切换家庭接口,指定当前默认家庭。下次应用重启则会返回该默认家庭。代码示例逻辑实现如下:

     fun getHomeDefaultDetail() {
      mFamilyUseCase.getCurrentDefaultFamilyDetail(object :
           IFamilyDataCallback<BizResponseData<FamilyBean>> {
           override fun onSuccess(result: BizResponseData<FamilyBean>?) {
               if (result?.data == null) {//没有默认家庭
                   creatDefaultFamily()
               } else {
                   result?.data?.let {
                      //此时注册家庭消息
                       registerHomeListener(it.homeId, it.familyName)
                       //刷新家庭数据和设备群组列表
                       getHomeDeviceList()
                   }
               }
           }
           override fun onError(errorCode: String?, errorMessage: String?) {
               view.showErrorMsg(errorCode, errorMessage)
           }
        })
    
      //创建默认家庭,该家庭没有房间地址,只有默认房间名称。
       private fun creatDefaultFamily() {
       mFamilyUseCase.createDefaultFamily( view.getHomeDefaultName(),
           object : IFamilyDataCallback<BizResponseData<FamilyBean>> {
               override fun onSuccess(result: BizResponseData<FamilyBean>?) {
                   result?.data?.let {
                       view.hideLoading()
                       //可调用该接口,利用 FamilyChangeListener #onFamilyShift 回调刷新
                       mFamilyUseCase.shiftCurrentFamily(it.homeId, null)
                   }
               }
    
               override fun onError(errorCode: String?, errorMessage: String?) {
                   view.showErrorMsg(errorCode, errorMessage)
               }
           })
          }
        }
    
  2. 注册家庭下设备群组新增和删除消息。

    成功获取到当前默认家庭以后,也可以注册家庭下设备群组新增和删除消息监听。并根据不同的家庭通知变更,刷新家庭信息,例如家庭所在城市和所在城市的天气信息,以及当前家庭所拥有设备和群组信息。代码示例实现逻辑如下:

    private fun registerHomeListener(homeId: Long, familyName: String?) {
    
           homeStatusListener = object : IThingHomeStatusListener {
               override fun onDeviceAdded(devId: String?) {
                   //使用缓存数据刷新
                   refreshDevlist(mCurrentHomeId?.let { ThingHomeSdk.newHomeInstance(it).homeBean })
               }
    
               override fun onDeviceRemoved(devId: String?) {
                   //使用缓存数据刷新
                   refreshDevlist(mCurrentHomeId?.let { ThingHomeSdk.newHomeInstance(it).homeBean })
               }
    
               override fun onGroupAdded(groupId: Long) {
                   //使用缓存数据刷新
                   refreshDevlist(mCurrentHomeId?.let { ThingHomeSdk.newHomeInstance(it).homeBean })
               }
    
               override fun onGroupRemoved(groupId: Long) {
                   //使用缓存数据刷新
                   refreshDevlist(mCurrentHomeId?.let { ThingHomeSdk.newHomeInstance(it).homeBean })
               }
    
               override fun onMeshAdded(meshId: String?) {
    
               }
    
           }
           FamilyManagerCoreKit.registerHomeStatusListener(homeId,
               homeStatusListener as IThingHomeStatusListener
           )
    
          }
    
  3. 刷新家庭信息设备列表。

    确认默认家庭以后,需要刷新家庭名称、家庭地理位置和天气等信息,以及包括家庭下全部设备和群组信息。代码示例逻辑实现如下:

    private fun getHomeDeviceList(homeId: Long) {
       //获取 HomeBean,HomeBean 中包含全部的设备列表,getHomeDetail 会触发云端接口刷新设备列表信息。
        ThingHomeSdk.newHomeInstance(homeId).getHomeDetail(object : IThingHomeResultCallback {
            override fun onSuccess(bean: HomeBean?) {
                refreshDevlist(bean)
            }
    
            override fun onError(errorCode: String?, errorMsg: String?) {
                view.showErrorMsg(errorCode, errorMsg)
            }
        })
      }
        private fun refreshDevlist(home: HomeBean?) {
         view.updateDevlist(home)
         home?.let {
            // 获取天气
            getHomeWeather(it.lon,it.lat)
            // 获取城市名称
            getHomeCity(it.lon,it.lat)
           }
        }
    
        private fun getHomeCity( lon:Double, lat:Double) {
        mFamilyUseCase.getCityByLatLon(lon,lat,object:IFamilyDataCallback<LocationCityBean>{
            override fun onSuccess(result: LocationCityBean?) {
                result?.let {
                    view.updateCityName(it.province+"  "+it.city)
                }
            }
    
            override fun onError(errorCode: String?, errorMessage: String?) {
    
            }
        } )
       }
    
       private fun getHomeWeather( lon:Double, lat:Double) {
        mFamilyUseCase.getHomeWeather(lon,lat,object:IFamilyDataCallback<WeatherBean>{
            override fun onSuccess(result: WeatherBean?) {
                result?.let {
                    view.updateWeather(it.condition+" ,"+result.temp)
                }
            }
    
            override fun onError(errorCode: String?, errorMessage: String?) {
    
            }
        } )
      }
    
  4. 家庭维度消息监听。

    完成家庭信息的刷新以后,可以添加全局家庭相关消息监听,例如家庭新增、家庭邀请和家庭删除等消息,还包括账号维度下的家庭分享设备的新增和删除。根据不同的消息和数据,实现不同的刷新逻辑。代码示例逻辑如下:

      private val familyChangeListener = object : FamilyChangeListener {
      override fun onFamilyAdded(homeId: Long) {
    
      }
    
      override fun onFamilyInvite(homeId: Long, homeName: String?) {
          //家庭邀请弹窗
          view.showFamilyInviteDialog(homeId, homeName)
      }
    
      override fun onFamilyRemoved(homeId: Long, isBySelfRemoved: Boolean) {
          if (!isBySelfRemoved) { //如果不是本人删除,则提示家庭已被删除 
              view.showFamilyRemovedDialog()
          }
          if (mCurrentHomeId == homeId) {
              getHomeDefaultDetail()
          }
      }
    
      override fun onFamilyInfoChanged(homeId: Long) {
           refreshFamilyBean(homeId)
      }
    
      override fun onFamilyShift(familyId: Long, familyName: String?) {
          registerHomeListener(familyId, familyName)
      }
    
      override fun onSharedDeviceList(sharedDeviceList: MutableList<DeviceBean>?) {
          //使用缓存数据刷新
          refreshDevlist(mCurrentHomeId?.let { ThingHomeSdk.newHomeInstance(it).homeBean })
      }
    
      override fun onSharedGroupList(sharedGroupList: MutableList<GroupBean>?) {
          //使用缓存数据刷新
          refreshDevlist(mCurrentHomeId?.let { ThingHomeSdk.newHomeInstance(it).homeBean })
      }
    
      override fun onServerConnectSuccess() {
    
      }
    }
    FamilyManagerCoreKit.registerFamilyChangeListener(familyChangeListener)
    

    以上为完成用户登录成功以后主要功能逻辑的实现,包括切换家庭、刷新设备缓存、收到家庭邀请、接受或者拒绝家庭邀请等。关于详细逻辑实现,查看 Demo

家庭管理

查询家庭列表,修改默认家庭信息,以及家庭删除接口逻辑。

  1. 查询家庭列表。

    查询家庭列表接口,获取账号下的全部家庭,包括自己创建的和被分享的家庭。其中,被分享家庭的当前状态有三种:

    • HomeStatus.WAITING:等待加入

    • HomeStatus.ACCEPT:已经接受邀请加入家庭

    • HomeStatus.REJECT:拒绝邀请
      如果加载显示家庭列表,最好过滤掉被拒绝的家庭。代码示例代码逻辑实现如下:

        fun getFamilyList() {
         mFamilyUseCase.getFamilyList(object :
             IFamilyDataCallback<BizResponseData<List<FamilyBean>>> {
             override fun onSuccess(result: BizResponseData<List<FamilyBean>>?) {
      
                     result?.data?.let {
                          it.filter { family->family.familyStatus != HomeStatus.REJECT }
                     }
                 }
      
             }
      
             override fun onError(errorCode: String?, errorMessage: String?) {
      
             }
         })
       }
      
      
  2. 修改家庭信息。

    创建的默认家庭只有一个家庭默认名称。如需修改名称、添加家庭地址和家庭房间,可以调用修改家庭接口,选择家庭进行修改和补充。注意 CreateFamilyRequestBeanrooms 字段不能为空。代码示例实现逻辑如下:

    fun updateFamily(
      name: String,
      lon: Double,
      lat: Double,
      address: String,
      settingFamilybean: FamilyBean?
    ) {
      val requestBean = settingFamilybean?.rooms?.let {
          CreateFamilyRequestBean(name, lon, lat, address, null)
      } ?: CreateFamilyRequestBean(name, lon, lat, address, arrayListOf("room1")).apply {
          isForComplete = true // 设置 isForComplete 来完善家庭信息,将返回家庭信息
      }
      settingFamilybean?.homeId?.let {
          mFamilyUseCase.updateFamily(
              it,
              requestBean,
              object : IFamilyDataCallback<BizResponseData<FamilyBean>> {
                  override fun onSuccess(result: BizResponseData<FamilyBean>?) {
                      result?.let {result->
                          if( result.data == null){
                              getFamilyDetail(it)
                          }
                      }
                  }
    
                  override fun onError(errorCode: String?, errorMessage: String?) {
                      ...
                  }
              })
      }
    }
    
  3. 删除家庭。

    删除家庭操作需要家庭所有者角色,并且是当前家庭下没有其他成员的情况下才能删除。一旦家庭被删除,家庭下的设备也会全部删除。删除家庭成功以后,再也无法恢复,所以删除家庭需要谨慎操作。

    如果当前是家庭所有者并且家庭下还有其他成员,那么可以先转移家庭所有者权限,变成管理员,然后离开家庭。代码示例逻辑实现如下:

    fun dismissfamily(homeId: Long?) {
        homeId?.let {
            mFamilyUseCase.dismissFamily(it, object : IFamilyDataCallback<Boolean> {
                override fun onSuccess(result: Boolean?) {
                    viewModelScope.launch {
                        _delFamilybean.emit(true)
                    }
                }
    
                override fun onError(errorCode: String?, errorMessage: String?) {
    
                }
            })
        }
    }
    

    关于家庭下的其他接口、转移家庭所有者权限和离开家庭,参考完整逻辑示例 Demo

房间管理

查询家庭下的全部房间,新增、修改和删除一个房间。

  1. 查询家庭下的房间列表。

    如需查看一个家庭下的全部房间数据列表,可调用查询房间列表接口,需要传入家庭 ID,指定查询哪个家庭的房间。代码示例逻辑如下:

     fun getRoomList(homeId: Long?) {
        if (homeId != null) {
            mRoomUseCase?.getRoomList(
                homeId,
                true,
                object : IFamilyDataCallback<BizResponseData<List<TRoomBean>>> {
                    override fun onSuccess(result: BizResponseData<List<TRoomBean>>?) {
                        result?.data?.let {
                            val list = arrayListOf<TRoomBean>()
                            list.addAll(it)
                           ...
                        }
                    }
    
                    override fun onError(errorCode: String?, errorMessage: String?) {
                        ...
                    }
                })
        }
      }
    
  2. 新增家庭下的房间。

    如需新增家庭下的房间,可调用添加房间接口,需要传入家庭 ID,指定添加房间到哪个家庭,然后为将要添加的房间命名。代码示例逻辑如下:

     fun addRoom(homeId: Long?,name: String?) {
        if (homeId != null) {
            mRoomUseCase?.addRoom(
                homeId,
                name,
                object : IFamilyDataCallback<BizResponseData<TRoomBean>> {
                    override fun onSuccess(result: BizResponseData<TRoomBean>?) {
                        result?.data?.let {
                            ...
                        }
                    }
    
                    override fun onError(errorCode: String?, errorMessage: String?) {
                        ...
                    }
                })
        }
        }
    
  3. 删除家庭下的房间。

    当您想要删除某个房间时,需要传入家庭 ID,指定哪个家庭和房间 ID。代码示例逻辑如下:

      fun deleteRoom(homeId: Long, roomId: Long) {
        if (roomId != null) {
            mRoomUseCase?.removeRoom(homeId, roomId, object : IFamilyDataCallback<Boolean> {
                override fun onSuccess(result: Boolean?) {
                   ...
                }
    
                override fun onError(errorCode: String?, errorMessage: String?) {
                   ...
                }
            })
        }
      }
    

    关于家庭房间下的其他接口,包括家庭房间的排序、房间下的设备删除、新增和排序,查看示例 Demo

成员管理

获取家庭下全部成员,添加或者删除家庭成员。

  1. 查询家庭下的全部成员列表。

    家庭下的全部成员列表有两个接口:

    • getFamilyMemberList:已经接受邀请的全部家庭成员。
    • getInvitationMemberList:还没有接受也没有拒绝的成员,即等待接受邀请的全部成员。

    如果被分享的成员拒绝了邀请,那么将不会是该家庭下的成员。代码示例逻辑实现如下:

        fun getMemberList(homeId: Long) {
        mFamilyUseCase.getFamilyMemberList(homeId,
            object : IFamilyDataCallback<BizResponseData<List<MemberBean>>> {
                override fun onSuccess(result: BizResponseData<List<MemberBean>>?) {
                    val members: ArrayList<MemberBean> = arrayListOf()
                    result?.data?.let { members.addAll(it) }
                    //再次获取等待接受邀请的成员
                    mFamilyUseCase.getInvitationMemberList(homeId,
                        object : IFamilyDataCallback<BizResponseData<List<MemberBean>>> {
                            override fun onSuccess(result1: BizResponseData<List<MemberBean>>?) {
                                result1?.data?.let { members.addAll(it) }
                                 ...
                            }
    
                            override fun onError(errorCode: String?, errorMessage: String?) {
                                 ...
                            }
                        })
                }
    
                override fun onError(errorCode: String?, errorMessage: String?) {
                   ...
                }
            })
        }
    
  2. 添加成员。

    家庭所有者可以添加一个已注册账号的成员,设置角色权限为普通成员或者管理员,被分享的成员账号应该是同一个数据区的,即 CountryCode 应该和添加者相同。需要注意的是 MemberWrapperBean 中家庭 ID(homeId)、成员角色(role)、成员名称(memberName)和成员账号(account)都不能为空。简单的代码调用示例逻辑如下:

     private fun showAddMemberDialog() {
        val inputLayout = TextInputLayout(requireContext()).apply {
            hint = getString(R.string.add_member_name_hint)
            setPadding(32, 0, 32, 0)
        }
        val editText = EditText(context)
        inputLayout.addView(editText)
        val inputLayout2 = TextInputLayout(requireContext()).apply {
            hint = getString(R.string.add_member_account_hint)
            setPadding(32, 0, 32, 0)
        }
        val editText2 = EditText(context)
        inputLayout2.addView(editText2)
        val radioGroup = RadioGroup(context).apply {
            orientation = LinearLayout.HORIZONTAL
            setPadding(32, 16, 32, 16)
        }
        val radioButton1 = MaterialRadioButton(requireContext()).apply {
            text = "admin"
        }
        val radioButton2 = MaterialRadioButton(requireContext()).apply {
            text = "common"
        }
    
        radioGroup.addView(radioButton1)
        radioGroup.addView(radioButton2)
        val linearLayout = LinearLayout(context).apply {
            orientation = LinearLayout.VERTICAL
            addView(inputLayout)
            addView(inputLayout2)
            addView(radioGroup)
        }
        MaterialAlertDialogBuilder(requireContext())
            .setTitle(getString(R.string.update_member))
            .setView(linearLayout)
            .setPositiveButton(getString(R.string.confirm)) { d, _ ->
                val name = editText.text.toString()
                val account = editText2.text.toString()
                var role = MemberRole.ROLE_MEMBER // 普通成员
                if (radioGroup.checkedRadioButtonId == radioButton1.id) {
                    role = MemberRole.ROLE_ADMIN //管理员
                }
                val bean = MemberBean()
                var code: String? = "86"
                if (!TextUtils.isEmpty(viewModel.mCurMemberBen?.countryCode)) {
                    code = viewModel.mCurMemberBen?.countryCode
                }
                bean.memberName = name
                bean.homeId = settingFamilybean?.homeId!!
                bean.countryCode = code
                bean.account = account
                bean.role = role
                addMember(bean)
                d.dismiss()
            }
            .setNegativeButton(getString(R.string.cancel)) { d, _ ->
                d.dismiss()
            }
            .show()
    
         }
    
       fun addMember(memberBean: MemberBean) {
        val bean = MemberWrapperBean.Builder()
            .setHomeId(memberBean.homeId)
            .setRole(memberBean.role)
            .setNickName(memberBean.memberName)
            .setAccount(memberBean.account)
            .setCountryCode(memberBean.countryCode)
            .setAdmin(memberBean.isAdmin)
            .build()
        mMemberUseCase.addMember(bean, object : IFamilyMemberDataCallback<MemberBean> {
            override fun onSuccess(result: MemberBean?) {
                 ...
            }
    
            override fun onError(errorCode: String?, errorMessage: String?) {
               ...
            }
        })
    }
    
  3. 删除成员。

    当需要删除一个成员时,需要操作人的权限大于被删除的成员,即家庭所有者可以删除管理员和普通成员,管理员只能删除普通成员,普通成员不能删除其他成员。接口调用需要传入家庭 ID(homeId),简单的代码调用示例逻辑如下:

        if(viewModel.mCurMemberBen == null | | memberBean== null){
            return
        }
        if(isAdmin && (mCurMemberBen!!.role <= memberBean!!.role)){
            Toast.makeText(
                requireContext(),
                getString(R.string.member_can_not_delete_tip),
                Toast.LENGTH_LONG
            )
            return
        }
        MaterialAlertDialogBuilder(requireContext())
            .setTitle(getString(R.string.confirm_delete_member))
            .setPositiveButton(getString(R.string.confirm)) { d, _ ->
                settingFamilybean?.homeId?.let {  deleteMember(it,memberBean) }
                d.dismiss()
            }
            .setNegativeButton(getString(R.string.cancel)) { d, _ ->
                d.dismiss()
            }
            .show()
    
        fun deleteMember(homeId: Long, memberBean: MemberBean) {
           mMemberUseCase.removeMember(
            homeId,
            memberBean.memberId,
            object : IFamilyMemberResultCallback {
                override fun onError(code: String?, error: String?) {
                   ...
                }
    
                override fun onSuccess() {
                   ...
                }
            })
      }
    

    家庭下的成员还有很多操作,包括家庭成员信息的修改、修改成员角色、通过生成邀请码分享添加成员,以及成员通过邀请码添加家庭。更多完整逻辑,参考示例 Demo

销毁资源

如果设置了 UseCase 模块的全局变量,之后在页面退出的时候应该及时销毁。

...
private var mFamilyUseCase: IFamilyUseCase = FamilyManagerCoreKit.getFamilyUseCase()
private var mMemberUseCase: IMemberUseCase = FamilyManagerCoreKit.getMemberUseCase()
private var mRoomUseCase: IFamilyRoomUseCase = FamilyManagerCoreKit.getRoomUseCase()
...
   override fun onDestroy() {
        mFamilyUseCase.onDestroy()
        mMemberUseCase.onDestroy()
        mRoomUseCase.onDestroy()
    }