diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> ) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> ) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> ) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> ) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> + app:tbv_smaller_title="true" + app:tbv_text="首页" /> ) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> + app:tbv_smaller_title="true" + app:tbv_text="首页" /> + android:textSize="@dimen/sp_16" /> ) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> + app:tbv_smaller_title="true" + app:tbv_text="首页" /> + android:textSize="@dimen/sp_16" /> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_refresh_white" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="概览" /> - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> + app:tbv_smaller_title="true" + app:tbv_text="首页" /> + android:textSize="@dimen/sp_16" /> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_refresh_white" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="概览" /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv.xml b/app/src/main/res/layout/item_device_rv.xml deleted file mode 100644 index c2c6857..0000000 --- a/app/src/main/res/layout/item_device_rv.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> + app:tbv_smaller_title="true" + app:tbv_text="首页" /> + android:textSize="@dimen/sp_16" /> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_refresh_white" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="概览" /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv.xml b/app/src/main/res/layout/item_device_rv.xml deleted file mode 100644 index c2c6857..0000000 --- a/app/src/main/res/layout/item_device_rv.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv_l.xml b/app/src/main/res/layout/item_device_rv_l.xml new file mode 100644 index 0000000..2657f5c --- /dev/null +++ b/app/src/main/res/layout/item_device_rv_l.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> + app:tbv_smaller_title="true" + app:tbv_text="首页" /> + android:textSize="@dimen/sp_16" /> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_refresh_white" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="概览" /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv.xml b/app/src/main/res/layout/item_device_rv.xml deleted file mode 100644 index c2c6857..0000000 --- a/app/src/main/res/layout/item_device_rv.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv_l.xml b/app/src/main/res/layout/item_device_rv_l.xml new file mode 100644 index 0000000..2657f5c --- /dev/null +++ b/app/src/main/res/layout/item_device_rv_l.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_group_over_view_rv.xml b/app/src/main/res/layout/item_group_over_view_rv.xml deleted file mode 100644 index 8c7436d..0000000 --- a/app/src/main/res/layout/item_group_over_view_rv.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> + app:tbv_smaller_title="true" + app:tbv_text="首页" /> + android:textSize="@dimen/sp_16" /> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_refresh_white" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="概览" /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv.xml b/app/src/main/res/layout/item_device_rv.xml deleted file mode 100644 index c2c6857..0000000 --- a/app/src/main/res/layout/item_device_rv.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv_l.xml b/app/src/main/res/layout/item_device_rv_l.xml new file mode 100644 index 0000000..2657f5c --- /dev/null +++ b/app/src/main/res/layout/item_device_rv_l.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_group_over_view_rv.xml b/app/src/main/res/layout/item_group_over_view_rv.xml deleted file mode 100644 index 8c7436d..0000000 --- a/app/src/main/res/layout/item_group_over_view_rv.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_group_over_view_rv_l.xml b/app/src/main/res/layout/item_group_over_view_rv_l.xml new file mode 100644 index 0000000..e7179c6 --- /dev/null +++ b/app/src/main/res/layout/item_group_over_view_rv_l.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 12b867b..cd8f7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ applicationId "com.casic.smarttube" minSdkVersion 26 targetSdkVersion 33 - versionCode 3 + versionCode 1020 versionName "1.0.2" } @@ -70,7 +70,7 @@ implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //空白页 + //侧滑删除 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' def vm_version = "2.5.1" diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d999103..7be718f 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult @@ -18,6 +19,7 @@ import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.extensions.toTextColor import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.dp2px import com.qmuiteam.qmui.recyclerView.QMUISwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder @@ -39,7 +41,7 @@ .build() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder { - val view = layoutInflater.inflate(R.layout.item_device_rv, parent, false) + val view = layoutInflater.inflate(R.layout.item_device_rv_l, parent, false) val swipeViewHolder = QMUISwipeViewHolder(view) swipeViewHolder.addSwipeAction(deleteAction) return swipeViewHolder @@ -68,7 +70,7 @@ deviceCodeView.text = rowsBean.devcode if (rowsBean.isUse == "1") { isUseView.text = "已激活" - isUseView.setTextColor(Color.GREEN) + isUseView.setTextColor(R.color.greenColor.convertColor(context)) } else { isUseView.text = "未激活" isUseView.setTextColor(Color.LTGRAY) @@ -123,22 +125,55 @@ } holder.itemView.setOnClickListener { - listener?.onClicked(position) + listener?.onClicked(rowsBean) } dataHistoryButton.setOnClickListener { - listener?.onHistoryClicked(position) + listener?.onHistoryClicked(rowsBean) } } private var listener: OnItemClickListener? = null interface OnItemClickListener { - fun onClicked(position: Int) + fun onClicked(item: DeviceListModel.DataModel) - fun onHistoryClicked(position: Int) + fun onHistoryClicked(item: DeviceListModel.DataModel) } fun setOnItemClickListener(onClickListener: OnItemClickListener?) { this.listener = onClickListener } + + fun refresh(newRows: MutableList) { + val diffCallback = object : DiffUtil.Callback() { + override fun getOldListSize(): Int = dataRows.size + override fun getNewListSize(): Int = newRows.size + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] === newRows[newItemPosition] + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return dataRows[oldItemPosition] == newRows[newItemPosition] + } + } + + val diffResult = DiffUtil.calculateDiff(diffCallback) + + dataRows.clear() + dataRows.addAll(newRows) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * 加载更多 + * */ + fun loadMore(newRows: MutableList) { + if (newRows.isEmpty()) { + return + } + val startPosition = this.dataRows.size + this.dataRows.addAll(newRows) + notifyItemRangeInserted(startPosition, newRows.size) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt deleted file mode 100644 index fca5514..0000000 --- a/app/src/main/java/com/casic/smarttube/adapter/OverviewGroupListAdapter.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.casic.smarttube.adapter - -import android.content.Context -import android.os.Build -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import com.amap.api.services.core.LatLonPoint -import com.amap.api.services.geocoder.GeocodeResult -import com.amap.api.services.geocoder.GeocodeSearch -import com.amap.api.services.geocoder.RegeocodeQuery -import com.amap.api.services.geocoder.RegeocodeResult -import com.casic.smarttube.R -import com.casic.smarttube.model.ProjectGroupModel - -class OverviewGroupListAdapter( - context: Context, private val dataRows: MutableList -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_over_view_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - - val inUseText = String.format("已激活:%s", rowsBean.alive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.inUseDeviceNumView.text = Html.fromHtml( - inUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.inUseDeviceNumView.text = Html.fromHtml(inUseText) - } - - val notUseText = String.format("未激活:%s", rowsBean.unalive) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - holder.notUseDeviceNumView.text = Html.fromHtml( - notUseText, Html.FROM_HTML_MODE_LEGACY, null, null - ) - } else { - holder.notUseDeviceNumView.text = Html.fromHtml(notUseText) - } - - //绑定事件 - holder.itemView.setOnClickListener { - listener?.onClicked(position) - } - - holder.itemView.setOnLongClickListener { - listener?.onLongClicked(position) - true - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - - fun onLongClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt deleted file mode 100644 index 22e56d2..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/QMUIEmptyView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.View -import com.qmuiteam.qmui.widget.QMUIEmptyView - -fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { - this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) -} - -fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { - this.show(false, title, null, "刷新", onButtonClickListener) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 1064978..d896eb5 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -163,7 +163,7 @@ bindRecyclerView(it) } } - groupViewModel.obtainProGroupList() + groupViewModel.getProGroupList() groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { @@ -214,7 +214,7 @@ if (rCode == 1000) { viewHolder.setText( R.id.groupLocationView, - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") + String.format("${result?.regeocodeAddress?.formatAddress}") ) } } diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt index c0afcc5..e997f6a 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt @@ -2,24 +2,33 @@ import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider -import com.casic.smarttube.adapter.OverviewGroupListAdapter +import androidx.recyclerview.widget.DividerItemDecoration +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentOverviewBinding -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.ProjectGroupModel import com.casic.smarttube.view.GroupDeviceActivity import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.EmptyView +import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter +import com.pengxh.kt.lite.adapter.ViewHolder import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog class OverviewFragment : KotlinBaseFragment() { + private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private lateinit var groupViewModel: ProjectGroupViewModel - private var dataBeans: MutableList = ArrayList() - private lateinit var groupListAdapter: OverviewGroupListAdapter + private lateinit var groupListAdapter: NormalRecyclerAdapter private var clickedPosition = 0 override fun initViewBinding( @@ -29,84 +38,122 @@ } override fun setupTopBarLayout() { - binding.titleView.text = "概览" + } override fun initOnCreate(savedInstanceState: Bundle?) { - groupViewModel = ViewModelProvider(this).get(ProjectGroupViewModel::class.java) - } - - override fun onResume() { - groupViewModel.obtainProGroupList() - super.onResume() - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - binding.rightOptionView.setOnClickListener { - groupViewModel.obtainProGroupList() - "刷新数据中,请稍后".show(requireContext()) - } - + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] groupViewModel.groupModel.observe(this) { if (it.code == 200) { - if (it.data.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - groupViewModel.obtainProGroupList() - } - } else { - binding.emptyInclude.emptyView.hide() - dataBeans.clear() - dataBeans = it.data - - groupListAdapter = OverviewGroupListAdapter(requireContext(), it.data) - binding.groupRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - OverviewGroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - requireContext().navigatePageTo(it.data[position].groupId) - } - - override fun onLongClicked(position: Int) { - //标记被点击的item位置 - clickedPosition = position - AlertInputDialog.Builder() - .setContext(requireContext()) - .setTitle("提示") - .setHintMessage("请输入新的项目名") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertInputDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick(value: String) { - groupViewModel.changeGroupId( - it.data[position].groupId, value - ) - } - }) - .build().show() - } - }) - } + bindRecyclerView(it) } } + groupViewModel.getGroupList() groupViewModel.changeGroupResult.observe(this) { if (it.code == 200) { - dataBeans.removeAt(clickedPosition) - groupListAdapter.notifyItemRemoved(clickedPosition) - groupListAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) + groupListAdapter.notifyItemChanged(clickedPosition) } } } + + private fun bindRecyclerView(it: ProjectGroupModel) { + val dataRows = it.data + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } else { + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + + groupListAdapter = object : NormalRecyclerAdapter( + R.layout.item_group_over_view_rv_l, it.data + ) { + override fun convertView( + viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel + ) { + viewHolder.setText(R.id.groupNameView, item.groupId) + .setText(R.id.totalDeviceNumView, item.totalDevice) + .setText(R.id.inUseDeviceNumView, item.alive) + .setText(R.id.notUseDeviceNumView, item.unalive) + .setOnClickListener(R.id.editGroupNameView) { + clickedPosition = position + editGroupName(item) + } + if (item.latGaode.isBlank() || item.lngGaode.isBlank()) { + viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置") + } else { + val point = LatLonPoint(item.latGaode.toDouble(), item.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + viewHolder.setText( + R.id.groupLocationView, + String.format("${result?.regeocodeAddress?.formatAddress}") + ) + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + } + } + } + binding.recyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.recyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + requireContext().navigatePageTo(item.groupId) + } + }) + } + } + + private fun editGroupName(item: ProjectGroupModel.DataModel) { + AlertInputDialog.Builder() + .setContext(requireContext()) + .setTitle("提示") + .setHintMessage("请输入新的项目名") + .setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertInputDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick(value: String) { + item.groupId = value + groupViewModel.changeGroupId(item.groupId, value) + } + }).build().show() + } + + override fun observeRequestState() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + + } + + override fun onRightClick() { + groupViewModel.getProGroupList() + } + }) + } + + override fun initEvent() { + binding.emptyView.setOnClickListener(object : EmptyView.OnClickListener { + override fun onReloadButtonClicked() { + groupViewModel.getProGroupList() + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index f501087..fc0a49d 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -96,7 +96,7 @@ * 获取设备分页列表 * */ @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( + suspend fun getDeviceListByPage( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String?, @Query("order") order: Int, diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 7b74fff..351988e 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -88,8 +88,8 @@ /** * 获取设备分页列表 */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( + suspend fun getDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.getDeviceListByPage( AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT ) } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index e9befb2..3e98725 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,7 +1,7 @@ package com.casic.smarttube.view import android.os.Bundle -import android.os.Handler +import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager @@ -10,19 +10,19 @@ import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets +import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog @@ -32,14 +32,14 @@ class GroupDeviceActivity : KotlinBaseActivity() { private lateinit var groupId: String - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter private val context = this private val easyPopupWindow by lazy { EasyPopupWindow(this) } - private var dataBeans: MutableList = ArrayList() - private var pageIndex = 1 + private val marginOffsets by lazy { 5.dp2px(this) } + private var dataRows: MutableList = ArrayList() + private var page = 1 private var isRefresh = false private var isLoadMore = false private var order = 0 @@ -66,25 +66,50 @@ override fun initOnCreate(savedInstanceState: Bundle?) { groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! binding.titleView.setTitle(String.format(groupId + "项目设备列表")) - weakReferenceHandler = WeakReferenceHandler(callback) + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] + groupViewModel.deviceListModel.observe(this) { + if (it.code == 200) { + bindRecyclerView(it) + } + } + getDeviceListByPage() + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - obtainDeviceListByPage() + deviceViewModel.deleteResult.observe(this) { + if (it.code == 200) { + if (isDeleteAll) { + dataRows.clear() + deviceAdapter.notifyItemMoved(0, dataRows.size) + deviceAdapter.notifyItemRangeChanged(0, dataRows.size) + } else { + dataRows.removeAt(clickedPosition) + deviceAdapter.notifyItemRemoved(clickedPosition) + deviceAdapter.notifyItemRangeChanged( + clickedPosition, dataRows.size - clickedPosition + ) + } + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE + } + } + } val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + LocaleConstant.DEVICE_OPERATE_IMAGES[0], LocaleConstant.DEVICE_OPERATE_TITLES[0] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + LocaleConstant.DEVICE_OPERATE_IMAGES[1], LocaleConstant.DEVICE_OPERATE_TITLES[1] ) ) add( EasyPopupWindow.MenuItem( - LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + LocaleConstant.DEVICE_OPERATE_IMAGES[2], LocaleConstant.DEVICE_OPERATE_TITLES[2] ) ) } @@ -97,8 +122,8 @@ } else { 0 } - pageIndex = 1 - obtainDeviceListByPage() + page = 1 + getDeviceListByPage() } 1 -> { @@ -113,21 +138,20 @@ override fun onConfirmClick() { val ids = ArrayList() - dataBeans.forEach { + dataRows.forEach { if (!it.deviceId.isNullOrBlank()) { ids.add(it.deviceId.toLong()) } } isDeleteAll = true deviceViewModel.deleteDeviceById(ids) - } }).build().show() } 2 -> { MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) + .setTitle("选择设备").setDataSource(dataRows) .setNegativeButton("取消").setPositiveButton("选好了") .setOnDialogButtonClickListener(object : MultiSelectDialog.OnDialogButtonClickListener { @@ -150,101 +174,36 @@ } } }) - easyPopupWindow.setBackgroundDrawable(null) } - override fun observeRequestState() { - groupViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") - else -> LoadingDialog.dismiss() + private fun bindRecyclerView(result: DeviceListModel) { + dataRows = result.data!! + when { + isRefresh -> { + binding.refreshView.finishRefresh() + isRefresh = false + deviceAdapter.refresh(dataRows) } - } - } - override fun initEvent() { - binding.groupDeviceLayout.setOnRefreshListener { - isRefresh = true - //刷新之后页码重置 - pageIndex = 1 - obtainDeviceListByPage() - } - binding.groupDeviceLayout.setOnLoadMoreListener { - isLoadMore = true - pageIndex++ - obtainDeviceListByPage() - } - - groupViewModel.deviceListModel.observe(this) { - if (it.code == 200) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - binding.groupDeviceLayout.finishRefresh() - isRefresh = false - } - - isLoadMore -> { - if (dataRows?.size == 0) { - "到底了,别拉了".show(this) - } - dataBeans.addAll(dataRows!!) - binding.groupDeviceLayout.finishLoadMore() - isLoadMore = false - } - - else -> { - dataBeans = dataRows!! - } + isLoadMore -> { + binding.refreshView.finishLoadMore() + isLoadMore = false + if (dataRows.size == 0) { + "到底了,别拉了".show(this) } - weakReferenceHandler.sendEmptyMessage(2022070601) + deviceAdapter.loadMore(dataRows) } - } - deviceViewModel.deleteResult.observe(this) { - if (it.code == 200) { - if (isDeleteAll) { - dataBeans.removeAll(dataBeans) - deviceAdapter.notifyItemMoved(0, dataBeans.size) - deviceAdapter.notifyItemRangeChanged(0, dataBeans.size) + else -> { + if (dataRows.size == 0) { + binding.emptyView.visibility = View.VISIBLE + binding.recyclerView.visibility = View.GONE } else { - dataBeans.removeAt(clickedPosition) - deviceAdapter.notifyItemRemoved(clickedPosition) - deviceAdapter.notifyItemRangeChanged( - clickedPosition, dataBeans.size - clickedPosition - ) - } - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } - } - } - } - - private fun obtainDeviceListByPage() { - groupViewModel.obtainDeviceListByPage(groupId, order, pageIndex) - } - - private val callback = Handler.Callback { - if (it.what == 2022070601) { - if (isRefresh || isLoadMore) { - deviceAdapter.notifyDataSetChanged() - } else { - if (dataBeans.size == 0) { - binding.emptyInclude.emptyView.showEmptyPage("这里什么都没有") { - pageIndex = 1 - obtainDeviceListByPage() - } - } else { - binding.emptyInclude.emptyView.hide() - deviceAdapter = DeviceListAdapter(this, dataBeans) + binding.emptyView.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE + deviceAdapter = DeviceListAdapter(this, dataRows) //绑定侧滑事件 - swipeAction.attachToRecyclerView(binding.groupDeviceView) + swipeAction.attachToRecyclerView(binding.recyclerView) val linearLayoutManager = object : LinearLayoutManager(this) { override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( @@ -253,34 +212,65 @@ ) } } - binding.groupDeviceView.layoutManager = linearLayoutManager - binding.groupDeviceView.adapter = deviceAdapter + binding.recyclerView.layoutManager = linearLayoutManager + binding.recyclerView.addItemDecoration( + RecyclerViewItemOffsets( + marginOffsets, marginOffsets, marginOffsets, marginOffsets + ) + ) + binding.recyclerView.adapter = deviceAdapter deviceAdapter.setOnItemClickListener(object : DeviceListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看设备详情".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } - override fun onHistoryClicked(position: Int) { - if (dataBeans[position].devcode.isNullOrBlank()) { + override fun onHistoryClicked(item: DeviceListModel.DataModel) { + if (item.devcode.isNullOrBlank()) { "设备编号为空,无法查看历史数据".show(context) return } - navigatePageTo( - arrayListOf(groupId, dataBeans[position].devcode) - ) + navigatePageTo(arrayListOf(groupId, item.devcode)) } }) } } } - true + } + + override fun observeRequestState() { + groupViewModel.loadState.observe(this) { + if (isRefresh || isLoadMore) { + return@observe + } + + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.refreshView.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + page = 1 + getDeviceListByPage() + } + binding.refreshView.setOnLoadMoreListener { + isLoadMore = true + page++ + getDeviceListByPage() + } + } + + private fun getDeviceListByPage() { + groupViewModel.getDeviceListByPage(groupId, order, page) } private val swipeAction = @@ -290,7 +280,7 @@ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { clickedPosition = viewHolder.bindingAdapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return @@ -328,7 +318,7 @@ override fun onConfirmClick() { clickedPosition = adapterPosition //删除数据库里对应的数据 - val deviceId = dataBeans[clickedPosition].deviceId + val deviceId = dataRows[clickedPosition].deviceId if (deviceId.isNullOrBlank()) { "管盯ID错误,不可删除,请检查数据源".show(context) return diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 6890e74..4466dd8 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -54,6 +54,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -77,6 +78,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -96,6 +98,7 @@ } } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) @@ -134,6 +137,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index b88476b..c873077 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -26,7 +26,7 @@ val groupListModel = MutableLiveData() val changeGroupResult = MutableLiveData() - fun obtainProGroupList() = launch({ + fun getProGroupList() = launch({ val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { @@ -54,12 +54,13 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) - fun obtainDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ + fun getDeviceListByPage(groupId: String, order: Int, page: Int) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByPage(groupId, order, page) + val response = RetrofitServiceManager.getDeviceListByPage(groupId, order, page) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -71,6 +72,7 @@ response.toErrorMessage().show(BaseApplication.obtainInstance()) } }, { + loadState.value = LoadState.Fail it.printStackTrace() }) diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt deleted file mode 100644 index cb14054..0000000 --- a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.casic.smarttube.widgets - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Point -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import com.amap.api.maps.Projection -import com.amap.api.maps.model.BitmapDescriptorFactory -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.LatLngBounds -import com.amap.api.maps.model.MarkerOptions -import com.casic.smarttube.R -import com.pengxh.kt.lite.extensions.toBitmap -import java.util.* - -class GaoDeClusterMarkerView( - private val context: Context, firstMarkers: MarkerOptions, - projection: Projection, gridSize: Int -) { - //当前可观区域里的 聚合过之后的集合 - private val includeMarkers: ArrayList - - // 创建区域 - val bounds: LatLngBounds - var options: MarkerOptions = MarkerOptions() - - init { - val screenLocation = projection.toScreenLocation(firstMarkers.position) - //范围类 - val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize) - //范围类 - val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize) - bounds = LatLngBounds( - projection.fromScreenLocation(southwestPoint), - projection.fromScreenLocation(northeastPoint) - ) - //设置初始化marker属性 - options.anchor(0.5f, 1.3f) - .title(firstMarkers.title) - .position(firstMarkers.position) - .icon(firstMarkers.icon) - .snippet(firstMarkers.snippet) - .draggable(false) - includeMarkers = ArrayList() - includeMarkers.add(firstMarkers) - } - - /** - * 添加marker - */ - fun addMarker(markerOptions: MarkerOptions) { - includeMarkers.add(markerOptions) // 添加到列表中 - } - - /** - * 设置聚合点的中心位置以及图标 - */ - fun setPositionAndIcon() { - val size = includeMarkers.size - var lat = 0.0 - var lng = 0.0 - // 一个的时候 - if (size == 1) { //设置marker单个属性 - // 设置marker位置 - options.position( - LatLng( - includeMarkers[0].position.latitude, - includeMarkers[0].position.longitude - ) - ) - } else { // 聚合的时候 - //设置marker聚合属性 - for (op in includeMarkers) { - lat += op.position.latitude - lng += op.position.longitude - } - // 设置marker的位置为中心位置为聚集点的平均位置 - options.position(LatLng(lat / size, lng / size)) - } - options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size))) - } - - /** - * marker视图 - */ - private fun getBitmap(num: Int): Bitmap? { - val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null) - val wellCountView = view.findViewById(R.id.wellCountView) - return if (num > 1) { - wellCountView.visibility = View.VISIBLE - wellCountView.text = String.format("${num}个") - wellCountView.gravity = Gravity.CENTER - view.toBitmap() - } else { - wellCountView.visibility = View.GONE - BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap - } - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index c6c6c6f..9e0267b 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="关于我们" /> + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" /> - + + android:layout_height="match_parent"> - - - - + android:layout_height="wrap_content" /> @@ -13,6 +13,7 @@ android:layout_height="wrap_content" android:background="@color/mainThemeColor" app:tbv_show_right_image="false" + app:tbv_smaller_title="true" app:tbv_text="设备最新数据地图展示" /> + app:tbv_smaller_title="true" + app:tbv_text="首页" /> + android:textSize="@dimen/sp_16" /> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_refresh_white" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="概览" /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv.xml b/app/src/main/res/layout/item_device_rv.xml deleted file mode 100644 index c2c6857..0000000 --- a/app/src/main/res/layout/item_device_rv.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_device_rv_l.xml b/app/src/main/res/layout/item_device_rv_l.xml new file mode 100644 index 0000000..2657f5c --- /dev/null +++ b/app/src/main/res/layout/item_device_rv_l.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_group_over_view_rv.xml b/app/src/main/res/layout/item_group_over_view_rv.xml deleted file mode 100644 index 8c7436d..0000000 --- a/app/src/main/res/layout/item_group_over_view_rv.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_group_over_view_rv_l.xml b/app/src/main/res/layout/item_group_over_view_rv_l.xml new file mode 100644 index 0000000..e7179c6 --- /dev/null +++ b/app/src/main/res/layout/item_group_over_view_rv_l.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/widget_view_empty.xml b/app/src/main/res/layout/widget_view_empty.xml index f2316ab..f5b48f1 100644 --- a/app/src/main/res/layout/widget_view_empty.xml +++ b/app/src/main/res/layout/widget_view_empty.xml @@ -13,7 +13,6 @@