处理手表步数和分析用户步数数据
1. 数据准备
设置时间范围:2025年8月15日 00:00:00 到 23:59:59
创建24个时间桶(每小时一个),用于按小时分组步数数据
从数据库获取该时间范围内的所有活动(步数)数据
2. 数据分组
将获取到的步数活动数据按小时进行分组
每个活动根据其时间戳分配到对应的小时桶中
3. 步数增量计算
按小时计算步数增量:计算每个小时内的净步数增长
处理跨小时情况:特别处理了跨小时的步数计算逻辑
计算总步数增量:计算整个时间段内的总净步数增长
4. 数据可视化准备
将每小时的步数增量数据转换为图表条目(BarEntry)
为后续的柱状图展示准备数据
以下代码基于Android&Kotlin开发
所需实体类
import androidx.room.*
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
import java.io.Serializabledata class Activity(@Expose(serialize = false, deserialize = false)@PrimaryKey(autoGenerate = true)@ColumnInfovar mId: Int = 0,@ColumnInfo@SerializedName("uid")var userId: Int = 0,@ColumnInfovar mCalorie: Int = 0,@ColumnInfovar mDistance: Int = 0,@ColumnInfovar mMode: Int = 0,@ColumnInfovar mState: Int = 0,@ColumnInfovar mStep: Int = 0,@Expose(serialize = false, deserialize = false)@ColumnInfovar mIsSync:Int = 0,@Expose(serialize = false, deserialize = false)@ColumnInfovar mLocalTime: String = "",@ColumnInfovar mTime: Long = 0,
) : Serializable
查询语句
SELECT * FROM activity WHERE mTime >= :start AND mTime < :end AND mCalorie >= 0 AND mStep <1000000 AND mDistance > 0 ORDER BY mTime ASC;
测试代码
import org.joda.time.DateTime
import com.github.mikephil.charting.data.BarEntry
import com.blankj.utilcode.constant.TimeConstantsprivate fun testActivity() {val startTime = DateTime(2025, 8, 15, 0, 0, 0).millisval endTime = DateTime(2025, 8, 15, 23, 59, 59).millisval values = arrayListOf<BarEntry>()val filterData = linkedMapOf<Long, ArrayList<Activity>>()// 初始化每小时的时间点for (i in 0..23) {filterData[startTime + (TimeConstants.HOUR * i)] = arrayListOf()}// 获取指定时间范围内的活动数据val data = getDatabase().activityDao().getListASC(startTime, endTime)// 将活动数据按小时分组for (activity in data) {val iterator = filterData.entries.iterator()while (iterator.hasNext()) {val entry = iterator.next()val timeThreshold = entry.keyval hourlyActivities = entry.valueif (activity.mTime <= timeThreshold) {hourlyActivities.add(activity)break}}}// 计算每小时的步数增量var previousHourLastStep = 0var hourIndex = 0for (entry in filterData.entries) {val hourlyActivities = entry.valuevar hourlyStepIncrement = 0if (hourlyActivities.isNotEmpty()) {var previousStep = 0var currentHourStepIncrement = 0// 计算该小时内步数的增量for (activity in hourlyActivities) {val currentStep = activity.mStepif (previousStep <= currentStep) {// 处理跨小时的情况if (previousStep == 0 && previousHourLastStep != 0 && currentStep >= previousHourLastStep) {currentHourStepIncrement = currentStep - previousHourLastStep} else {currentHourStepIncrement = currentStep - previousStep}hourlyStepIncrement += currentHourStepIncrement}previousStep = currentStep}// 更新上一小时的最后步数previousHourLastStep = hourlyActivities.last().mStep}val entry = BarEntry(hourIndex.toFloat(), hourlyStepIncrement.toFloat())values.add(entry)Log.d(TAG, "testActivity() called: hour=${entry.x}, step=${entry.y}")hourIndex++}// 计算总步数增量var totalPreviousStep = 0var totalStepIncrement = 0for (activity in data) {val currentStep = activity.mStepif (totalPreviousStep <= currentStep) {totalStepIncrement += currentStep - totalPreviousStep}totalPreviousStep = currentStep}Log.d(TAG, "testActivity: $totalStepIncrement")}
测试结果