fix: 合并冲突

This commit is contained in:
xiaoyan 2023-04-24 10:56:29 +08:00
commit e3a9b09aa2
52 changed files with 1497 additions and 447 deletions

View File

@ -16,6 +16,7 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据--> <!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<!-- 访问网络,网络定位需要上网 --> <!-- 访问网络,网络定位需要上网 -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- 允许访问振动设备 --> <!-- 允许访问振动设备 -->
@ -36,10 +37,10 @@
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true"
android:largeHeap="true" android:largeHeap="true"
android:theme="@style/Theme.OMQualityInspection" android:requestLegacyExternalStorage="true"
android:requestLegacyExternalStorage="true"> android:supportsRtl="true"
android:theme="@style/Theme.OMQualityInspection">
<activity <activity
android:name=".ui.activity.login.LoginActivity" android:name=".ui.activity.login.LoginActivity"
android:exported="true" android:exported="true"
@ -59,7 +60,9 @@
android:screenOrientation="landscape" android:screenOrientation="landscape"
android:theme="@style/Theme.OMQualityInspection" /> android:theme="@style/Theme.OMQualityInspection" />
<meta-data android:name="ScopedStorage" android:value="true" /> <meta-data
android:name="ScopedStorage"
android:value="true" />
</application> </application>
</manifest> </manifest>

View File

@ -27,7 +27,7 @@ class Constant {
/** /**
* 服务器地址 * 服务器地址
*/ */
const val SERVER_ADDRESS = "http://fastmap.navinfo.com/drdc/" const val SERVER_ADDRESS = "http://fastmap.navinfo.com/"
const val DEBUG = true const val DEBUG = true

View File

@ -2,6 +2,7 @@ package com.navinfo.omqs
import android.app.Application import android.app.Application
import android.util.Log import android.util.Log
import com.navinfo.omqs.db.MyRealmModule
import com.navinfo.omqs.tools.FileManager import com.navinfo.omqs.tools.FileManager
import com.navinfo.omqs.ui.manager.TakePhotoManager import com.navinfo.omqs.ui.manager.TakePhotoManager
import com.navinfo.omqs.util.NetUtils import com.navinfo.omqs.util.NetUtils
@ -20,6 +21,7 @@ class OMQSApplication : Application() {
Util.getInstance().init(applicationContext) Util.getInstance().init(applicationContext)
NetUtils.getInstance().init(this) NetUtils.getInstance().init(this)
TakePhotoManager.getInstance().init(this, 1) TakePhotoManager.getInstance().init(this, 1)
FileManager.initRootDir(this)
} }
private fun getKey(inputString: String): String { private fun getKey(inputString: String): String {

View File

@ -0,0 +1,21 @@
package com.navinfo.omqs.bean
import io.realm.RealmObject
import io.realm.annotations.RealmClass
@RealmClass
open class HadLinkDvoBean @JvmOverloads constructor(
/**
* 图幅号
*/
var mesh: String = "",
/**
* linkPid
*/
var linkPid: String = "",
/**
* (几何)加偏后
*/
var geometry: String = ""
) : RealmObject()

View File

@ -3,6 +3,7 @@ package com.navinfo.omqs.bean
import android.os.Parcelable import android.os.Parcelable
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.navinfo.omqs.tools.FileManager
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -17,19 +18,9 @@ data class OfflineMapCityBean @JvmOverloads constructor(
var version: Long = 0L, var version: Long = 0L,
var fileSize: Long = 0L, var fileSize: Long = 0L,
var currentSize: Long = 0L, var currentSize: Long = 0L,
var status: Int = NONE var status: Int = FileManager.Companion.FileDownloadStatus.NONE
) : Parcelable { ) : Parcelable {
companion object Status {
const val NONE = 0 //无状态
const val WAITING = 1 //等待中
const val LOADING = 2 //下载中
const val PAUSE = 3 //暂停
const val ERROR = 4 //错误
const val DONE = 5 //完成
const val UPDATE = 6 //有新版本要更新
}
// // status的转换对象 // // status的转换对象
// var statusEnum: StatusEnum // var statusEnum: StatusEnum
// get() { // get() {

View File

@ -11,20 +11,33 @@ import kotlinx.parcelize.Parcelize
data class ScProblemTypeBean( data class ScProblemTypeBean(
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
var id: Long = 0, var id: Long = 0,
/**
* elementType
* 要素类型
*/
@ColumnInfo("ELEMENT_TYPE")
val elementType: String = "",
/**
* 要素代码
*/
@ColumnInfo("ELEMENT_CODE")
val elementCode: String = "",
/** /**
* 问题分类 * 问题分类
*/ */
@ColumnInfo("CLASS_TYPE") @ColumnInfo("CLASS_TYPE")
var classType: String = "", val classType: String = "",
/** /**
* 问题类型 * 问题类型
*/ */
@ColumnInfo("TYPE") @ColumnInfo("TYPE")
var problemType: String = "", val problemType: String = "",
/** /**
* 问题现象 * 问题现象
*/ */
@ColumnInfo("PHENOMENON") @ColumnInfo("PHENOMENON")
var phenomenon: String = "" val phenomenon: String = ""
) : Parcelable ) : Parcelable

View File

@ -0,0 +1,64 @@
package com.navinfo.omqs.bean
import com.google.gson.annotations.SerializedName
import com.navinfo.omqs.Constant
import com.navinfo.omqs.system.SystemConstant
import com.navinfo.omqs.tools.FileManager.Companion.FileDownloadStatus
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import io.realm.annotations.RealmClass
@RealmClass
open class TaskBean @JvmOverloads constructor(
/**
* 测评任务id
*/
@PrimaryKey
var id: Int = 0,
/**
* 测评任务名称
*/
var evaluationTaskName: String = "",
/**
* 市编码
*/
var cityCode: String = "",
/**
*市名称
*/
var cityName: String = "",
/**
* omdb标准版
*/
var dataVersion: String = "",
/**
* 测评人名称
*/
var evaluatorName: String = "",
/**
* 项目标签
*/
var project: String = "",
/**
* 图幅号
*/
@SerializedName("hadLinkDvo")
var hadLinkDvoList: RealmList<HadLinkDvoBean> = RealmList<HadLinkDvoBean>(),
/**
* 文件大小
*/
var fileSize: Long = 0L,
/**
* 当前下载进度
*/
var currentSize: Long = 0L,
/**
* 当前下载状态
*/
var status: Int = FileDownloadStatus.NONE
) : RealmObject(){
fun getDownLoadUrl():String{
return "${Constant.SERVER_ADDRESS}devcp/download?fileStr=26"
}
}

View File

@ -1,7 +1,9 @@
package com.navinfo.omqs.db package com.navinfo.omqs.db
import com.navinfo.collect.library.data.entity.QsRecordBean import com.navinfo.collect.library.data.entity.QsRecordBean
import com.navinfo.omqs.bean.HadLinkDvoBean
import com.navinfo.omqs.bean.TaskBean
//@io.realm.annotations.RealmModule(classes = [QsRecordBean::class]) @io.realm.annotations.RealmModule(classes = [TaskBean::class, HadLinkDvoBean::class])
//class MyRealmModule { class MyRealmModule {
//} }

View File

@ -5,6 +5,7 @@ import com.navinfo.omqs.db.RealmOperateHelper
import com.navinfo.omqs.db.RoomAppDatabase import com.navinfo.omqs.db.RoomAppDatabase
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
import com.navinfo.omqs.http.taskdownload.TaskDownloadManager
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
@ -34,6 +35,16 @@ class MainActivityModule {
): OfflineMapDownloadManager = ): OfflineMapDownloadManager =
OfflineMapDownloadManager(networkServiceAPI, roomAppDatabase, mapController) OfflineMapDownloadManager(networkServiceAPI, roomAppDatabase, mapController)
/**
* 注入任务下载
*/
@ActivityRetainedScoped
@Provides
fun providesTaskListDownloadManager(
networkServiceAPI: RetrofitNetworkServiceAPI,
): TaskDownloadManager =
TaskDownloadManager(networkServiceAPI)
/** /**
* 实验失败这样创建viewmodel不会在activity销毁的时候同时销毁 * 实验失败这样创建viewmodel不会在activity销毁的时候同时销毁
* 4-14:因为没有传入activity的 owner,无法检测生命周期 * 4-14:因为没有传入activity的 owner,无法检测生命周期

View File

@ -0,0 +1,7 @@
package com.navinfo.omqs.http
class DefaultTaskResponse<T> {
var success: Boolean = false
var msg: String = ""
var obj: T? = null
}

View File

@ -1,6 +1,7 @@
package com.navinfo.omqs.http package com.navinfo.omqs.http
import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.omqs.bean.TaskBean
/** /**
@ -11,4 +12,8 @@ interface NetworkService {
* 获取离线地图城市列表 * 获取离线地图城市列表
*/ */
suspend fun getOfflineMapCityList():NetResult<List<OfflineMapCityBean>> suspend fun getOfflineMapCityList():NetResult<List<OfflineMapCityBean>>
/**
* 获取任务列表
*/
suspend fun getTaskList(evaluatorNo:String): NetResult<DefaultTaskResponse<List<TaskBean>>>
} }

View File

@ -1,6 +1,7 @@
package com.navinfo.omqs.http package com.navinfo.omqs.http
import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.omqs.bean.TaskBean
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import javax.inject.Inject import javax.inject.Inject
@ -32,4 +33,23 @@ class NetworkServiceImpl @Inject constructor(
NetResult.Error(e) NetResult.Error(e)
} }
} }
override suspend fun getTaskList(evaluatorNo: String): NetResult<DefaultTaskResponse<List<TaskBean>>> =
//在IO线程中运行
withContext(Dispatchers.IO) {
return@withContext try {
val result = netApi.retrofitGetTaskList(evaluatorNo)
if (result.isSuccessful) {
if (result.code() == 200) {
NetResult.Success(result.body())
} else {
NetResult.Failure(result.code(), result.message())
}
} else {
NetResult.Failure(result.code(), result.message())
}
} catch (e: Exception) {
NetResult.Error(e)
}
}
} }

View File

@ -1,10 +1,12 @@
package com.navinfo.omqs.http package com.navinfo.omqs.http
import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.omqs.bean.TaskBean
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.Response import retrofit2.Response
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Header import retrofit2.http.Header
import retrofit2.http.Query
import retrofit2.http.Streaming import retrofit2.http.Streaming
import retrofit2.http.Url import retrofit2.http.Url
@ -46,8 +48,15 @@ interface RetrofitNetworkServiceAPI {
*/ */
@Streaming @Streaming
@GET @GET
suspend fun retrofitDownLoadFile(@Header("RANGE") start: String? = "0", @Url url: String):Response<ResponseBody> suspend fun retrofitDownLoadFile(
@Header("RANGE") start: String? = "0",
@Url url: String
): Response<ResponseBody>
@GET("/devcp/task?evaluatType=2")
suspend fun retrofitGetTaskList(
@Query("evaluatorNo") evaluatorNo: String,
): Response<DefaultTaskResponse<List<TaskBean>>>
/** /**
* @FormUrlEncoded 请求格式注解请求实体是一个From表单每个键值对需要使用@Field注解 * @FormUrlEncoded 请求格式注解请求实体是一个From表单每个键值对需要使用@Field注解

View File

@ -112,6 +112,4 @@ class OfflineMapDownloadManager(
scopeMap[id]!!.removeObserver() scopeMap[id]!!.removeObserver()
} }
} }
} }

View File

@ -6,6 +6,8 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.navinfo.omqs.Constant import com.navinfo.omqs.Constant
import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.omqs.tools.FileManager
import com.navinfo.omqs.tools.FileManager.Companion.FileDownloadStatus
import kotlinx.coroutines.* import kotlinx.coroutines.*
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
@ -23,7 +25,7 @@ class OfflineMapDownloadScope(
private val downloadManager: OfflineMapDownloadManager, private val downloadManager: OfflineMapDownloadManager,
val cityBean: OfflineMapCityBean, val cityBean: OfflineMapCityBean,
) : ) :
CoroutineScope by CoroutineScope(Dispatchers.IO) { CoroutineScope by CoroutineScope(Dispatchers.IO + CoroutineName("OfflineMapDownLoad")) {
/** /**
*下载任务用来取消的 *下载任务用来取消的
*/ */
@ -46,7 +48,7 @@ class OfflineMapDownloadScope(
//改进的代码 //改进的代码
fun start() { fun start() {
change(OfflineMapCityBean.WAITING) change(FileDownloadStatus.WAITING)
downloadManager.launchScope(this@OfflineMapDownloadScope) downloadManager.launchScope(this@OfflineMapDownloadScope)
} }
@ -56,7 +58,7 @@ class OfflineMapDownloadScope(
*/ */
fun pause() { fun pause() {
downloadJob?.cancel("pause") downloadJob?.cancel("pause")
change(OfflineMapCityBean.PAUSE) change(FileDownloadStatus.PAUSE)
} }
/** /**
@ -65,11 +67,8 @@ class OfflineMapDownloadScope(
*/ */
fun launch() { fun launch() {
downloadJob = launch() { downloadJob = launch() {
Log.e("jingo", "启动下载1")
download() download()
Log.e("jingo", "启动下载2")
downloadManager.launchNext(cityBean.id) downloadManager.launchNext(cityBean.id)
Log.e("jingo", "启动下载3")
} }
} }
@ -78,7 +77,7 @@ class OfflineMapDownloadScope(
* 是否是等待任务 * 是否是等待任务
*/ */
fun isWaiting(): Boolean { fun isWaiting(): Boolean {
return cityBean.status == OfflineMapCityBean.WAITING return cityBean.status == FileDownloadStatus.WAITING
} }
/** /**
@ -86,7 +85,7 @@ class OfflineMapDownloadScope(
* @param status [OfflineMapCityBean.Status] * @param status [OfflineMapCityBean.Status]
*/ */
private fun change(status: Int) { private fun change(status: Int) {
if (cityBean.status != status || status == OfflineMapCityBean.LOADING) { if (cityBean.status != status || status == FileDownloadStatus.LOADING) {
cityBean.status = status cityBean.status = status
downloadData.postValue(cityBean) downloadData.postValue(cityBean)
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
@ -128,7 +127,7 @@ class OfflineMapDownloadScope(
url = cityBean.url url = cityBean.url
) )
val responseBody = response.body() val responseBody = response.body()
change(OfflineMapCityBean.LOADING) change(FileDownloadStatus.LOADING)
responseBody ?: throw IOException("jingo ResponseBody is null") responseBody ?: throw IOException("jingo ResponseBody is null")
//写入文件 //写入文件
randomAccessFile = RandomAccessFile(fileTemp, "rwd") randomAccessFile = RandomAccessFile(fileTemp, "rwd")
@ -144,7 +143,7 @@ class OfflineMapDownloadScope(
if (readLength != -1) { if (readLength != -1) {
randomAccessFile.write(buffer, 0, readLength) randomAccessFile.write(buffer, 0, readLength)
cityBean.currentSize += readLength cityBean.currentSize += readLength
change(OfflineMapCityBean.LOADING) change(FileDownloadStatus.LOADING)
} else { } else {
break break
} }
@ -155,15 +154,15 @@ class OfflineMapDownloadScope(
val res = val res =
fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}")) fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}"))
Log.e("jingo", "文件下载完成 修改文件 $res") Log.e("jingo", "文件下载完成 修改文件 $res")
change(OfflineMapCityBean.DONE) change(FileDownloadStatus.DONE)
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
downloadManager.mapController.layerManagerHandler.loadBaseMap() downloadManager.mapController.layerManagerHandler.loadBaseMap()
} }
} else { } else {
change(OfflineMapCityBean.PAUSE) change(FileDownloadStatus.PAUSE)
} }
} catch (e: Throwable) { } catch (e: Throwable) {
change(OfflineMapCityBean.ERROR) change(FileDownloadStatus.ERROR)
} finally { } finally {
inputStream?.close() inputStream?.close()
randomAccessFile?.close() randomAccessFile?.close()

View File

@ -0,0 +1,113 @@
package com.navinfo.omqs.http.taskdownload
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import com.navinfo.omqs.bean.TaskBean
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
import java.util.concurrent.ConcurrentHashMap
/**
* 管理任务数据下载
*/
class TaskDownloadManager(
val netApi: RetrofitNetworkServiceAPI,
) {
/**
* 最多同时下载数量
*/
private val MAX_SCOPE = 3
/**
* 存储有哪些城市需要下载的队列
*/
private val scopeMap: ConcurrentHashMap<Int, TaskDownloadScope> by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
ConcurrentHashMap<Int, TaskDownloadScope>()
}
/**
* 存储正在下载的城市队列
*/
private val taskScopeMap: ConcurrentHashMap<Int, TaskDownloadScope> by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
ConcurrentHashMap<Int, TaskDownloadScope>()
}
/**
* 启动下载任务
* 请不要直接使用此方法启动下载任务,它是交由[OfflineMapDownloadScope]进行调用
*/
fun launchScope(scope: TaskDownloadScope) {
if (taskScopeMap.size >= MAX_SCOPE) {
return
}
if (taskScopeMap.contains(scope.taskBean.id)) {
return
}
taskScopeMap[scope.taskBean.id] = scope
scope.launch()
}
/**
* 启动下一个任务,如果有正在等待中的任务的话
* 请不要直接使用此方法启动下载任务,它是交由[OfflineMapDownloadScope]进行调用
* @param previousUrl 上一个下载任务的下载连接
*/
fun launchNext(id: Int) {
taskScopeMap.remove(id)
for (entrySet in scopeMap) {
val downloadScope = entrySet.value
if (downloadScope.isWaiting()) {
launchScope(downloadScope)
break
}
}
}
/**
* 暂停任务
* 只有等待中的任务和正在下载中的任务才可以进行暂停操作
*/
fun pause(id: Int) {
if (taskScopeMap.containsKey(id)) {
val downloadScope = taskScopeMap[id]
downloadScope?.let {
downloadScope.pause()
}
launchNext(id)
}
}
/**
* 将下载任务加入到协程作用域的下载队列里
* 请求一个下载任务[OfflineMapDownloadScope]
* 这是创建[OfflineMapDownloadScope]的唯一途径,请不要通过其他方式创建[OfflineMapDownloadScope]
*/
fun start(id: Int) {
scopeMap[id]?.start()
}
fun addTask(taskBean: TaskBean) {
if (!scopeMap.containsKey(taskBean.id)) {
scopeMap[taskBean.id] = TaskDownloadScope(this, taskBean)
}
}
fun observer(
id: Int, lifecycleOwner: LifecycleOwner, observer: Observer<TaskBean>
) {
if (scopeMap.containsKey(id)) {
scopeMap[id]!!.observer(lifecycleOwner, observer)
}
}
fun removeObserver(id: Int) {
if (scopeMap.containsKey(id)) {
scopeMap[id]!!.removeObserver()
}
}
}

View File

@ -0,0 +1,168 @@
package com.navinfo.omqs.http.taskdownload
import android.util.Log
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.navinfo.omqs.Constant
import com.navinfo.omqs.bean.TaskBean
import com.navinfo.omqs.tools.FileManager.Companion.FileDownloadStatus
import kotlinx.coroutines.*
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.RandomAccessFile
class TaskDownloadScope(
private val downloadManager: TaskDownloadManager,
val taskBean: TaskBean,
) :
CoroutineScope by CoroutineScope(Dispatchers.IO + CoroutineName("OfflineMapDownLoad")) {
/**
*下载任务用来取消的
*/
private var downloadJob: Job? = null
/**
* 管理观察者同时只有一个就行了
*/
private val observer = Observer<Any> {}
// private var lifecycleOwner: LifecycleOwner? = null
/**
*通知UI更新
*/
private val downloadData = MutableLiveData<TaskBean>()
init {
downloadData.value = taskBean
}
//改进的代码
fun start() {
change(FileDownloadStatus.WAITING)
downloadManager.launchScope(this@TaskDownloadScope)
}
/**
* 暂停任务
* 其实就是取消任务移除监听
*/
fun pause() {
downloadJob?.cancel("pause")
change(FileDownloadStatus.PAUSE)
}
/**
* 启动协程进行下载
* 请不要尝试在外部调用此方法,那样会脱离[OfflineMapDownloadManager]的管理
*/
fun launch() {
downloadJob = launch() {
download()
downloadManager.launchNext(taskBean.id)
}
}
/**
* 是否是等待任务
*/
fun isWaiting(): Boolean {
return taskBean.status == FileDownloadStatus.WAITING
}
/**
* 更新任务
* @param status [OfflineMapCityBean.Status]
*/
private fun change(status: Int) {
if (taskBean.status != status || status == FileDownloadStatus.LOADING) {
taskBean.status = status
downloadData.postValue(taskBean)
launch(Dispatchers.IO) {
// downloadManager.roomDatabase.getOfflineMapDao().update(taskBean)
}
}
}
/**
* 添加下载任务观察者
*/
fun observer(owner: LifecycleOwner, ob: Observer<TaskBean>) {
removeObserver()
// this.lifecycleOwner = owner
downloadData.observe(owner, ob)
}
/**
* 下载文件
*/
private suspend fun download() {
var inputStream: InputStream? = null
var randomAccessFile: RandomAccessFile? = null
try {
//创建离线地图 下载文件夹,.map文件夹的下一级
val fileDir = File("${Constant.OFFLINE_MAP_PATH}download")
if (!fileDir.exists()) {
fileDir.mkdirs()
}
val fileTemp =
File("${Constant.OFFLINE_MAP_PATH}download/${taskBean.id}_${taskBean.dataVersion}")
val startPosition = taskBean.currentSize
//验证断点有效性
if (startPosition < 0) throw IOException("jingo Start position less than zero")
val response = downloadManager.netApi.retrofitDownLoadFile(
start = "bytes=$startPosition-",
url = taskBean.getDownLoadUrl()
)
val responseBody = response.body()
change(FileDownloadStatus.LOADING)
responseBody ?: throw IOException("jingo ResponseBody is null")
//写入文件
randomAccessFile = RandomAccessFile(fileTemp, "rwd")
randomAccessFile.seek(startPosition)
taskBean.currentSize = startPosition
inputStream = responseBody.byteStream()
val bufferSize = 1024 * 2
val buffer = ByteArray(bufferSize)
var readLength = 0
while (downloadJob?.isActive == true) {
readLength = inputStream.read(buffer)
if (readLength != -1) {
randomAccessFile.write(buffer, 0, readLength)
taskBean.currentSize += readLength
change(FileDownloadStatus.LOADING)
} else {
break
}
}
Log.e("jingo", "文件下载完成 ${taskBean.currentSize} == ${taskBean.fileSize}")
if (taskBean.currentSize == taskBean.fileSize) {
val res =
fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${taskBean.evaluationTaskName}.zip"))
Log.e("jingo", "文件下载完成 修改文件 $res")
change(FileDownloadStatus.DONE)
} else {
change(FileDownloadStatus.PAUSE)
}
} catch (e: Throwable) {
change(FileDownloadStatus.ERROR)
} finally {
inputStream?.close()
randomAccessFile?.close()
}
}
fun removeObserver() {
downloadData.observeForever(observer)
// lifecycleOwner?.let {
downloadData.removeObserver(observer)
// null
// }
}
}

View File

@ -6,7 +6,19 @@ import com.navinfo.omqs.bean.OfflineMapCityBean
import java.io.File import java.io.File
class FileManager { class FileManager {
companion object { companion object {
object FileDownloadStatus {
const val NONE = 0 //无状态
const val WAITING = 1 //等待中
const val LOADING = 2 //下载中
const val PAUSE = 3 //暂停
const val ERROR = 4 //错误
const val DONE = 5 //完成
const val UPDATE = 6 //有新版本要更新
}
//初始化数据文件夹 //初始化数据文件夹
fun initRootDir(context:Context){ fun initRootDir(context:Context){
// 在SD卡创建项目目录 // 在SD卡创建项目目录
@ -51,7 +63,7 @@ class FileManager {
if (item.isFile && item.name.startsWith(cityBean.id)) { if (item.isFile && item.name.startsWith(cityBean.id)) {
//如果本地文件与从网络获取到版本号一致,表示这个文件已经下载完毕,不用处理了 //如果本地文件与从网络获取到版本号一致,表示这个文件已经下载完毕,不用处理了
if (item.name.contains("_${cityBean.version}.map")) { if (item.name.contains("_${cityBean.version}.map")) {
cityBean.status = OfflineMapCityBean.DONE cityBean.status = FileDownloadStatus.DONE
return return
} }
//文件存在,版本号不对应,留给下面流程处理 //文件存在,版本号不对应,留给下面流程处理
@ -72,16 +84,16 @@ class FileManager {
if (item.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}"))) { if (item.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}"))) {
//删除旧版本数据 //删除旧版本数据
mapFile?.delete() mapFile?.delete()
cityBean.status = OfflineMapCityBean.DONE cityBean.status = FileDownloadStatus.DONE
return return
} }
} else { // 临时文件大小和目标不一致,说明下载了一半 } else { // 临时文件大小和目标不一致,说明下载了一半
cityBean.status = OfflineMapCityBean.PAUSE cityBean.status = FileDownloadStatus.PAUSE
cityBean.currentSize = item.length() cityBean.currentSize = item.length()
return return
} }
} else { //虽然省市id开头一致但是版本号不一致说明之前版本下载了一部分现在要更新了原来下载的文件直接删除 } else { //虽然省市id开头一致但是版本号不一致说明之前版本下载了一部分现在要更新了原来下载的文件直接删除
cityBean.status = OfflineMapCityBean.UPDATE cityBean.status = FileDownloadStatus.UPDATE
item.delete() item.delete()
return return
} }

View File

@ -29,10 +29,10 @@ open abstract class PermissionsActivity : BaseActivity() {
//定位权限 //定位权限
permissionList.add(Permission.ACCESS_FINE_LOCATION) permissionList.add(Permission.ACCESS_FINE_LOCATION)
permissionList.add(Permission.ACCESS_COARSE_LOCATION) permissionList.add(Permission.ACCESS_COARSE_LOCATION)
// //android10 //android10
// if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
// permissionList.add(Permission.ACCESS_BACKGROUND_LOCATION) // permissionList.add(Permission.ACCESS_BACKGROUND_LOCATION)
// } }
XXPermissions.with(this) XXPermissions.with(this)
// 申请单个权限 // 申请单个权限
.permission(permissionList) .permission(permissionList)

View File

@ -4,6 +4,8 @@ import android.os.Bundle
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.databinding.DataBindingUtil import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import com.blankj.utilcode.util.ToastUtils
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController import androidx.navigation.findNavController
import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.map.NIMapController
@ -14,6 +16,8 @@ import com.navinfo.omqs.databinding.ActivityMainBinding
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
import com.navinfo.omqs.system.SystemConstant import com.navinfo.omqs.system.SystemConstant
import com.navinfo.omqs.ui.activity.BaseActivity import com.navinfo.omqs.ui.activity.BaseActivity
import com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment
import com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultViewModel
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
@ -52,8 +56,12 @@ class MainActivity : BaseActivity() {
binding.mainActivity = this binding.mainActivity = this
//给xml传递viewModel对象 //给xml传递viewModel对象
binding.viewModel = viewModel binding.viewModel = viewModel
// lifecycle.addObserver(viewModel)
lifecycleScope viewModel.liveDataQsRecordIdList.observe(this) {
//处理页面跳转
viewModel.navigation(this, it)
}
} }
override fun onStart() { override fun onStart() {
@ -63,9 +71,11 @@ class MainActivity : BaseActivity() {
mapController.locationLayerHandler.startLocation() mapController.locationLayerHandler.startLocation()
//启动轨迹存储 //启动轨迹存储
mapController.locationLayerHandler.setNiLocationListener(NiLocationListener { mapController.locationLayerHandler.setNiLocationListener(NiLocationListener {
binding!!.viewModel!!.addSaveTrace(it) viewModel.addSaveTrace(it)
binding!!.viewModel!!.startSaveTraceThread(this) // binding.viewModel!!.startSaveTraceThread(this)
}) })
//显示轨迹图层
// mapController.layerManagerHandler.showNiLocationLayer(Constant.DATA_PATH+ SystemConstant.USER_ID+"/trace.sqlite")
mapController.layerManagerHandler.showNiLocationLayer() mapController.layerManagerHandler.showNiLocationLayer()
} }
@ -96,6 +106,7 @@ class MainActivity : BaseActivity() {
* 打开相机预览 * 打开相机预览
*/ */
fun openCamera() { fun openCamera() {
binding.viewModel!!.onClickCameraButton(this)
//显示轨迹图层 //显示轨迹图层
//binding!!.viewModel!!.onClickCameraButton(this) //binding!!.viewModel!!.onClickCameraButton(this)
} }
@ -108,7 +119,7 @@ class MainActivity : BaseActivity() {
naviController.navigate(R.id.EvaluationResultFragment) naviController.navigate(R.id.EvaluationResultFragment)
} }
override fun onBackPressed() { // override fun onBackPressed() {
super.onBackPressed() // super.onBackPressed()
} // }
} }

View File

@ -2,12 +2,16 @@ package com.navinfo.omqs.ui.activity.map
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.navigation.findNavController
import com.blankj.utilcode.util.ToastUtils import com.blankj.utilcode.util.ToastUtils
import com.navinfo.collect.library.data.dao.impl.TraceDataBase import com.navinfo.collect.library.data.dao.impl.TraceDataBase
import com.navinfo.collect.library.data.entity.NiLocation import com.navinfo.collect.library.data.entity.NiLocation
import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.map.handler.OnQsRecordItemClickListener
import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.GeometryToolsKt import com.navinfo.collect.library.utils.GeometryToolsKt
import com.navinfo.omqs.Constant import com.navinfo.omqs.Constant
@ -19,7 +23,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.RealmSet import io.realm.RealmSet
import org.oscim.core.GeoPoint import org.oscim.core.GeoPoint
import org.videolan.libvlc.LibVlcUtil import org.videolan.libvlc.LibVlcUtil
import java.util.*
import javax.inject.Inject import javax.inject.Inject
/** /**
@ -30,9 +33,19 @@ class MainViewModel @Inject constructor(
private val mapController: NIMapController, private val mapController: NIMapController,
) : ViewModel() { ) : ViewModel() {
val liveDataQsRecordIdList = MutableLiveData<List<String>>()
private var mCameraDialog: CommonDialog? = null private var mCameraDialog: CommonDialog? = null
private var niLocationList:MutableList<NiLocation> = ArrayList<NiLocation>() private var niLocationList: MutableList<NiLocation> = ArrayList<NiLocation>()
init {
mapController.layerManagerHandler.setOnQsRecordItemClickListener(object :
OnQsRecordItemClickListener {
override fun onQsRecordList(list: MutableList<String>) {
liveDataQsRecordIdList.value = list
}
})
}
/** /**
* 点击我的位置回到我的位置 * 点击我的位置回到我的位置
@ -46,14 +59,21 @@ class MainViewModel @Inject constructor(
} }
//点击相机按钮 //点击相机按钮
fun onClickCameraButton(context: Context){ fun onClickCameraButton(context: Context) {
Log.e("qj", LibVlcUtil.hasCompatibleCPU(context).toString()) Log.e("qj", LibVlcUtil.hasCompatibleCPU(context).toString())
ToastUtils.showShort("点击了相机") ToastUtils.showShort("点击了相机")
if (mCameraDialog == null) { if (mCameraDialog == null) {
mCameraDialog = CommonDialog(context, context.resources.getDimension(R.dimen.head_img_width).toInt() * 3 + context.resources.getDimension(R.dimen.ten).toInt() + context.resources.getDimension(R.dimen.twenty_four).toInt(), context.resources.getDimension(R.dimen.head_img_width).toInt() + 10, 1) mCameraDialog = CommonDialog(
context,
context.resources.getDimension(R.dimen.head_img_width)
.toInt() * 3 + context.resources.getDimension(R.dimen.ten)
.toInt() + context.resources.getDimension(R.dimen.twenty_four).toInt(),
context.resources.getDimension(R.dimen.head_img_width).toInt() + 10,
1
)
mCameraDialog!!.setCancelable(true) mCameraDialog!!.setCancelable(true)
} }
mCameraDialog!!.openCamear(mCameraDialog!!.getmShareUtil().continusTakePhotoState) mCameraDialog!!.openCamear(mCameraDialog!!.getmShareUtil().continusTakePhotoState)
@ -62,10 +82,11 @@ class MainViewModel @Inject constructor(
mCameraDialog!!.hideLoading() mCameraDialog!!.hideLoading()
mCameraDialog!!.stopVideo() mCameraDialog!!.stopVideo()
try { try {
if (!mCameraDialog!!.getmShareUtil().connectstate){ if (!mCameraDialog!!.getmShareUtil().connectstate) {
mCameraDialog!!.updateCameraResources(1, mCameraDialog!!.getmDeviceNum()) mCameraDialog!!.updateCameraResources(1, mCameraDialog!!.getmDeviceNum())
} }
TakePhotoManager.getInstance().getCameraVedioClent(mCameraDialog!!.getmDeviceNum()).StopSearch() TakePhotoManager.getInstance().getCameraVedioClent(mCameraDialog!!.getmDeviceNum())
.StopSearch()
} catch (e: Exception) { } catch (e: Exception) {
} }
}) })
@ -77,12 +98,12 @@ class MainViewModel @Inject constructor(
}) })
} }
fun startSaveTraceThread(context: Context){ fun startSaveTraceThread(context: Context) {
Thread(Runnable { Thread(Runnable {
try { try {
while (true){ while (true) {
if(niLocationList!=null&&niLocationList.size>0){ if (niLocationList != null && niLocationList.size > 0) {
var niLocation = niLocationList[0] var niLocation = niLocationList[0]
val geometry = GeometryTools.createGeometry(GeoPoint(niLocation.latitude,niLocation.longitude)) val geometry = GeometryTools.createGeometry(GeoPoint(niLocation.latitude,niLocation.longitude))
@ -99,23 +120,60 @@ class MainViewModel @Inject constructor(
} }
} }
TraceDataBase.getDatabase(context, Constant.DATA_PATH+ SystemConstant.USER_ID+"/trace.sqlite").niLocationDao.insert(niLocation) TraceDataBase.getDatabase(
context,
Constant.DATA_PATH + SystemConstant.USER_ID + "/trace.sqlite"
).niLocationDao.insert(niLocation)
niLocationList.removeAt(0) niLocationList.removeAt(0)
Log.e("qj","saveTrace") Log.e("qj", "saveTrace")
} }
Thread.sleep(30) Thread.sleep(30)
} }
} catch (e: InterruptedException) { } catch (e: InterruptedException) {
e.printStackTrace() e.printStackTrace()
Log.e("qj","异常==${e.message}") Log.e("qj", "异常==${e.message}")
} }
}).start() }).start()
} }
//增加轨迹存储 //增加轨迹存储
fun addSaveTrace(niLocation: NiLocation){ fun addSaveTrace(niLocation: NiLocation) {
if(niLocation!=null&&niLocationList!=null){ if (niLocation != null && niLocationList != null) {
niLocationList.add(niLocation) niLocationList.add(niLocation)
} }
} }
fun navigation(activity: MainActivity, list: List<String>) {
//获取右侧fragment容器
val naviController = activity.findNavController(R.id.main_activity_right_fragment)
naviController.currentDestination?.let { navDestination ->
// when (val fragment =
// activity.supportFragmentManager.findFragmentById(navDestination.id)) {
// //判断右侧的fragment是不是质检数据
//// is EvaluationResultFragment -> {
//// val viewModelFragment =
//// ViewModelProvider(fragment)[EvaluationResultViewModel::class.java]
//// viewModelFragment.notifyData(list)
//// }
// is EmptyFragment -> {
// if (list.size == 1) {
// val bundle = Bundle()
// bundle.putString("QsId", list[0])
// naviController.navigate(R.id.EvaluationResultFragment, bundle)
// }
// }
// }
when (navDestination.id) {
R.id.EmptyFragment -> {
if (list.size == 1) {
val bundle = Bundle()
bundle.putString("QsId", list[0])
naviController.navigate(R.id.EvaluationResultFragment, bundle)
}
}
}
}
}
} }

View File

@ -4,6 +4,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.navigation.NavOptions import androidx.navigation.NavOptions
import androidx.navigation.findNavController import androidx.navigation.findNavController
import com.navinfo.omqs.R import com.navinfo.omqs.R
@ -14,30 +15,26 @@ import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint @AndroidEntryPoint
class EvaluationResultFragment : BaseFragment(), View.OnClickListener { class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
private var _binding: FragmentEvaluationResultBinding? = null private lateinit var binding: FragmentEvaluationResultBinding
private val binding get() = _binding!!
private val viewModel by shareViewModels<EvaluationResultViewModel>("QsRecode") private val viewModel by shareViewModels<EvaluationResultViewModel>("QsRecode")
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View { ): View {
_binding = FragmentEvaluationResultBinding.inflate(inflater, container, false) binding =
DataBindingUtil.inflate(inflater, R.layout.fragment_evaluation_result, container, false)
binding.fragment = this
binding.viewModel = viewModel
binding.lifecycleOwner = this
return binding.root return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
liveDataObserve() //监听是否退出当前页面
viewModel.liveDataFinish.observe(viewLifecycleOwner) {
/** onBackPressed()
* 点击监听 }
*/
binding.evaluationClassType.setOnClickListener(this)
binding.evaluationProblemType.setOnClickListener(this)
binding.evaluationPhenomenon.setOnClickListener(this)
binding.evaluationLink.setOnClickListener(this)
binding.evaluationCause.setOnClickListener(this)
//返回按钮点击 //返回按钮点击
binding.evaluationBar.setNavigationOnClickListener { binding.evaluationBar.setNavigationOnClickListener {
onBackPressed() onBackPressed()
@ -59,7 +56,17 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
/** /**
* 读取元数据 * 读取元数据
*/ */
viewModel.loadMetadata() if (arguments != null) {
val id = requireArguments().getString("QsId")
if (id != null) {
viewModel.loadData(id)
} else {
viewModel.initNewData()
}
} else {
viewModel.initNewData()
}
// //监听大分类数据变化 // //监听大分类数据变化
// viewModel.liveDataClassTypeList.observe(viewLifecycleOwner) { // viewModel.liveDataClassTypeList.observe(viewLifecycleOwner) {
// if (it == null || it.isEmpty()) { // if (it == null || it.isEmpty()) {
@ -155,43 +162,12 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
// //
// } // }
/**
* 监听liveData
*/
private fun liveDataObserve() {
//监听问题分类更新UI
viewModel.liveDataCurrentClassType.observe(viewLifecycleOwner) {
binding.evaluationClassType.text = it
}
//监听问题类型更新UI
viewModel.liveDataCurrentProblemType.observe(viewLifecycleOwner) {
binding.evaluationProblemType.text = it
}
//监听问题现象更新UI
viewModel.liveDataCurrentPhenomenon.observe(viewLifecycleOwner) {
binding.evaluationPhenomenon.text = it
}
//监听问题环节更新UI
viewModel.liveDataCurrentProblemLink.observe(viewLifecycleOwner) {
binding.evaluationLink.text = it
}
//监听问题初步原因更新UI
viewModel.liveDataCurrentCause.observe(viewLifecycleOwner) {
binding.evaluationCause.text = it
}
//监听是否退出当前页面
viewModel.liveDataFinish.observe(viewLifecycleOwner) {
onBackPressed()
}
}
override fun onDestroyView() { override fun onDestroyView() {
activity?.apply { activity?.apply {
findNavController(R.id.main_activity_middle_fragment).navigateUp() findNavController(R.id.main_activity_middle_fragment).navigateUp()
} }
super.onDestroyView() super.onDestroyView()
_binding = null
} }
/** /**

View File

@ -4,12 +4,12 @@ import android.util.Log
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.navinfo.collect.library.map.GeoPoint
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.data.entity.QsRecordBean import com.navinfo.collect.library.data.entity.QsRecordBean
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.omqs.db.RoomAppDatabase import com.navinfo.omqs.db.RoomAppDatabase
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.Realm import io.realm.Realm
import io.realm.kotlin.where
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.* import java.util.*
@ -28,63 +28,34 @@ class EvaluationResultViewModel @Inject constructor(
val liveDataFinish = MutableLiveData<Boolean>() val liveDataFinish = MutableLiveData<Boolean>()
/** /**
* 问题分类 liveData[PhenomenonLeftAdapter]展示的数据 * 问题分类 liveData[LeftAdapter]展示的数据
*/ */
val liveDataClassTypeList = MutableLiveData<List<String>>() val liveDataLeftTypeList = MutableLiveData<List<String>>()
/** /**
* 问题类型 liveData [PhenomenonMiddleAdapter]展示的数据 * 问题类型 liveData [MiddleAdapter]展示的数据
*/ */
val liveDataProblemTypeList = MutableLiveData<List<String>>() val liveDataMiddleTypeList = MutableLiveData<List<String>>()
/** /**
* 问题现象 liveData [PhenomenonRightGroupHeaderAdapter]展示的数据 * 问题现象 liveData [RightGroupHeaderAdapter]展示的数据
*/ */
val liveDataPhenomenonRightList = MutableLiveData<List<PhenomenonMiddleBean>>() val liveDataRightTypeList = MutableLiveData<List<RightBean>>()
/** var liveDataQsRecordBean = MutableLiveData<QsRecordBean>()
* 当前选择问题分类 [EvaluationResultFragment] 问题分类展示数据
*/
var liveDataCurrentClassType = MutableLiveData<String>()
/**
* 当前选择的问题类型 [EvaluationResultFragment] 问题类型展示数据
*/
var liveDataCurrentProblemType = MutableLiveData<String>()
/**
* 当前选择的问题现象 [EvaluationResultFragment] 问题现象展示数据
*/
var liveDataCurrentPhenomenon = MutableLiveData<String>()
/**
* 当前选择的问题环节 [EvaluationResultFragment] 问题环节展示数据
*/
var liveDataCurrentProblemLink = MutableLiveData<String>()
/**
* 当前选择的问初步原因 [EvaluationResultFragment] 初步原因展示数据
*/
var liveDataCurrentCause = MutableLiveData<String>()
var currentGeoPoint: GeoPoint? = null
var oldBean: QsRecordBean? = null
init { init {
liveDataQsRecordBean.value = QsRecordBean(id = UUID.randomUUID().toString())
Log.e("jingo", "EvaluationResultViewModel 创建了 ${hashCode()}") Log.e("jingo", "EvaluationResultViewModel 创建了 ${hashCode()}")
mapController.markerHandle.apply { mapController.markerHandle.apply {
setOnMapClickListener { setOnMapClickListener {
currentGeoPoint = it liveDataQsRecordBean.value!!.geometry = it.toGeometry()
addMarker(it, markerTitle) addMarker(it, markerTitle)
} }
} }
val geoPoint = mapController.locationLayerHandler.getCurrentGeoPoint()
geoPoint?.let {
currentGeoPoint = it
mapController.markerHandle.addMarker(geoPoint, markerTitle)
}
} }
@ -99,144 +70,181 @@ class EvaluationResultViewModel @Inject constructor(
/** /**
* 查询数据库获取问题分类 * 查询数据库获取问题分类
*/ */
fun loadMetadata() { fun initNewData() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
getClassTypeList() getClassTypeList()
getProblemLinkList() getProblemLinkList()
} }
val geoPoint = mapController.locationLayerHandler.getCurrentGeoPoint()
geoPoint?.let {
liveDataQsRecordBean.value!!.geometry = it.toGeometry()
mapController.markerHandle.addMarker(geoPoint, markerTitle)
}
} }
/** /**
* //获取问题分类列表 * //获取问题分类列表
*/ */
fun getClassTypeList() { fun getClassTypeList() {
Log.e("jingo", "getClassTypeList S")
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList() val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList()
list?.let { list?.let {
if (list.isNotEmpty()) {
//通知页面更新 //通知页面更新
liveDataClassTypeList.postValue(it) liveDataLeftTypeList.postValue(it)
val classType = it[0]
//如果右侧栏没数据,给个默认值 //如果右侧栏没数据,给个默认值
if (liveDataCurrentClassType.value == null) { if (liveDataQsRecordBean.value!!.classType.isEmpty()) {
liveDataCurrentClassType.postValue(it[0]) Log.e("jingo", "getClassTypeList $classType")
liveDataQsRecordBean.value!!.classType = classType
} }
getProblemList(it[0]) getProblemList(classType)
} }
} }
}
Log.e("jingo", "getClassTypeList E")
} }
/** /**
* 获取问题环节列表和初步问题 * 获取问题环节列表和初步问题
*/ */
fun getProblemLinkList() { fun getProblemLinkList() {
Log.e("jingo", "getProblemLinkList S")
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val list = roomAppDatabase.getScRootCauseAnalysisDao().findAllData() val list = roomAppDatabase.getScRootCauseAnalysisDao().findAllData()
list?.let { tl -> list?.let { tl ->
if (tl.isNotEmpty()) { if (tl.isNotEmpty()) {
val typeTitleList = mutableListOf<String>() val middleList = mutableListOf<String>()
val phenomenonRightList = mutableListOf<PhenomenonMiddleBean>() val rightList = mutableListOf<RightBean>()
for (item in tl) { for (item in tl) {
if (!typeTitleList.contains(item.problemLink)) { if (!middleList.contains(item.problemLink)) {
typeTitleList.add(item.problemLink) middleList.add(item.problemLink)
} }
phenomenonRightList.add( rightList.add(
PhenomenonMiddleBean( RightBean(
title = item.problemLink, text = item.problemCause, isSelect = false title = item.problemLink, text = item.problemCause, isSelect = false
) )
) )
} }
if (liveDataQsRecordBean.value!!.problemLink.isEmpty()) {
if (liveDataCurrentProblemLink.value == null) { liveDataQsRecordBean.value!!.problemLink = middleList[0]
liveDataCurrentProblemLink.postValue(phenomenonRightList[0].text) Log.e("jingo", "getProblemLinkList ${middleList[0]}")
} }
if (liveDataCurrentCause.value == null) { if (liveDataQsRecordBean.value!!.cause.isEmpty()) {
liveDataCurrentCause.postValue(typeTitleList[0]) liveDataQsRecordBean.value!!.cause = rightList[0].text
Log.e("jingo", "getProblemLinkList ${rightList[0].text}")
} }
liveDataProblemTypeList.postValue(typeTitleList) liveDataQsRecordBean.postValue(liveDataQsRecordBean.value)
liveDataPhenomenonRightList.postValue(phenomenonRightList) liveDataMiddleTypeList.postValue(middleList)
liveDataRightTypeList.postValue(rightList)
} }
} }
} }
Log.e("jingo", "getProblemLinkList E")
} }
/** /**
* 获取问题类型列表和问题现象 * 获取问题类型列表和问题现象
*/ */
private suspend fun getProblemList(classType: String) { private suspend fun getProblemList(classType: String) {
Log.e("jingo", "getProblemList S")
val typeList = roomAppDatabase.getScProblemTypeDao().findProblemTypeList(classType) val typeList = roomAppDatabase.getScProblemTypeDao().findProblemTypeList(classType)
typeList?.let { tl -> typeList?.let { tl ->
if (tl.isNotEmpty()) { if (tl.isNotEmpty()) {
val typeTitleList = mutableListOf<String>() val typeTitleList = mutableListOf<String>()
val phenomenonRightList = mutableListOf<PhenomenonMiddleBean>() val phenomenonRightList = mutableListOf<RightBean>()
for (item in tl) { for (item in tl) {
if (!typeTitleList.contains(item.problemType)) { if (!typeTitleList.contains(item.problemType)) {
typeTitleList.add(item.problemType) typeTitleList.add(item.problemType)
} }
phenomenonRightList.add( phenomenonRightList.add(
PhenomenonMiddleBean( RightBean(
title = item.problemType, text = item.phenomenon, isSelect = false title = item.problemType, text = item.phenomenon, isSelect = false
) )
) )
} }
if (liveDataCurrentPhenomenon.value == null) { if (liveDataQsRecordBean.value!!.problemType.isEmpty()) {
liveDataCurrentPhenomenon.postValue(phenomenonRightList[0].text) liveDataQsRecordBean.value!!.problemType = typeTitleList[0]
Log.e("jingo", "getProblemList ${typeTitleList[0]}")
} }
if (liveDataCurrentProblemType.value == null) { liveDataMiddleTypeList.postValue(typeTitleList)
liveDataCurrentProblemType.postValue(typeTitleList[0]) if (liveDataQsRecordBean.value!!.phenomenon.isEmpty()) {
liveDataQsRecordBean.value!!.phenomenon = phenomenonRightList[0].text
Log.e("jingo", "getProblemList ${phenomenonRightList[0].text}")
} }
liveDataProblemTypeList.postValue(typeTitleList) liveDataQsRecordBean.postValue(liveDataQsRecordBean.value)
liveDataPhenomenonRightList.postValue(phenomenonRightList) liveDataRightTypeList.postValue(phenomenonRightList)
} }
} }
Log.e("jingo", "getProblemList E")
} }
/** /**
* 查询问题类型 * 查询问题类型列表
*/ */
fun getProblemTypeList(classType: String) { fun getProblemTypeList(classType: String) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
liveDataCurrentClassType.postValue(classType)
getProblemList(classType) getProblemList(classType)
} }
} }
fun setPhenomenonMiddleBean(bean: PhenomenonMiddleBean) { /**
if (liveDataCurrentPhenomenon.value != bean.text) liveDataCurrentPhenomenon.value = * 监听右侧栏的点击事件修改数据
bean.text */
if (liveDataCurrentProblemType.value != bean.title) liveDataCurrentProblemType.value = fun setPhenomenonMiddleBean(adapterBean: RightBean) {
bean.title liveDataQsRecordBean.value!!.phenomenon = adapterBean.text
liveDataQsRecordBean.value!!.problemType = adapterBean.title
liveDataQsRecordBean.postValue(liveDataQsRecordBean.value)
} }
fun setProblemLinkMiddleBean(bean: PhenomenonMiddleBean) { fun setProblemLinkMiddleBean(adapterBean: RightBean) {
if (liveDataCurrentProblemLink.value != bean.text) liveDataCurrentProblemLink.value = liveDataQsRecordBean.value!!.cause = adapterBean.text
bean.text liveDataQsRecordBean.value!!.problemLink = adapterBean.title
if (liveDataCurrentCause.value != bean.title) liveDataCurrentCause.value = bean.title liveDataQsRecordBean.postValue(liveDataQsRecordBean.value)
} }
fun saveData() { fun saveData() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val qsRecord = QsRecordBean(
id = UUID.randomUUID().toString(),
classType = liveDataCurrentClassType.value.toString(),
type = liveDataCurrentProblemType.value.toString(),
phenomenon = liveDataCurrentPhenomenon.value.toString(),
problemLink = liveDataCurrentProblemLink.value.toString(),
cause = liveDataCurrentCause.value.toString(),
)
qsRecord.geometry = currentGeoPoint!!.toGeometry()
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
Log.e("jingo","realm hashCOde ${realm.hashCode()}")
realm.executeTransaction { realm.executeTransaction {
it.copyToRealmOrUpdate(qsRecord) it.copyToRealmOrUpdate(liveDataQsRecordBean.value)
} }
realm.close() // realm.close()
mapController.mMapView.updateMap() mapController.layerManagerHandler.addOrUpdateQsRecordMark(liveDataQsRecordBean.value!!)
liveDataFinish.postValue(true) liveDataFinish.postValue(true)
} }
} }
fun deleteData() { fun deleteData() {
viewModelScope.launch(Dispatchers.IO) {
val realm = Realm.getDefaultInstance()
Log.e("jingo","realm hashCOde ${realm.hashCode()}")
realm.executeTransaction {
val objects = it.where(QsRecordBean::class.java)
.equalTo("id", liveDataQsRecordBean.value?.id).findFirst()
objects?.deleteFromRealm()
}
// realm.close()
mapController.layerManagerHandler.removeQsRecordMark(liveDataQsRecordBean.value!!)
liveDataFinish.postValue(true)
}
}
/**
* 根据数据id查询数据
*/
fun loadData(id: String) {
viewModelScope.launch(Dispatchers.IO) {
val realm = Realm.getDefaultInstance()
val objects = realm.where<QsRecordBean>().equalTo("id", id).findFirst()
if (objects != null) {
oldBean = realm.copyFromRealm(objects)
liveDataQsRecordBean.postValue(oldBean!!.copy())
}
}
} }
} }

View File

@ -7,7 +7,7 @@ import com.navinfo.omqs.databinding.TextItemSelectBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder import com.navinfo.omqs.ui.other.BaseViewHolder
class PhenomenonLeftAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) : class LeftAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) :
BaseRecyclerViewAdapter<String>() { BaseRecyclerViewAdapter<String>() {
private var selectTitle = "" private var selectTitle = ""

View File

@ -7,7 +7,7 @@ import com.navinfo.omqs.databinding.TextItemSelectBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder import com.navinfo.omqs.ui.other.BaseViewHolder
class PhenomenonMiddleAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) : class MiddleAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) :
BaseRecyclerViewAdapter<String>() { BaseRecyclerViewAdapter<String>() {
private var selectTitle = "" private var selectTitle = ""

View File

@ -5,13 +5,9 @@ import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.FragmentPhenomenonBinding import com.navinfo.omqs.databinding.FragmentPhenomenonBinding
import com.navinfo.omqs.ui.fragment.BaseFragment import com.navinfo.omqs.ui.fragment.BaseFragment
import com.navinfo.omqs.ui.other.shareViewModels import com.navinfo.omqs.ui.other.shareViewModels
@ -41,12 +37,15 @@ class PhenomenonFragment :
//左侧菜单 //左侧菜单
binding.phenomenonLeftRecyclerview.setHasFixedSize(true) binding.phenomenonLeftRecyclerview.setHasFixedSize(true)
binding.phenomenonLeftRecyclerview.layoutManager = LinearLayoutManager(requireContext()) binding.phenomenonLeftRecyclerview.layoutManager = LinearLayoutManager(requireContext())
val leftAdapter = PhenomenonLeftAdapter { _, text -> /**
* 监听左侧栏的点击事件
*/
val leftAdapter = LeftAdapter { _, text ->
viewModel.getProblemTypeList(text) viewModel.getProblemTypeList(text)
} }
binding.phenomenonLeftRecyclerview.adapter = leftAdapter binding.phenomenonLeftRecyclerview.adapter = leftAdapter
//左侧菜单查询结果监听 //左侧菜单查询结果监听
viewModel.liveDataClassTypeList.observe(viewLifecycleOwner) { viewModel.liveDataLeftTypeList.observe(viewLifecycleOwner) {
leftAdapter.refreshData(it) leftAdapter.refreshData(it)
} }
@ -55,26 +54,34 @@ class PhenomenonFragment :
var rightLayoutManager = LinearLayoutManager(requireContext()) var rightLayoutManager = LinearLayoutManager(requireContext())
binding.phenomenonRightRecyclerview.layoutManager = rightLayoutManager binding.phenomenonRightRecyclerview.layoutManager = rightLayoutManager
val rightAdapter = PhenomenonRightGroupHeaderAdapter { _, bean -> /**
* 监听右侧栏的点击事件
*/
val rightAdapter = RightGroupHeaderAdapter { _, bean ->
viewModel.setPhenomenonMiddleBean(bean) viewModel.setPhenomenonMiddleBean(bean)
} }
binding.phenomenonRightRecyclerview.adapter = rightAdapter binding.phenomenonRightRecyclerview.adapter = rightAdapter
//右侧菜单增加组标题 //右侧菜单增加组标题
binding.phenomenonRightRecyclerview.addItemDecoration( binding.phenomenonRightRecyclerview.addItemDecoration(
PhenomenonRightGroupHeaderDecoration( RightGroupHeaderDecoration(
requireContext() requireContext()
) )
) )
//右侧菜单查询数据监听 //右侧菜单查询数据监听
viewModel.liveDataPhenomenonRightList.observe(viewLifecycleOwner) { viewModel.liveDataRightTypeList.observe(viewLifecycleOwner) {
rightAdapter.refreshData(it) rightAdapter.refreshData(it)
} }
val middleAdapter = PhenomenonMiddleAdapter { _, title -> /**
* 监听中间栏的点击事件
*/
val middleAdapter = MiddleAdapter { _, title ->
rightLayoutManager.scrollToPositionWithOffset(rightAdapter.getGroupTopIndex(title), 0) rightLayoutManager.scrollToPositionWithOffset(rightAdapter.getGroupTopIndex(title), 0)
} }
/**
* 监控右侧滚动更新左侧
*/
binding.phenomenonRightRecyclerview.addOnScrollListener(object : binding.phenomenonRightRecyclerview.addOnScrollListener(object :
OnScrollListener() { OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
@ -98,7 +105,7 @@ class PhenomenonFragment :
binding.phenomenonMiddleRecyclerview.layoutManager = LinearLayoutManager(requireContext()) binding.phenomenonMiddleRecyclerview.layoutManager = LinearLayoutManager(requireContext())
binding.phenomenonMiddleRecyclerview.adapter = middleAdapter binding.phenomenonMiddleRecyclerview.adapter = middleAdapter
//中间侧菜单查询结果监听 //中间侧菜单查询结果监听
viewModel.liveDataProblemTypeList.observe(viewLifecycleOwner) { viewModel.liveDataMiddleTypeList.observe(viewLifecycleOwner) {
middleAdapter.refreshData(it) middleAdapter.refreshData(it)
} }
binding.phenomenonDrawer.setOnClickListener { binding.phenomenonDrawer.setOnClickListener {

View File

@ -1,6 +0,0 @@
package com.navinfo.omqs.ui.fragment.evaluationresult
/**
* 问题现象列表
*/
data class PhenomenonMiddleBean(val title: String, val text: String, var isSelect: Boolean = false)

View File

@ -35,22 +35,22 @@ class ProblemLinkFragment : BaseFragment() {
var rightLayoutManager = LinearLayoutManager(requireContext()) var rightLayoutManager = LinearLayoutManager(requireContext())
binding.linkRightRecyclerview.layoutManager = rightLayoutManager binding.linkRightRecyclerview.layoutManager = rightLayoutManager
val rightAdapter = PhenomenonRightGroupHeaderAdapter { _, bean -> val rightAdapter = RightGroupHeaderAdapter { _, bean ->
viewModel.setProblemLinkMiddleBean(bean) viewModel.setProblemLinkMiddleBean(bean)
} }
binding.linkRightRecyclerview.adapter = rightAdapter binding.linkRightRecyclerview.adapter = rightAdapter
//右侧菜单增加组标题 //右侧菜单增加组标题
binding.linkRightRecyclerview.addItemDecoration( binding.linkRightRecyclerview.addItemDecoration(
PhenomenonRightGroupHeaderDecoration( RightGroupHeaderDecoration(
requireContext() requireContext()
) )
) )
//右侧菜单查询数据监听 //右侧菜单查询数据监听
viewModel.liveDataPhenomenonRightList.observe(viewLifecycleOwner) { viewModel.liveDataRightTypeList.observe(viewLifecycleOwner) {
rightAdapter.refreshData(it) rightAdapter.refreshData(it)
} }
val middleAdapter = PhenomenonMiddleAdapter { _, title -> val middleAdapter = MiddleAdapter { _, title ->
rightLayoutManager.scrollToPositionWithOffset(rightAdapter.getGroupTopIndex(title), 0) rightLayoutManager.scrollToPositionWithOffset(rightAdapter.getGroupTopIndex(title), 0)
} }
@ -72,7 +72,7 @@ class ProblemLinkFragment : BaseFragment() {
binding.linkMiddleRecyclerview.layoutManager = LinearLayoutManager(requireContext()) binding.linkMiddleRecyclerview.layoutManager = LinearLayoutManager(requireContext())
binding.linkMiddleRecyclerview.adapter = middleAdapter binding.linkMiddleRecyclerview.adapter = middleAdapter
//中间侧菜单查询结果监听 //中间侧菜单查询结果监听
viewModel.liveDataProblemTypeList.observe(viewLifecycleOwner) { viewModel.liveDataMiddleTypeList.observe(viewLifecycleOwner) {
middleAdapter.refreshData(it) middleAdapter.refreshData(it)
} }
binding.linkDrawer.setOnClickListener { binding.linkDrawer.setOnClickListener {

View File

@ -0,0 +1,6 @@
package com.navinfo.omqs.ui.fragment.evaluationresult
/**
* 问题现象列表
*/
data class RightBean(val title: String, val text: String, var isSelect: Boolean = false)

View File

@ -7,8 +7,8 @@ import com.navinfo.omqs.databinding.TextItemSelectBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder import com.navinfo.omqs.ui.other.BaseViewHolder
class PhenomenonRightGroupHeaderAdapter(private var itemListener: ((Int, PhenomenonMiddleBean) -> Unit?)? = null) : class RightGroupHeaderAdapter(private var itemListener: ((Int, RightBean) -> Unit?)? = null) :
BaseRecyclerViewAdapter<PhenomenonMiddleBean>() { BaseRecyclerViewAdapter<RightBean>() {
private var groupTitleList = mutableListOf<String>() private var groupTitleList = mutableListOf<String>()
override fun getItemViewRes(position: Int): Int { override fun getItemViewRes(position: Int): Int {
return R.layout.text_item_select return R.layout.text_item_select
@ -85,7 +85,7 @@ class PhenomenonRightGroupHeaderAdapter(private var itemListener: ((Int, Phenome
return 0 return 0
} }
override fun refreshData(newData: List<PhenomenonMiddleBean>) { override fun refreshData(newData: List<RightBean>) {
super.refreshData(newData) super.refreshData(newData)
groupTitleList.clear() groupTitleList.clear()
for (item in newData) { for (item in newData) {

View File

@ -5,7 +5,6 @@ import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
import android.graphics.Rect import android.graphics.Rect
import android.util.Log
import android.view.View import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -15,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView.ItemDecoration
/** /**
* 自定义装饰器实现分组+吸顶效果 * 自定义装饰器实现分组+吸顶效果
*/ */
class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration() { class RightGroupHeaderDecoration(context: Context) : ItemDecoration() {
//头部的高 //头部的高
private val mItemHeaderHeight: Int private val mItemHeaderHeight: Int
private val mTextPaddingLeft: Int private val mTextPaddingLeft: Int
@ -48,8 +47,8 @@ class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration()
* @param state * @param state
*/ */
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (parent.adapter is PhenomenonRightGroupHeaderAdapter) { if (parent.adapter is RightGroupHeaderAdapter) {
val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter val adapter = parent.adapter as RightGroupHeaderAdapter
val count = parent.childCount //获取可见范围内Item的总数 val count = parent.childCount //获取可见范围内Item的总数
for (i in 0 until count) { for (i in 0 until count) {
val view: View = parent.getChildAt(i) val view: View = parent.getChildAt(i)
@ -99,8 +98,8 @@ class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration()
* @param state * @param state
*/ */
override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (parent.adapter is PhenomenonRightGroupHeaderAdapter) { if (parent.adapter is RightGroupHeaderAdapter) {
val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter val adapter = parent.adapter as RightGroupHeaderAdapter
val position = val position =
(parent.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition() (parent.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition()
parent.findViewHolderForAdapterPosition(position)?.let { parent.findViewHolderForAdapterPosition(position)?.let {
@ -169,8 +168,8 @@ class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration()
parent: RecyclerView, parent: RecyclerView,
state: RecyclerView.State state: RecyclerView.State
) { ) {
if (parent.adapter is PhenomenonRightGroupHeaderAdapter) { if (parent.adapter is RightGroupHeaderAdapter) {
val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter val adapter = parent.adapter as RightGroupHeaderAdapter
//获取当前view在整个列表中的位置 //获取当前view在整个列表中的位置
val position = parent.getChildLayoutPosition(view) val position = parent.getChildLayoutPosition(view)
//是不是改组的第一个 //是不是改组的第一个
@ -180,7 +179,7 @@ class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration()
if (adapter.isLastGroupTitle(position)) { if (adapter.isLastGroupTitle(position)) {
lastGroupView = view lastGroupView = view
} }
} else if (position == (parent.adapter as PhenomenonRightGroupHeaderAdapter).itemCount - 1) { } else if (position == (parent.adapter as RightGroupHeaderAdapter).itemCount - 1) {
//判断这条是不是最后一条 //判断这条是不是最后一条
//如果是最后一个,找到他所在组的第一个 //如果是最后一个,找到他所在组的第一个
lastGroupView?.let { lastGroupView?.let {

View File

@ -10,6 +10,8 @@ import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding
import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
import com.navinfo.omqs.tools.FileManager
import com.navinfo.omqs.tools.FileManager.Companion.FileDownloadStatus
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder import com.navinfo.omqs.ui.other.BaseViewHolder
import javax.inject.Inject import javax.inject.Inject
@ -31,11 +33,11 @@ class OfflineMapCityListAdapter(
if (it.tag != null) { if (it.tag != null) {
val cityBean = data[it.tag as Int] val cityBean = data[it.tag as Int]
when (cityBean.status) { when (cityBean.status) {
OfflineMapCityBean.NONE, OfflineMapCityBean.UPDATE, OfflineMapCityBean.PAUSE, OfflineMapCityBean.ERROR -> { FileDownloadStatus.NONE, FileDownloadStatus.UPDATE, FileDownloadStatus.PAUSE, FileDownloadStatus.ERROR -> {
Log.e("jingo", "开始下载 ${cityBean.status}") Log.e("jingo", "开始下载 ${cityBean.status}")
downloadManager.start(cityBean.id) downloadManager.start(cityBean.id)
} }
OfflineMapCityBean.LOADING, OfflineMapCityBean.WAITING -> { FileDownloadStatus.LOADING, FileDownloadStatus.WAITING -> {
Log.e("jingo", "暂停 ${cityBean.status}") Log.e("jingo", "暂停 ${cityBean.status}")
downloadManager.pause(cityBean.id) downloadManager.pause(cityBean.id)
} }
@ -88,37 +90,37 @@ class OfflineMapCityListAdapter(
binding.offlineMapProgress.progress = binding.offlineMapProgress.progress =
(cityBean.currentSize * 100 / cityBean.fileSize).toInt() (cityBean.currentSize * 100 / cityBean.fileSize).toInt()
when (cityBean.status) { when (cityBean.status) {
OfflineMapCityBean.NONE -> { FileDownloadStatus.NONE -> {
if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility = if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility =
View.INVISIBLE View.INVISIBLE
binding.offlineMapDownloadBtn.text = "下载" binding.offlineMapDownloadBtn.text = "下载"
} }
OfflineMapCityBean.WAITING -> { FileDownloadStatus.WAITING -> {
if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility = if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility =
View.VISIBLE View.VISIBLE
binding.offlineMapDownloadBtn.text = "等待中" binding.offlineMapDownloadBtn.text = "等待中"
} }
OfflineMapCityBean.LOADING -> { FileDownloadStatus.LOADING -> {
if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility = if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility =
View.VISIBLE View.VISIBLE
binding.offlineMapDownloadBtn.text = "暂停" binding.offlineMapDownloadBtn.text = "暂停"
} }
OfflineMapCityBean.PAUSE -> { FileDownloadStatus.PAUSE -> {
if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility = if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility =
View.VISIBLE View.VISIBLE
binding.offlineMapDownloadBtn.text = "继续" binding.offlineMapDownloadBtn.text = "继续"
} }
OfflineMapCityBean.ERROR -> { FileDownloadStatus.ERROR -> {
if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility = if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility =
View.VISIBLE View.VISIBLE
binding.offlineMapDownloadBtn.text = "重试" binding.offlineMapDownloadBtn.text = "重试"
} }
OfflineMapCityBean.DONE -> { FileDownloadStatus.DONE -> {
if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility = if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility =
View.INVISIBLE View.INVISIBLE
binding.offlineMapDownloadBtn.text = "已完成" binding.offlineMapDownloadBtn.text = "已完成"
} }
OfflineMapCityBean.UPDATE -> { FileDownloadStatus.UPDATE -> {
if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility = if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility =
View.INVISIBLE View.INVISIBLE
binding.offlineMapDownloadBtn.text = "更新" binding.offlineMapDownloadBtn.text = "更新"

View File

@ -8,11 +8,12 @@ import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import com.navinfo.omqs.databinding.FragmentOfflineMapBinding import com.navinfo.omqs.databinding.FragmentOfflineMapBinding
import com.navinfo.omqs.ui.fragment.BaseFragment
/** /**
* 离线地图总页面 * 离线地图总页面
*/ */
class OfflineMapFragment : Fragment() { class OfflineMapFragment : BaseFragment() {
private var _binding: FragmentOfflineMapBinding? = null private var _binding: FragmentOfflineMapBinding? = null

View File

@ -24,6 +24,7 @@ import com.navinfo.omqs.db.ImportOMDBHelper
import com.navinfo.omqs.hilt.ImportOMDBHiltFactory import com.navinfo.omqs.hilt.ImportOMDBHiltFactory
import com.navinfo.omqs.tools.CoroutineUtils import com.navinfo.omqs.tools.CoroutineUtils
import com.navinfo.omqs.ui.activity.BaseActivity import com.navinfo.omqs.ui.activity.BaseActivity
import com.navinfo.omqs.ui.fragment.BaseFragment
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import io.realm.Realm import io.realm.Realm
import io.realm.RealmDictionary import io.realm.RealmDictionary
@ -40,12 +41,13 @@ import javax.inject.Inject
* 个人中心 * 个人中心
*/ */
@AndroidEntryPoint @AndroidEntryPoint
class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { class PersonalCenterFragment : BaseFragment(), FSAFActivityCallbacks {
private var _binding: FragmentPersonalCenterBinding? = null private var _binding: FragmentPersonalCenterBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private val fileChooser by lazy { FileChooser(requireContext()) } private val fileChooser by lazy { FileChooser(requireContext()) }
private val viewModel by lazy { viewModels<PersonalCenterViewModel>().value } private val viewModel by lazy { viewModels<PersonalCenterViewModel>().value }
@Inject @Inject
lateinit var importOMDBHiltFactory: ImportOMDBHiltFactory lateinit var importOMDBHiltFactory: ImportOMDBHiltFactory
@Inject @Inject
@ -65,9 +67,9 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
binding.root.setNavigationItemSelectedListener { binding.root.setNavigationItemSelectedListener {
when (it.itemId) { when (it.itemId) {
R.id.personal_center_menu_offline_map -> R.id.personal_center_menu_offline_map ->
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment) findNavController().navigate(R.id.OfflineMapFragment)
R.id.personal_center_menu_obtain_data -> { // 生成数据根据sqlite文件生成对应的zip文件 R.id.personal_center_menu_obtain_data -> { // 生成数据根据sqlite文件生成对应的zip文件
fileChooser.openChooseFileDialog(object: FileChooserCallback() { fileChooser.openChooseFileDialog(object : FileChooserCallback() {
override fun onCancel(reason: String) { override fun onCancel(reason: String) {
} }
@ -75,31 +77,47 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
val file = UriUtils.uri2File(uri) val file = UriUtils.uri2File(uri)
// 开始导入数据 // 开始导入数据
// 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
val job = CoroutineUtils.launchWithLoading(requireContext(), loadingMessage = "生成数据...") { val job = CoroutineUtils.launchWithLoading(
val importOMDBHelper: ImportOMDBHelper = importOMDBHiltFactory.obtainImportOMDBHelper(requireContext(), file, File(file.parentFile, "config.json")) requireContext(),
loadingMessage = "生成数据..."
) {
val importOMDBHelper: ImportOMDBHelper =
importOMDBHiltFactory.obtainImportOMDBHelper(
requireContext(),
file,
File(file.parentFile, "config.json")
)
viewModel.obtainOMDBZipData(importOMDBHelper) viewModel.obtainOMDBZipData(importOMDBHelper)
} }
} }
}) })
} }
R.id.personal_center_menu_import_data -> { // 导入zip数据 R.id.personal_center_menu_import_data -> { // 导入zip数据
fileChooser.openChooseFileDialog(object: FileChooserCallback() { fileChooser.openChooseFileDialog(object : FileChooserCallback() {
override fun onCancel(reason: String) { override fun onCancel(reason: String) {
} }
override fun onResult(uri: Uri) { override fun onResult(uri: Uri) {
val file = UriUtils.uri2File(uri) val file = UriUtils.uri2File(uri)
// 开始导入数据 // 开始导入数据
CoroutineUtils.launchWithLoading(requireContext(), loadingMessage = "导入数据...") { CoroutineUtils.launchWithLoading(
val importOMDBHelper: ImportOMDBHelper = importOMDBHiltFactory.obtainImportOMDBHelper(requireContext(), file, File(file.parentFile, "config.json")) requireContext(),
loadingMessage = "导入数据..."
) {
val importOMDBHelper: ImportOMDBHelper =
importOMDBHiltFactory.obtainImportOMDBHelper(
requireContext(),
file,
File(file.parentFile, "config.json")
)
viewModel.importOMDBData(importOMDBHelper) viewModel.importOMDBData(importOMDBHelper)
} }
} }
}) })
} }
R.id.personal_center_menu_import_yuan_data->{ R.id.personal_center_menu_import_yuan_data -> {
// 用户选中导入数据,打开文件选择器,用户选择导入的数据文件目录 // 用户选中导入数据,打开文件选择器,用户选择导入的数据文件目录
fileChooser.openChooseFileDialog(object: FileChooserCallback() { fileChooser.openChooseFileDialog(object : FileChooserCallback() {
override fun onCancel(reason: String) { override fun onCancel(reason: String) {
} }
@ -114,6 +132,9 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
// 定位到指定位置 // 定位到指定位置
niMapController.mMapView.vtmMap.animator().animateTo(GeoPoint(28.608398, 115.67901)) niMapController.mMapView.vtmMap.animator().animateTo(GeoPoint(28.608398, 115.67901))
} }
R.id.personal_center_menu_task_list -> {
findNavController().navigate(R.id.TaskListFragment)
}
} }
true true
} }

View File

@ -185,16 +185,17 @@ class PersonalCenterViewModel @Inject constructor(
val list = mutableListOf<ScProblemTypeBean>() val list = mutableListOf<ScProblemTypeBean>()
for (i in 1 until rowCount) { for (i in 1 until rowCount) {
val row: Row = it.getRow(i) // 获取行 val row: Row = it.getRow(i) // 获取行
val cellCount: Int = row.physicalNumberOfCells // 获取列数 // val cellCount: Int = row.physicalNumberOfCells // 获取列数
if (cellCount == 3) { val bean = ScProblemTypeBean(
val bean = ScProblemTypeBean() elementType = row.getCell(0).stringCellValue,
bean.classType = row.getCell(0).stringCellValue elementCode = row.getCell(1).numericCellValue.toString(),
bean.problemType = row.getCell(1).stringCellValue classType = row.getCell(2).stringCellValue,
bean.phenomenon = row.getCell(2).stringCellValue problemType = row.getCell(3).stringCellValue,
phenomenon = row.getCell(4).stringCellValue
)
list.add(bean) list.add(bean)
Log.e("jingo", bean.toString()) Log.e("jingo", bean.toString())
} }
}
roomAppDatabase.getScProblemTypeDao().insertOrUpdateList(list) roomAppDatabase.getScProblemTypeDao().insertOrUpdateList(list)
} }
val sheet2 = workbook.getSheet("SC_ROOT_CAUSE_ANALYSIS") val sheet2 = workbook.getSheet("SC_ROOT_CAUSE_ANALYSIS")

View File

@ -0,0 +1,132 @@
package com.navinfo.omqs.ui.fragment.tasklist
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.TaskBean
import com.navinfo.omqs.databinding.AdapterTaskListBinding
import com.navinfo.omqs.http.taskdownload.TaskDownloadManager
import com.navinfo.omqs.tools.FileManager.Companion.FileDownloadStatus
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder
/**
* 离线地图城市列表 RecyclerView 适配器
*
* RecycleView ViewHolder 中监听 ViewModel LiveData然后此时传递的 lifecycleOwner 是对应的 Fragment由于 ViewHolder 的生命周期是比 Fragment 短的所以当 ViewHolder 销毁时由于 Fragment Lifecycle 还没有结束此时 ViewHolder 会发生内存泄露监听的 LiveData 没有解绑
* 这种场景下有两种解决办法
*使用 LiveData observeForever 然后在 ViewHolder 销毁前手动调用 removeObserver
*使用 LifecycleRegistry ViewHolder 分发生命周期(这里使用了这个)
*/
class TaskListAdapter(
private val downloadManager: TaskDownloadManager, private val context: Context
) : BaseRecyclerViewAdapter<TaskBean>() {
private val downloadBtnClick = View.OnClickListener() {
if (it.tag != null) {
val taskBean = data[it.tag as Int]
when (taskBean.status) {
FileDownloadStatus.NONE, FileDownloadStatus.UPDATE, FileDownloadStatus.PAUSE, FileDownloadStatus.ERROR -> {
Log.e("jingo", "开始下载 ${taskBean.status}")
downloadManager.start(taskBean.id)
}
FileDownloadStatus.LOADING, FileDownloadStatus.WAITING -> {
Log.e("jingo", "暂停 ${taskBean.status}")
downloadManager.pause(taskBean.id)
}
else -> {
Log.e("jingo", "暂停 ${taskBean.status}")
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
val viewBinding =
AdapterTaskListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BaseViewHolder(viewBinding)
}
override fun onViewRecycled(holder: BaseViewHolder) {
super.onViewRecycled(holder)
//页面滑动时会用holder重构页面但是对进度条的监听回调会一直返回扰乱UI所以当当前holder去重构的时候移除监听
downloadManager.removeObserver(holder.tag.toInt())
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val binding: AdapterTaskListBinding =
holder.viewBinding as AdapterTaskListBinding
val taskBean = data[position]
//tag 方便onclick里拿到数据
holder.tag = taskBean.id.toString()
changeViews(binding, taskBean)
downloadManager.addTask(taskBean)
downloadManager.observer(taskBean.id, holder, DownloadObserver(taskBean.id, binding))
binding.taskDownloadBtn.tag = position
binding.taskDownloadBtn.setOnClickListener(downloadBtnClick)
binding.taskName.text = taskBean.evaluationTaskName
// binding.offlineMapCitySize.text = cityBean.getFileSizeText()
}
inner class DownloadObserver(val id: Int, val binding: AdapterTaskListBinding) :
Observer<TaskBean> {
override fun onChanged(t: TaskBean?) {
if (id == t?.id)
changeViews(binding, t)
}
}
private fun changeViews(binding: AdapterTaskListBinding, cityBean: TaskBean) {
binding.taskProgress.progress =
(cityBean.currentSize * 100 / cityBean.fileSize).toInt()
when (cityBean.status) {
FileDownloadStatus.NONE -> {
if (binding.taskProgress.visibility == View.VISIBLE) binding.taskProgress.visibility =
View.INVISIBLE
binding.taskDownloadBtn.text = "下载"
}
FileDownloadStatus.WAITING -> {
if (binding.taskProgress.visibility != View.VISIBLE) binding.taskProgress.visibility =
View.VISIBLE
binding.taskDownloadBtn.text = "等待中"
}
FileDownloadStatus.LOADING -> {
if (binding.taskProgress.visibility != View.VISIBLE) binding.taskProgress.visibility =
View.VISIBLE
binding.taskDownloadBtn.text = "暂停"
}
FileDownloadStatus.PAUSE -> {
if (binding.taskProgress.visibility != View.VISIBLE) binding.taskProgress.visibility =
View.VISIBLE
binding.taskDownloadBtn.text = "继续"
}
FileDownloadStatus.ERROR -> {
if (binding.taskProgress.visibility != View.VISIBLE) binding.taskProgress.visibility =
View.VISIBLE
binding.taskDownloadBtn.text = "重试"
}
FileDownloadStatus.DONE -> {
if (binding.taskProgress.visibility == View.VISIBLE) binding.taskProgress.visibility =
View.INVISIBLE
binding.taskDownloadBtn.text = "已完成"
}
FileDownloadStatus.UPDATE -> {
if (binding.taskProgress.visibility == View.VISIBLE) binding.taskProgress.visibility =
View.INVISIBLE
binding.taskDownloadBtn.text = "更新"
}
}
}
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_offline_map_city
}
}

View File

@ -0,0 +1,55 @@
package com.navinfo.omqs.ui.fragment.tasklist
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.navinfo.omqs.databinding.FragmentTaskListBinding
import com.navinfo.omqs.http.taskdownload.TaskDownloadManager
import com.navinfo.omqs.ui.fragment.BaseFragment
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class TaskListFragment : BaseFragment(){
@Inject
lateinit var downloadManager: TaskDownloadManager
private var _binding: FragmentTaskListBinding? = null
private val viewModel by viewModels<TaskListViewModel>()
private val binding get() = _binding!!
private val adapter: TaskListAdapter by lazy {
TaskListAdapter(
downloadManager,
requireContext()
)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentTaskListBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val layoutManager = LinearLayoutManager(context)
//// 设置 RecyclerView 的固定大小,避免在滚动时重新计算视图大小和布局,提高性能
binding.taskRecyclerview.setHasFixedSize(true)
binding.taskRecyclerview.layoutManager = layoutManager
binding.taskRecyclerview.adapter = adapter
viewModel.liveDataTaskList.observe(viewLifecycleOwner) {
adapter.refreshData(it)
}
viewModel.getTaskList(requireContext())
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -0,0 +1,61 @@
package com.navinfo.omqs.ui.fragment.tasklist
import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.navinfo.omqs.bean.TaskBean
import com.navinfo.omqs.http.NetResult
import com.navinfo.omqs.http.NetworkService
import com.navinfo.omqs.tools.FileManager
import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.Realm
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel
class TaskListViewModel @Inject constructor(
private val networkService: NetworkService
) : ViewModel() {
val liveDataTaskList = MutableLiveData<List<TaskBean>>()
fun getTaskList(context: Context) {
viewModelScope.launch(Dispatchers.IO) {
val realm = Realm.getDefaultInstance()
Log.e("jingo","realm hashCOde ${realm.hashCode()}")
when (val result = networkService.getTaskList("02911")) {
is NetResult.Success -> {
if (result.data != null) {
realm.executeTransaction {
realm.copyToRealmOrUpdate(result.data.obj)
}
}
}
is NetResult.Error -> {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${result.exception.message}", Toast.LENGTH_SHORT)
.show()
}
}
is NetResult.Failure -> {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT)
.show()
}
}
is NetResult.Loading -> {}
else -> {}
}
val objects = realm.where(TaskBean::class.java).findAll()
liveDataTaskList.postValue(realm.copyFromRealm(objects))
// realm.close()
}
}
}

View File

@ -0,0 +1,53 @@
package com.navinfo.omqs.ui.widget
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.EditText
import androidx.appcompat.widget.AppCompatEditText
import com.navinfo.omqs.R
class MyEditeText @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = android.R.attr.editTextStyle //不这样写可能有些属性用不了
) : AppCompatEditText(context, attrs, defStyleAttr) {
init {
//Edittext通知父控件自己处理自己的滑动事件
setOnTouchListener { v, event ->
if (canVerticalScroll(this)) {
v.parent.requestDisallowInterceptTouchEvent(true)
if (event.action == MotionEvent.ACTION_UP) {
v.parent.requestDisallowInterceptTouchEvent(false)
}
}
false
}
}
/**
* EditText竖直方向是否可以滚动
*
* @param //editText需要判断的EditText
* @return true可以滚动 false不可以滚动
*/
private fun canVerticalScroll(contentEt: EditText): Boolean {
//滚动的距离
val scrollY = contentEt.scrollY
//控件内容的总高度
val scrollRange = contentEt.layout.height
//控件实际显示的高度
val scrollExtent =
contentEt.height - contentEt.compoundPaddingTop - contentEt.compoundPaddingBottom
//控件内容总高度与实际显示高度的差值
val scrollDifference = scrollRange - scrollExtent
if (scrollDifference == 0) {
return false
}
return (scrollY > 0) || (scrollY < scrollDifference - 1)
}
}

View File

@ -121,10 +121,9 @@
<fragment <fragment
android:id="@+id/main_activity_drawer_fragment" android:id="@+id/main_activity_drawer_fragment"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="wrap_content" android:layout_width="300dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="left" android:layout_gravity="left"
app:layout_constraintHorizontal_bias="0.3"
app:navGraph="@navigation/left_drawer_nav_graph" /> app:navGraph="@navigation/left_drawer_nav_graph" />
</androidx.drawerlayout.widget.DrawerLayout> </androidx.drawerlayout.widget.DrawerLayout>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/cv_bg_color"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp"
tools:context="com.navinfo.omqs.ui.fragment.tasklist.TaskListAdapter">
<TextView
android:id="@+id/task_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="省市名称"
android:textColor="@color/white"
android:textSize="@dimen/default_font_size" />
<TextView
android:id="@+id/task_size"
style="@style/map_size_font_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/task_name"
android:drawableLeft="@mipmap/point_blue"
android:layout_marginTop="5dp"
android:text="文件大小"
android:textSize="@dimen/card_title_font_3size" />
<TextView
android:id="@+id/task_download_btn"
style="@style/map_download_style_btn"
android:layout_width="60dp"
android:layout_alignTop="@id/task_name"
android:layout_alignBottom="@id/task_size"
android:layout_alignParentRight="true"
android:shadowColor="@android:color/transparent"
android:text="下载"
android:textColor="@color/btn_blue_solid"
android:textSize="@dimen/card_title_font_2size" />
<TextView
android:id="@+id/task_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginBottom="10dp"
android:layout_toLeftOf="@id/task_download_btn"
android:clickable="true"
android:focusable="false"
android:shadowColor="@android:color/transparent"
android:textColor="@color/white"
android:textSize="@dimen/card_title_font_2size" />
<com.navinfo.omqs.ui.widget.MyProgressBar
android:id="@+id/task_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="16dp"
android:layout_below="@id/task_download_btn"
android:progressDrawable="@drawable/progress_bg"
android:paddingTop="10dp"
android:visibility="invisible" />
</RelativeLayout>

View File

@ -1,7 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="fragment"
type="com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment"
/>
<variable
name="viewModel"
type="com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/white" android:background="@color/white"
@ -47,39 +59,64 @@
<TextView <TextView
android:id="@+id/evaluation_class_type" android:id="@+id/evaluation_class_type"
android:text="@{viewModel.liveDataQsRecordBean.classType}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:onClick="@{fragment.onClick}"
android:background="@drawable/fm_card_map_down_status_bg" /> android:background="@drawable/fm_card_map_down_status_bg" />
<TextView <TextView
android:id="@+id/evaluation_problem_type" android:id="@+id/evaluation_problem_type"
android:text="@{viewModel.liveDataQsRecordBean.problemType}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:onClick="@{fragment.onClick}"
android:background="@drawable/fm_card_map_down_status_bg" /> android:background="@drawable/fm_card_map_down_status_bg" />
<TextView <TextView
android:id="@+id/evaluation_phenomenon" android:id="@+id/evaluation_phenomenon"
android:text="@{viewModel.liveDataQsRecordBean.phenomenon}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:onClick="@{fragment.onClick}"
android:background="@drawable/fm_card_map_down_status_bg" /> android:background="@drawable/fm_card_map_down_status_bg" />
<TextView <TextView
android:id="@+id/evaluation_link" android:id="@+id/evaluation_link"
android:text="@{viewModel.liveDataQsRecordBean.problemLink}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:onClick="@{fragment.onClick}"
android:background="@drawable/fm_card_map_down_status_bg" /> android:background="@drawable/fm_card_map_down_status_bg" />
<TextView <TextView
android:id="@+id/evaluation_cause" android:id="@+id/evaluation_cause"
android:text="@{viewModel.liveDataQsRecordBean.cause}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:onClick="@{fragment.onClick}"
android:background="@drawable/fm_card_map_down_status_bg" /> android:background="@drawable/fm_card_map_down_status_bg" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="备注信息" />
<com.navinfo.omqs.ui.widget.MyEditeText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入备注信息"
android:gravity="start"
android:maxLines="3"
android:lines="3"
android:text="@={viewModel.liveDataQsRecordBean.description}"
android:inputType="textMultiLine"
android:background="@drawable/fm_card_map_down_status_bg"
/>
<!-- <com.google.android.material.tabs.TabLayout--> <!-- <com.google.android.material.tabs.TabLayout-->
<!-- android:id="@+id/evaluation_class_tab_layout"--> <!-- android:id="@+id/evaluation_class_tab_layout"-->
<!-- android:layout_width="match_parent"--> <!-- android:layout_width="match_parent"-->
@ -94,4 +131,5 @@
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -17,8 +17,10 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/offline_map_city_list_recyclerview" android:id="@+id/offline_map_city_list_recyclerview"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/offline_map_search" /> app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/offline_map_search"
app:layout_constraintVertical_bias="0.0"
tools:layout_editor_absoluteX="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,27 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".ui.fragment.tasklist.TaskListFragment">
<EditText
android:id="@+id/task_search"
style="@style/input_blue_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="搜索"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/task_recyclerview"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/task_search"
app:layout_constraintVertical_bias="0.0"
tools:layout_editor_absoluteX="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -32,6 +32,10 @@
android:checkableBehavior="single"> android:checkableBehavior="single">
<item android:title="小标题"> <item android:title="小标题">
<menu> <menu>
<item
android:id="@+id/personal_center_menu_task_list"
android:icon="@drawable/baseline_person_24"
android:title="任务列表" />
<item <item
android:id="@+id/personal_center_menu_offline_map3" android:id="@+id/personal_center_menu_offline_map3"
android:icon="@drawable/baseline_person_24" android:icon="@drawable/baseline_person_24"
@ -40,10 +44,7 @@
android:id="@+id/personal_center_menu_offline_map4" android:id="@+id/personal_center_menu_offline_map4"
android:icon="@drawable/baseline_person_24" android:icon="@drawable/baseline_person_24"
android:title="menu_gallery" /> android:title="menu_gallery" />
<item
android:id="@+id/personal_center_menu_offline_map5"
android:icon="@drawable/baseline_person_24"
android:title="menu_slideshow" />
<item <item
android:id="@+id/personal_center_menu_test" android:id="@+id/personal_center_menu_test"
android:icon="@drawable/baseline_person_24" android:icon="@drawable/baseline_person_24"

View File

@ -13,16 +13,20 @@
<action <action
android:id="@+id/action_FirstFragment_to_SecondFragment" android:id="@+id/action_FirstFragment_to_SecondFragment"
app:destination="@id/SecondFragment" /> app:destination="@id/OfflineMapFragment" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/SecondFragment" android:id="@+id/OfflineMapFragment"
android:name="com.navinfo.omqs.ui.fragment.offlinemap.OfflineMapFragment" android:name="com.navinfo.omqs.ui.fragment.offlinemap.OfflineMapFragment"
android:label="@string/second_fragment_label" android:label="离线地图"
tools:layout="@layout/fragment_offline_map"> tools:layout="@layout/fragment_offline_map">
<action </fragment>
android:id="@+id/action_SecondFragment_to_FirstFragment" <fragment
app:destination="@id/PersonalCenterFragment" /> android:id="@+id/TaskListFragment"
android:name="com.navinfo.omqs.ui.fragment.tasklist.TaskListFragment"
android:label="任务列表"
tools:layout="@layout/fragment_task_list">
</fragment> </fragment>
</navigation> </navigation>

View File

@ -15,5 +15,10 @@
android:id="@+id/EvaluationResultFragment" android:id="@+id/EvaluationResultFragment"
android:name="com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment" android:name="com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment"
android:label="评测页面" android:label="评测页面"
tools:layout="@layout/fragment_evaluation_result"></fragment> tools:layout="@layout/fragment_evaluation_result">
<argument
android:name="QsId"
app:argType="string"
app:nullable="true" />
</fragment>
</navigation> </navigation>

View File

@ -105,7 +105,7 @@ dependencies {
implementation "com.badlogicgames.gdx:gdx:1.11.0" implementation "com.badlogicgames.gdx:gdx:1.11.0"
implementation "com.badlogicgames.gdx:gdx-backend-android:1.11.0" implementation "com.badlogicgames.gdx:gdx-backend-android:1.11.0"
implementation "com.caverock:androidsvg:1.4" implementation "com.caverock:androidsvg:1.4"
implementation "org.mapsforge:vtm-jts:$vtmVersion" api "org.mapsforge:vtm-jts:$vtmVersion"
api 'org.locationtech.jts:jts-core:1.19.0' api 'org.locationtech.jts:jts-core:1.19.0'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.11' implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.11'
implementation 'com.squareup.okio:okio:3.3.0' implementation 'com.squareup.okio:okio:3.3.0'

View File

@ -4,6 +4,7 @@ import com.navinfo.collect.library.utils.GeometryToolsKt
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.RealmSet import io.realm.RealmSet
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import io.realm.annotations.RealmClass
/** /**
@ -36,7 +37,7 @@ open class QsRecordBean @JvmOverloads constructor(
/** /**
* 问题类型 * 问题类型
*/ */
var type: String = "", var problemType: String = "",
/** /**
* 问题现象 * 问题现象
@ -88,6 +89,27 @@ open class QsRecordBean @JvmOverloads constructor(
) : RealmObject() { ) : RealmObject() {
fun copy(): QsRecordBean {
val qs = QsRecordBean(
id = id,
elementId = elementId,
linkId = linkId,
classType = classType,
problemType = problemType,
phenomenon = phenomenon,
description = description,
problemLink = problemLink,
cause = cause,
checkUserId = checkUserId,
checkTime = checkTime,
confirmUserId = confirmUserId,
t_lifecycle = t_lifecycle,
t_status = t_status,
)
qs.geometry = geometry
return qs
}
private val tileX = RealmSet<Int>() // x方向的tile编码 private val tileX = RealmSet<Int>() // x方向的tile编码
private val tileY = RealmSet<Int>() // y方向的tile编码 private val tileY = RealmSet<Int>() // y方向的tile编码

View File

@ -10,15 +10,7 @@ import org.oscim.layers.marker.MarkerItem
*10:51 *10:51
*说明 *说明
*/ */
class ClusterMarkerItem(uid: Any?, title: String?, description: String?, geoPoint: GeoPoint?) : class ClusterMarkerItem(uid: Any, title: String?, description: String?, geoPoint: GeoPoint) :
MarkerItem(uid, title, description, geoPoint) { MarkerItem(uid, title, description, geoPoint) {
var clusterList: List<Int> = ArrayList() var clusterList: List<Int> = ArrayList()
constructor(title: String?, description: String?, geoPoint: GeoPoint?) : this(
null,
title,
description,
geoPoint
) {
}
} }

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.util.Log
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -42,6 +43,7 @@ import org.oscim.layers.tile.vector.VectorTileLayer
import org.oscim.layers.tile.vector.labeling.LabelLayer import org.oscim.layers.tile.vector.labeling.LabelLayer
import org.oscim.layers.tile.vector.labeling.LabelTileLoaderHook import org.oscim.layers.tile.vector.labeling.LabelTileLoaderHook
import org.oscim.map.Map import org.oscim.map.Map
import org.oscim.map.Map.UpdateListener
import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory
import org.oscim.tiling.source.mapfile.MapFileTileSource import org.oscim.tiling.source.mapfile.MapFileTileSource
import java.io.File import java.io.File
@ -69,7 +71,8 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
private lateinit var canvas: org.oscim.backend.canvas.Canvas private lateinit var canvas: org.oscim.backend.canvas.Canvas
private lateinit var itemizedLayer: MyItemizedLayer private lateinit var itemizedLayer: MyItemizedLayer
private lateinit var markerRendererFactory: MarkerRendererFactory private lateinit var markerRendererFactory: MarkerRendererFactory
private val markerItemsNames = mutableListOf<MarkerInterface>() private var resId = R.mipmap.map_icon_point_add
private var itemListener: OnQsRecordItemClickListener? = null
/** /**
* 轨迹渲染图层 * 轨迹渲染图层
@ -97,14 +100,6 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
init { init {
initMap() initMap()
mMapView.vtmMap.events.bind(Map.UpdateListener { e, mapPosition ->
val isOmdbZoom = mapPosition.zoomLevel>=Constant.OMDB_MIN_ZOOM
baseGroupLayer?.layers?.forEach {
it.isEnabled = !isOmdbZoom
}
omdbVectorTileLayer.isEnabled = isOmdbZoom
omdbLabelLayer.isEnabled = isOmdbZoom
})
} }
/** /**
@ -113,6 +108,8 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
private fun initMap() { private fun initMap() {
loadBaseMap() loadBaseMap()
//初始化之间数据图层
initQsRecordDataLayer()
initOMDBVectorTileLayer() initOMDBVectorTileLayer()
@ -137,8 +134,23 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
//初始化之间数据图层 //初始化之间数据图层
initQsRecordDataLayer() initQsRecordDataLayer()
mMapView.vtmMap.updateMap()
mMapView.updateMap()
// initMapLifeSource()
// 设置矢量图层均在12级以上才显示
mMapView.vtmMap.events.bind(UpdateListener { e, mapPosition ->
if (e == org.oscim.map.Map.SCALE_EVENT) {
itemizedLayer.isEnabled = mapPosition.getZoomLevel() >= 12
// 测评数据图层在指定Zoom后开始显示
val isOmdbZoom = mapPosition.zoomLevel>=Constant.OMDB_MIN_ZOOM
baseGroupLayer?.layers?.forEach {
it.isEnabled = !isOmdbZoom
}
omdbVectorTileLayer.isEnabled = isOmdbZoom
omdbLabelLayer.isEnabled = isOmdbZoom
}
})
} }
private fun initOMDBVectorTileLayer() { private fun initOMDBVectorTileLayer() {
@ -210,8 +222,48 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
for (layer in it.layers) { for (layer in it.layers) {
addLayer(layer, NIMapView.LAYER_GROUPS.BASE) addLayer(layer, NIMapView.LAYER_GROUPS.BASE)
} }
}
}
mMapView.switchTileVectorLayerTheme(NIMapView.MAP_THEME.DEFAULT)
mMapView.updateMap() mMapView.updateMap()
} }
fun setOnQsRecordItemClickListener(listener: OnQsRecordItemClickListener?) {
itemListener = listener
}
/**
* 增加或更新marker
*/
suspend fun addOrUpdateQsRecordMark(data: QsRecordBean) {
for (item in itemizedLayer.itemList) {
if (item is MarkerItem) {
if (item.title == data.id) {
itemizedLayer.itemList.remove(item)
break
}
}
}
createMarkerItem(data)
withContext(Dispatchers.Main) {
mMapView.updateMap(true)
}
}
/**
* 删除marker
*/
suspend fun removeQsRecordMark(data: QsRecordBean) {
for (item in itemizedLayer.itemList) {
if (item is MarkerItem) {
if (item.title == data.id) {
itemizedLayer.itemList.remove(item)
itemizedLayer.populate()
return
}
}
} }
} }
@ -219,6 +271,7 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
* 初始话质检数据图层 * 初始话质检数据图层
*/ */
private fun initQsRecordDataLayer() { private fun initQsRecordDataLayer() {
canvas = CanvasAdapter.newCanvas() canvas = CanvasAdapter.newCanvas()
paint = CanvasAdapter.newPaint() paint = CanvasAdapter.newPaint()
paint.setTypeface(Paint.FontFamily.DEFAULT, Paint.FontStyle.NORMAL) paint.setTypeface(Paint.FontFamily.DEFAULT, Paint.FontStyle.NORMAL)
@ -248,17 +301,6 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
} }
} }
var resId = R.mipmap.map_icon_point_add
mContext.lifecycleScope.launch(Dispatchers.IO) {
var list = mutableListOf<QsRecordBean>()
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
val objects = realm.where<QsRecordBean>().findAll()
list = realm.copyFromRealm(objects)
}
realm.close()
itemizedLayer = itemizedLayer =
MyItemizedLayer( MyItemizedLayer(
mMapView.vtmMap, mMapView.vtmMap,
@ -266,23 +308,52 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
markerRendererFactory, markerRendererFactory,
object : MyItemizedLayer.OnItemGestureListener { object : MyItemizedLayer.OnItemGestureListener {
override fun onItemSingleTapUp( override fun onItemSingleTapUp(
layer: MyItemizedLayer?, list: MutableList<Int>,
list: MutableList<Int>?,
nearest: Int nearest: Int
): Boolean { ): Boolean {
itemListener?.let {
val idList = mutableListOf<String>()
if (list.size == 0) {
} else {
for (i in list) {
val markerInterface: MarkerInterface =
itemizedLayer.itemList[i]
if (markerInterface is MarkerItem) {
idList.add(markerInterface.title)
}
}
it.onQsRecordList(idList.distinct().toMutableList())
}
}
return true return true
} }
override fun onItemLongPress( override fun onItemLongPress(
layer: MyItemizedLayer?,
list: MutableList<Int>?, list: MutableList<Int>?,
nearest: Int nearest: Int
): Boolean { ): Boolean {
return true return true
} }
}) })
addLayer(itemizedLayer, NIMapView.LAYER_GROUPS.OPERATE)
mContext.lifecycleScope.launch(Dispatchers.IO) {
var list = mutableListOf<QsRecordBean>()
val realm = Realm.getDefaultInstance()
Log.e("jingo","realm hashCOde ${realm.hashCode()}")
realm.executeTransaction {
val objects = realm.where<QsRecordBean>().findAll()
list = realm.copyFromRealm(objects)
}
// realm.close()
for (item in list) { for (item in list) {
createMarkerItem(item)
}
}
}
private suspend fun createMarkerItem(item: QsRecordBean) {
val bitmap: Bitmap = createTextMarkerBitmap(mContext, item.description, resId) val bitmap: Bitmap = createTextMarkerBitmap(mContext, item.description, resId)
if (item.t_lifecycle != 2) { if (item.t_lifecycle != 2) {
val geometry: Geometry? = GeometryTools.createGeometry(item.geometry) val geometry: Geometry? = GeometryTools.createGeometry(item.geometry)
@ -336,21 +407,16 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
// geoPoint // geoPoint
// ) // )
// } // }
markerItemsNames.add(geoMarkerItem)
val markerSymbol = val markerSymbol =
MarkerSymbol(bitmap, MarkerSymbol.HotspotPlace.CENTER) MarkerSymbol(bitmap, MarkerSymbol.HotspotPlace.CENTER)
geoMarkerItem.marker = markerSymbol geoMarkerItem.marker = markerSymbol
itemizedLayer.itemList.add(geoMarkerItem)
} }
} }
} }
itemizedLayer.populate()
} }
itemizedLayer.addItems(markerItemsNames)
addLayer(itemizedLayer, NIMapView.LAYER_GROUPS.OPERATE)
withContext(Dispatchers.Main) {
itemizedLayer.map().updateMap(true)
}
}
}
/** /**
* 文字和图片拼装文字换行 * 文字和图片拼装文字换行
@ -573,8 +639,12 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr
vectorNiLocationTileLayer.isEnabled = false vectorNiLocationTileLayer.isEnabled = false
labelNiLocationLayer.isEnabled = false labelNiLocationLayer.isEnabled = false
} }
} }
interface OnQsRecordItemClickListener {
fun onQsRecordList(list: MutableList<String>)
}
/** /**
* 基础 * 基础

View File

@ -50,7 +50,7 @@ public class MyItemizedLayer extends ItemizedLayer {
public boolean run(List list1, int nearest) { public boolean run(List list1, int nearest) {
if (mOnItemGestureListener != null) { if (mOnItemGestureListener != null) {
return mOnItemGestureListener.onItemSingleTapUp(MyItemizedLayer.this, list1, nearest); return mOnItemGestureListener.onItemSingleTapUp(list1, nearest);
} }
return false; return false;
} }
@ -62,7 +62,7 @@ public class MyItemizedLayer extends ItemizedLayer {
public boolean run(List list1, int nearest) { public boolean run(List list1, int nearest) {
if (mOnItemGestureListener != null) { if (mOnItemGestureListener != null) {
return mOnItemGestureListener.onItemLongPress(MyItemizedLayer.this, list1, nearest); return mOnItemGestureListener.onItemLongPress(list1, nearest);
} }
return false; return false;
} }
@ -155,8 +155,8 @@ public class MyItemizedLayer extends ItemizedLayer {
} }
public interface OnItemGestureListener { public interface OnItemGestureListener {
boolean onItemSingleTapUp(MyItemizedLayer layer, List<Integer> list, int nearest); boolean onItemSingleTapUp(List<Integer> list, int nearest);
boolean onItemLongPress(MyItemizedLayer layer, List<Integer> list, int nearest); boolean onItemLongPress(List<Integer> list, int nearest);
} }
} }