opt 出行面板本地数据存储
This commit is contained in:
@@ -8,4 +8,8 @@ package com.zhidao.mogo.module.event.panel
|
||||
object EventPanelConstants {
|
||||
const val MODULE_NAME = "MODULE_EVENT_PANEL"
|
||||
const val PATH_NAME = "/event/panel"
|
||||
|
||||
const val ROAD_EVENT_USEFUL = "2"
|
||||
const val ROAD_EVENT_UNUSEFUL = "1"
|
||||
const val ROAD_EVENT_USEFUL_STATUS_UNSET = "0"
|
||||
}
|
||||
@@ -46,6 +46,10 @@ class EventPanelModuleProvider : IEventPanelProvider {
|
||||
EventPanelFragment.getInstance().showPanel()
|
||||
}
|
||||
|
||||
override fun isPanelShow(): Boolean {
|
||||
return EventPanelFragment.getInstance().isPanelShow()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 隐藏面板
|
||||
|
||||
@@ -2,16 +2,24 @@ package com.zhidao.mogo.module.event.panel.bean
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.zhidao.mogo.module.event.panel.EventPanelConstants.ROAD_EVENT_USEFUL_STATUS_UNSET
|
||||
|
||||
/**
|
||||
* 出行记录本地存储封装类
|
||||
* 出行记录本地存储封装类,此类标识了数据库表名以及字段名
|
||||
*
|
||||
* @author
|
||||
* @author tongchenfei
|
||||
*/
|
||||
@Entity
|
||||
data class TripRecord(@PrimaryKey(autoGenerate = false)
|
||||
var eventType:Int,
|
||||
var canUsed: Boolean = true,
|
||||
var isUsed: Boolean = false,
|
||||
var entity: String? = null,
|
||||
var recordTime: Long = 0)
|
||||
var id: Int,
|
||||
var eventId: String = "",
|
||||
var eventType: Int,
|
||||
/**
|
||||
* 是否有用
|
||||
* 1 - 没用
|
||||
* 2 - 有用
|
||||
* 0 - 未设置
|
||||
*/
|
||||
var usefulStatus: String = ROAD_EVENT_USEFUL_STATUS_UNSET,
|
||||
var entity: String = "",
|
||||
var recordTime: Long = System.currentTimeMillis())
|
||||
@@ -10,7 +10,15 @@ interface TripRecordDao {
|
||||
* @param limitTime 当日0点的时间戳
|
||||
*/
|
||||
@Query(value = "SELECT * FROM TripRecord WHERE recordTime > :limitTime ORDER BY recordTime DESC")
|
||||
fun getAllTripRecord(limitTime:Long):Single<List<TripRecord>>
|
||||
fun queryAllTripRecord(limitTime:Long):Single<List<TripRecord>>
|
||||
|
||||
/**
|
||||
* 根据事件id获取出行动态
|
||||
*
|
||||
* @param eventId 事件id [com.mogo.module.common.entity.V2XRoadEventEntity.noveltyInfo.infoId]
|
||||
*/
|
||||
@Query(value = "SELECT * FROM TripRecord WHERE eventId = :eventId")
|
||||
fun queryTripRecordByEventId(eventId:String):Single<TripRecord>
|
||||
|
||||
@Insert
|
||||
fun insert(vararg tripRecord: TripRecord)
|
||||
|
||||
@@ -31,7 +31,13 @@ class EventPanelFragment : MvpFragment<EventPanelFragment, EventPanelPresenter>(
|
||||
override fun initViews() {
|
||||
Logger.d(MODULE_NAME, "EventPanelFragment init view===")
|
||||
vpEventPanel.adapter = EventPagerAdapter(this)
|
||||
|
||||
btnShowOrHidePanels.setOnClickListener {
|
||||
if (vpEventPanel.visibility == View.GONE) {
|
||||
showPanel()
|
||||
}else{
|
||||
hidePanel()
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun createPresenter(): EventPanelPresenter {
|
||||
return EventPanelPresenter(this)
|
||||
@@ -39,11 +45,17 @@ class EventPanelFragment : MvpFragment<EventPanelFragment, EventPanelPresenter>(
|
||||
|
||||
fun showPanel(){
|
||||
Logger.d(MODULE_NAME,"in fragment show panel")
|
||||
clPanelContainer.visibility = View.VISIBLE
|
||||
vpEventPanel.visibility = View.VISIBLE
|
||||
btnShowOrHidePanels.text = "隐藏面板"
|
||||
}
|
||||
|
||||
fun hidePanel(){
|
||||
Logger.d(MODULE_NAME,"in fragment hide panel")
|
||||
clPanelContainer.visibility = View.GONE
|
||||
vpEventPanel.visibility = View.GONE
|
||||
btnShowOrHidePanels.text = "显示面板"
|
||||
}
|
||||
|
||||
fun isPanelShow():Boolean{
|
||||
return vpEventPanel.visibility == View.VISIBLE
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.zhidao.mogo.module.event.panel.fragment
|
||||
|
||||
import android.util.Log
|
||||
import com.mogo.commons.mvp.MvpFragment
|
||||
import com.mogo.module.common.entity.V2XMessageEntity
|
||||
import com.mogo.utils.logger.Logger
|
||||
import com.zhidao.mogo.module.event.panel.EventPanelConstants.MODULE_NAME
|
||||
import com.zhidao.mogo.module.event.panel.R
|
||||
@@ -14,14 +15,17 @@ import kotlin.random.Random
|
||||
* 出行动态fragment
|
||||
*/
|
||||
const val TAG = "TripRecordFragment"
|
||||
class TripRecordFragment: MvpFragment<TripRecordFragment, TripRecordPresenter>() {
|
||||
|
||||
class TripRecordFragment : MvpFragment<TripRecordFragment, TripRecordPresenter>() {
|
||||
private val tripRecordList = ArrayList<TripRecord>()
|
||||
override fun getLayoutId(): Int = R.layout.module_event_panel_fragment_trip_record
|
||||
private val typeArray = arrayOf(V2XMessageEntity.V2XTypeEnum.ALERT_ROAD_WARNING, V2XMessageEntity.V2XTypeEnum.ALERT_ILLEGAL_PARK_WARNING, V2XMessageEntity.V2XTypeEnum.ALERT_SEEK_WARNING)
|
||||
|
||||
override fun initViews() {
|
||||
btnInsert.setOnClickListener {
|
||||
val randomType = Random.nextInt(10000)
|
||||
val tripRecord = TripRecord(randomType)
|
||||
val randomId = Random.nextInt(10000)
|
||||
val randomType = Random.nextInt(3)
|
||||
val tripRecord = TripRecord(id = randomId, eventType = typeArray[randomType])
|
||||
val random = Random.nextInt(10)
|
||||
tripRecord.entity = "entity: $random"
|
||||
tripRecord.recordTime = System.currentTimeMillis()
|
||||
@@ -40,7 +44,7 @@ class TripRecordFragment: MvpFragment<TripRecordFragment, TripRecordPresenter>()
|
||||
btnUpdate.setOnClickListener {
|
||||
val random = Random.nextInt(tripRecordList.size)
|
||||
val tripRecord = tripRecordList[random]
|
||||
Log.d(TAG,"before update: $tripRecord")
|
||||
Log.d(TAG, "before update: $tripRecord")
|
||||
tripRecord.recordTime = System.currentTimeMillis()
|
||||
mPresenter.updateTripRecords(tripRecord)
|
||||
Log.d(TAG, "update over: $tripRecord")
|
||||
@@ -52,11 +56,19 @@ class TripRecordFragment: MvpFragment<TripRecordFragment, TripRecordPresenter>()
|
||||
}
|
||||
}
|
||||
|
||||
override fun createPresenter(): TripRecordPresenter = TripRecordPresenter(this)
|
||||
override fun createPresenter(): TripRecordPresenter = TripRecordPresenter(this)
|
||||
|
||||
fun refreshTripRecord(tripRecords: List<TripRecord>) {
|
||||
Logger.d(MODULE_NAME, "刷新出行动态:$tripRecords")
|
||||
fun refreshTripRecordList(tripRecords: List<TripRecord>) {
|
||||
Logger.d(MODULE_NAME, "刷新出行动态列表:$tripRecords")
|
||||
tripRecordList.clear()
|
||||
tripRecordList.addAll(tripRecords)
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新单个出行动态,如果无此动态,新增动态
|
||||
*/
|
||||
fun refreshTripRecord(tripRecord: TripRecord) {
|
||||
Logger.d(MODULE_NAME, "刷新单个出行动态: $tripRecord")
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,71 +1,162 @@
|
||||
package com.zhidao.mogo.module.event.panel.presenter
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import com.mogo.commons.mvp.Presenter
|
||||
import com.mogo.module.common.entity.V2XMessageEntity
|
||||
import com.mogo.module.common.entity.V2XMessageEntity.V2XTypeEnum.*
|
||||
import com.mogo.module.common.entity.V2XRoadEventEntity
|
||||
import com.mogo.utils.ThreadPoolService
|
||||
import com.mogo.utils.logger.Logger
|
||||
import com.mogo.utils.network.utils.GsonUtil
|
||||
import com.zhidao.mogo.module.event.panel.EventPanelConstants.MODULE_NAME
|
||||
import com.zhidao.mogo.module.event.panel.bean.TripRecord
|
||||
import com.zhidao.mogo.module.event.panel.dao.TripRecordDatabase
|
||||
import com.zhidao.mogo.module.event.panel.fragment.TripRecordFragment
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.util.*
|
||||
|
||||
private const val BROADCAST_SCENE_EVENT_ACTION = "com.v2x.scene_local_broadcast"
|
||||
private const val BROADCAST_SCENE_MODIFY_ACTION = "com.zhidao.tanlu.dataerror"
|
||||
|
||||
private const val BROADCAST_SCENE_EXTRA_KEY = "V2XMessageEntity"
|
||||
private const val BORADCAST_SCENE_MODIFY_EVENT_ID_KEY = "id"
|
||||
private const val BROADCAST_SCENE_MODIFY_EVENT_UPDATE_TYPE_KEY = "updateType"
|
||||
|
||||
class TripRecordPresenter(view: TripRecordFragment) : Presenter<TripRecordFragment>(view) {
|
||||
var queryDisposable:Disposable? = null
|
||||
private val sceneEventReceiver = SceneEventReceiver()
|
||||
private val tripRecordDao = TripRecordDatabase.getInstance(context).getTripRecordDao()
|
||||
|
||||
init {
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(sceneEventReceiver, IntentFilter(BROADCAST_SCENE_EVENT_ACTION))
|
||||
context.registerReceiver(sceneEventReceiver, IntentFilter(BROADCAST_SCENE_MODIFY_ACTION))
|
||||
}
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
fun queryAllTripRecord() {
|
||||
queryDisposable = TripRecordDatabase.getInstance(context).getTripRecordDao().getAllTripRecord(countLimitTime()).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).map {
|
||||
Logger.d(MODULE_NAME,"delete over time record when query thread is ${Thread.currentThread().name}")
|
||||
TripRecordDatabase.getInstance(context).getTripRecordDao().deleteOvertimeTripRecord(countLimitTime())
|
||||
val queryDisposable = tripRecordDao.queryAllTripRecord(countLimitTime()).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).map {
|
||||
Logger.d(MODULE_NAME, "delete over time record when query thread is ${Thread.currentThread().name}")
|
||||
tripRecordDao.deleteOvertimeTripRecord(countLimitTime())
|
||||
it
|
||||
}.observeOn(AndroidSchedulers.mainThread()).subscribe {it->
|
||||
}.observeOn(AndroidSchedulers.mainThread()).subscribe { it ->
|
||||
Log.d(MODULE_NAME, "db query: $it, thread is ${Thread.currentThread().name}")
|
||||
mView.refreshTripRecordList(it)
|
||||
}
|
||||
compositeDisposable.add(queryDisposable)
|
||||
}
|
||||
|
||||
fun insertTripRecord(record: TripRecord) {
|
||||
val disposable = Single.create<TripRecord> {
|
||||
Logger.d(MODULE_NAME, "准备将数据插入数据库: $record")
|
||||
tripRecordDao.insert(record)
|
||||
it.onSuccess(record)
|
||||
}.subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).map {
|
||||
// 为了防止只进不出,所以在插入新数据时,进行过期数据删除操作
|
||||
Logger.d(MODULE_NAME, "delete over time record when insert: $it")
|
||||
tripRecordDao.deleteOvertimeTripRecord(countLimitTime())
|
||||
record
|
||||
}.observeOn(AndroidSchedulers.mainThread()).subscribe{it->
|
||||
Logger.d(MODULE_NAME, "插入+删除操作完成,做界面展示===$it")
|
||||
mView.refreshTripRecord(it)
|
||||
}
|
||||
compositeDisposable.add(disposable)
|
||||
}
|
||||
|
||||
fun insertTripRecord(vararg records: TripRecord) {
|
||||
fun updateTripRecords(vararg records: TripRecord) {
|
||||
ThreadPoolService.execute {
|
||||
TripRecordDatabase.getInstance(context).getTripRecordDao().insert(*records)
|
||||
// 为了防止只进不出,所以在插入新数据时,进行过期数据删除操作
|
||||
Logger.d(MODULE_NAME,"delete over time record when insert")
|
||||
TripRecordDatabase.getInstance(context).getTripRecordDao().deleteOvertimeTripRecord(countLimitTime())
|
||||
tripRecordDao.update(*records)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTripRecords(vararg records: TripRecord) {
|
||||
fun deleteTripRecords(vararg records: TripRecord) {
|
||||
ThreadPoolService.execute {
|
||||
TripRecordDatabase.getInstance(context).getTripRecordDao().update(*records)
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteTripRecords(vararg records: TripRecord) {
|
||||
ThreadPoolService.execute {
|
||||
TripRecordDatabase.getInstance(context).getTripRecordDao().delete(*records)
|
||||
tripRecordDao.delete(*records)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算约束时间,即当日0时
|
||||
*/
|
||||
private fun countLimitTime():Long{
|
||||
private fun countLimitTime(): Long {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.time = Date()
|
||||
calendar.set(Calendar.HOUR_OF_DAY,0)
|
||||
calendar.set(Calendar.MINUTE,0)
|
||||
calendar.set(Calendar.SECOND,0)
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0)
|
||||
calendar.set(Calendar.MINUTE, 0)
|
||||
calendar.set(Calendar.SECOND, 0)
|
||||
return calendar.timeInMillis
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
super.onDestroy(owner)
|
||||
queryDisposable?.let {
|
||||
if (!it.isDisposed) {
|
||||
it.dispose()
|
||||
}
|
||||
if(!compositeDisposable.isDisposed) {
|
||||
compositeDisposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理道路事件推送,保存到本地数据库
|
||||
* 目前只处理道路事件,违章提醒,他车求助,其他事件暂不处理
|
||||
*/
|
||||
private fun dealSceneMessage(type: Int, content: Any) {
|
||||
if (type in arrayOf(ALERT_ROAD_WARNING, ALERT_ILLEGAL_PARK_WARNING, ALERT_SEEK_WARNING)) {
|
||||
val eventId = if(type == ALERT_ROAD_WARNING){
|
||||
val event = content as V2XRoadEventEntity
|
||||
event.noveltyInfo.infoId
|
||||
}else{
|
||||
""
|
||||
}
|
||||
Logger.d(MODULE_NAME, "处理场景事件,准备插入数据库===eventId: $eventId")
|
||||
insertTripRecord(TripRecord(id = content.hashCode(), eventId = eventId, eventType = type, entity = GsonUtil.jsonFromObject(content)))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地数据库同步v2x传过来的纠错信息
|
||||
*/
|
||||
private fun syncRoadEventModifyState(eventId: String, modifyType: String) {
|
||||
Logger.d(MODULE_NAME, "准备同步纠错信息: $eventId, $modifyType")
|
||||
val disposable = tripRecordDao.queryTripRecordByEventId(eventId).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).map {
|
||||
Logger.d(MODULE_NAME, "查询将纠错数据: $it")
|
||||
it.usefulStatus = modifyType
|
||||
it
|
||||
}.map {
|
||||
Logger.d(MODULE_NAME, "准备更新纠错数据: $it")
|
||||
tripRecordDao.update(it)
|
||||
it
|
||||
}.observeOn(AndroidSchedulers.mainThread()).subscribe { it->
|
||||
Logger.d(MODULE_NAME, "数据纠错更新完成,准备刷新界面==$it")
|
||||
mView.refreshTripRecord(it)
|
||||
}
|
||||
compositeDisposable.add(disposable)
|
||||
}
|
||||
|
||||
inner class SceneEventReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Logger.d(MODULE_NAME, "收到V2X事件推送===")
|
||||
when (intent.action) {
|
||||
BROADCAST_SCENE_EVENT_ACTION -> {
|
||||
// 道路事件推送
|
||||
val message = intent.getSerializableExtra(BROADCAST_SCENE_EXTRA_KEY) as V2XMessageEntity<*>
|
||||
Logger.d(MODULE_NAME, "道路事件推送 type: ${message.type}, content: ${message.content}")
|
||||
dealSceneMessage(message.type, message.content)
|
||||
}
|
||||
BROADCAST_SCENE_MODIFY_ACTION -> {
|
||||
// 纠错推送
|
||||
syncRoadEventModifyState(intent.getStringExtra(BORADCAST_SCENE_MODIFY_EVENT_ID_KEY), intent.getStringExtra(BROADCAST_SCENE_MODIFY_EVENT_UPDATE_TYPE_KEY))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/clPanelContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@@ -7,5 +8,18 @@
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/vpEventPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/btnShowOrHidePanels"
|
||||
android:text="显示面板"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#000"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="10dp"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -21,6 +21,7 @@
|
||||
android:text="Insert"
|
||||
android:textColor="#000"
|
||||
android:textSize="30sp"
|
||||
android:layout_marginTop="100dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/btnUpdate"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@@ -32,6 +33,7 @@
|
||||
android:text="Update"
|
||||
android:textColor="#000"
|
||||
android:textSize="30sp"
|
||||
android:layout_marginTop="100dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/btnInsert"
|
||||
app:layout_constraintRight_toLeftOf="@+id/btnDelete"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@@ -43,6 +45,7 @@
|
||||
android:text="Delete"
|
||||
android:textColor="#000"
|
||||
android:textSize="30sp"
|
||||
android:layout_marginTop="100dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/btnUpdate"
|
||||
app:layout_constraintRight_toLeftOf="@+id/btnQuery"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@@ -54,6 +57,7 @@
|
||||
android:text="Query"
|
||||
android:textColor="#000"
|
||||
android:textSize="30sp"
|
||||
android:layout_marginTop="100dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/btnDelete"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@@ -17,4 +17,10 @@ public interface IEventPanelProvider extends IMogoModuleProvider {
|
||||
* 隐藏面板
|
||||
*/
|
||||
void hidePanel();
|
||||
|
||||
/**
|
||||
* 面板是否在展示
|
||||
* @return true-正在展示 false-未展示
|
||||
*/
|
||||
boolean isPanelShow();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user