From ab5cb7a0784ea8bb9eeb380c9c7a0387101b3f26 Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Fri, 21 Apr 2023 14:10:05 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E6=8D=95=E6=8D=89=E6=95=B0=E6=8D=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 11 +- .../java/com/navinfo/omqs/OMQSApplication.kt | 2 +- .../navinfo/omqs/bean/ScProblemTypeBean.kt | 19 +- .../omqs/ui/activity/PermissionsActivity.kt | 2 +- .../omqs/ui/activity/map/MainActivity.kt | 18 +- .../omqs/ui/activity/map/MainViewModel.kt | 12 ++ .../EvaluationResultFragment.kt | 68 +++---- .../EvaluationResultViewModel.kt | 176 ++++++++--------- ...henomenonLeftAdapter.kt => LeftAdapter.kt} | 2 +- ...menonMiddleAdapter.kt => MiddleAdapter.kt} | 2 +- .../evaluationresult/PhenomenonFragment.kt | 31 +-- .../evaluationresult/PhenomenonMiddleBean.kt | 6 - .../evaluationresult/ProblemLinkFragment.kt | 10 +- .../ui/fragment/evaluationresult/RightBean.kt | 6 + ...rAdapter.kt => RightGroupHeaderAdapter.kt} | 6 +- ...ation.kt => RightGroupHeaderDecoration.kt} | 17 +- .../personalcenter/PersonalCenterViewModel.kt | 19 +- app/src/main/res/layout/activity_main.xml | 3 +- .../res/layout/fragment_evaluation_result.xml | 185 ++++++++++-------- .../navigation/right_fragment_nav_graph.xml | 7 +- .../library/data/entity/QsRecordBean.kt | 2 +- .../library/map/cluster/ClusterMarkerItem.kt | 10 +- .../map/handler/LayerManagerHandler.kt | 178 +++++++++++------ .../library/map/layers/MyItemizedLayer.java | 8 +- 24 files changed, 448 insertions(+), 352 deletions(-) rename app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/{PhenomenonLeftAdapter.kt => LeftAdapter.kt} (95%) rename app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/{PhenomenonMiddleAdapter.kt => MiddleAdapter.kt} (95%) delete mode 100644 app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonMiddleBean.kt create mode 100644 app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightBean.kt rename app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/{PhenomenonRightGroupHeaderAdapter.kt => RightGroupHeaderAdapter.kt} (92%) rename app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/{PhenomenonRightGroupHeaderDecoration.kt => RightGroupHeaderDecoration.kt} (91%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f32f5edd..865ca118 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,6 +14,7 @@ + @@ -34,10 +35,10 @@ android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:supportsRtl="true" android:largeHeap="true" - android:theme="@style/Theme.OMQualityInspection" - android:requestLegacyExternalStorage="true"> + android:requestLegacyExternalStorage="true" + android:supportsRtl="true" + android:theme="@style/Theme.OMQualityInspection"> - + \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt index 556829bb..fd8928cd 100644 --- a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt +++ b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt @@ -18,7 +18,7 @@ class OMQSApplication : Application() { FileManager.initRootDir(this) Realm.init(this) val password = "encryp".encodeToByteArray().copyInto(ByteArray(64)) - // 70617373776f72640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Log.d("OMQSApplication", "密码是: ${byteArrayToHexString(password)}") val config = RealmConfiguration.Builder() .directory(File(Constant.DATA_PATH)) diff --git a/app/src/main/java/com/navinfo/omqs/bean/ScProblemTypeBean.kt b/app/src/main/java/com/navinfo/omqs/bean/ScProblemTypeBean.kt index 4ce71de7..0bfcecea 100644 --- a/app/src/main/java/com/navinfo/omqs/bean/ScProblemTypeBean.kt +++ b/app/src/main/java/com/navinfo/omqs/bean/ScProblemTypeBean.kt @@ -11,20 +11,33 @@ import kotlinx.parcelize.Parcelize data class ScProblemTypeBean( @PrimaryKey(autoGenerate = true) var id: Long = 0, + /** + * elementType + * 要素类型 + */ + @ColumnInfo("ELEMENT_TYPE") + val elementType: String = "", + /** + * 要素代码 + */ + @ColumnInfo("ELEMENT_CODE") + val elementCode: String = "", /** * 问题分类 */ @ColumnInfo("CLASS_TYPE") - var classType: String = "", + val classType: String = "", + /** * 问题类型 */ @ColumnInfo("TYPE") - var problemType: String = "", + val problemType: String = "", + /** * 问题现象 */ @ColumnInfo("PHENOMENON") - var phenomenon: String = "" + val phenomenon: String = "" ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt index fa584a95..5e6ba595 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt @@ -30,7 +30,7 @@ open class PermissionsActivity : BaseActivity() { permissionList.add(Permission.ACCESS_FINE_LOCATION) permissionList.add(Permission.ACCESS_COARSE_LOCATION) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - permissionList.add(Permission.ACCESS_BACKGROUND_LOCATION) +// permissionList.add(Permission.ACCESS_BACKGROUND_LOCATION) } XXPermissions.with(this) // 申请单个权限 diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt index b28d7c4f..b6700885 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt @@ -52,8 +52,16 @@ class MainActivity : BaseActivity() { binding.mainActivity = this //给xml传递viewModel对象 binding.viewModel = viewModel -// lifecycle.addObserver(viewModel) - lifecycleScope + + viewModel.liveDataQsRecordIdList.observe(this) { + if (it.size == 1) { + val bundle = Bundle() + bundle.putString("QsId", it[0]) + val naviController = findNavController(R.id.main_activity_right_fragment) + naviController.navigate(R.id.EvaluationResultFragment, bundle) + } + } + } override fun onStart() { @@ -94,7 +102,7 @@ class MainActivity : BaseActivity() { naviController.navigate(R.id.EvaluationResultFragment) } - override fun onBackPressed() { - super.onBackPressed() - } +// override fun onBackPressed() { +// super.onBackPressed() +// } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt index c052a0f7..ab00003e 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt @@ -1,8 +1,10 @@ package com.navinfo.omqs.ui.activity.map import android.util.Log +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.navinfo.collect.library.map.NIMapController +import com.navinfo.collect.library.map.handler.OnQsRecordItemClickListener import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.scopes.ActivityRetainedScoped import javax.inject.Inject @@ -16,6 +18,16 @@ class MainViewModel @Inject constructor( private val mapController: NIMapController, ) : ViewModel() { + val liveDataQsRecordIdList = MutableLiveData>() + + init { + mapController.layerManagerHandler.setOnQsRecordItemClickListener(object : + OnQsRecordItemClickListener { + override fun onQsRecordList(list: MutableList) { + liveDataQsRecordIdList.value = list + } + }) + } /** * 点击我的位置,回到我的位置 diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultFragment.kt index 4e9013db..eeac9c80 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.databinding.DataBindingUtil import androidx.navigation.NavOptions import androidx.navigation.findNavController import com.navinfo.omqs.R @@ -14,30 +15,26 @@ import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class EvaluationResultFragment : BaseFragment(), View.OnClickListener { - private var _binding: FragmentEvaluationResultBinding? = null - private val binding get() = _binding!! + private lateinit var binding: FragmentEvaluationResultBinding private val viewModel by shareViewModels("QsRecode") override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): 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 } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - liveDataObserve() - - /** - * 点击监听 - */ - binding.evaluationClassType.setOnClickListener(this) - binding.evaluationProblemType.setOnClickListener(this) - binding.evaluationPhenomenon.setOnClickListener(this) - binding.evaluationLink.setOnClickListener(this) - binding.evaluationCause.setOnClickListener(this) - + //监听是否退出当前页面 + viewModel.liveDataFinish.observe(viewLifecycleOwner) { + onBackPressed() + } //返回按钮点击 binding.evaluationBar.setNavigationOnClickListener { 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.loadMetadata() + } + } else { + viewModel.loadMetadata() + } + // //监听大分类数据变化 // viewModel.liveDataClassTypeList.observe(viewLifecycleOwner) { // 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() { activity?.apply { findNavController(R.id.main_activity_middle_fragment).navigateUp() } super.onDestroyView() - _binding = null } /** diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt index a233fb64..1e162cb1 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt @@ -10,6 +10,7 @@ import com.navinfo.collect.library.data.entity.QsRecordBean import com.navinfo.omqs.db.RoomAppDatabase import dagger.hilt.android.lifecycle.HiltViewModel import io.realm.Realm +import io.realm.kotlin.where import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.* @@ -28,63 +29,32 @@ class EvaluationResultViewModel @Inject constructor( val liveDataFinish = MutableLiveData() /** - * 问题分类 liveData,给[PhenomenonLeftAdapter]展示的数据 + * 问题分类 liveData,给[LeftAdapter]展示的数据 */ - val liveDataClassTypeList = MutableLiveData>() + val liveDataLeftTypeList = MutableLiveData>() /** - * 问题类型 liveData 给[PhenomenonMiddleAdapter]展示的数据 + * 问题类型 liveData 给[MiddleAdapter]展示的数据 */ - val liveDataProblemTypeList = MutableLiveData>() + val liveDataMiddleTypeList = MutableLiveData>() /** - * 问题现象 liveData 给[PhenomenonRightGroupHeaderAdapter]展示的数据 + * 问题现象 liveData 给[RightGroupHeaderAdapter]展示的数据 */ - val liveDataPhenomenonRightList = MutableLiveData>() + val liveDataRightTypeList = MutableLiveData>() - /** - * 当前选择问题分类 给[EvaluationResultFragment]中 【问题分类】展示数据 - */ - var liveDataCurrentClassType = MutableLiveData() - - /** - * 当前选择的问题类型 给[EvaluationResultFragment]中 【问题类型】展示数据 - */ - var liveDataCurrentProblemType = MutableLiveData() - - /** - * 当前选择的问题现象 给[EvaluationResultFragment]中 【问题现象】展示数据 - */ - var liveDataCurrentPhenomenon = MutableLiveData() - - - /** - * 当前选择的问题环节 给[EvaluationResultFragment]中 【问题环节】展示数据 - */ - var liveDataCurrentProblemLink = MutableLiveData() - - /** - * 当前选择的问初步原因 给[EvaluationResultFragment]中 【初步原因】展示数据 - */ - var liveDataCurrentCause = MutableLiveData() - - var currentGeoPoint: GeoPoint? = null - + var liveDataQsRecordBean = MutableLiveData() init { + liveDataQsRecordBean.value = QsRecordBean(id = UUID.randomUUID().toString(), classType = "89193") Log.e("jingo", "EvaluationResultViewModel 创建了 ${hashCode()}") mapController.markerHandle.apply { setOnMapClickListener { - currentGeoPoint = it + liveDataQsRecordBean.value!!.geometry = it.toGeometry() addMarker(it, markerTitle) } } - val geoPoint = mapController.locationLayerHandler.getCurrentGeoPoint() - geoPoint?.let { - currentGeoPoint = it - mapController.markerHandle.addMarker(geoPoint, markerTitle) - } } @@ -104,22 +74,31 @@ class EvaluationResultViewModel @Inject constructor( getClassTypeList() getProblemLinkList() } + val geoPoint = mapController.locationLayerHandler.getCurrentGeoPoint() + geoPoint?.let { + liveDataQsRecordBean.value!!.geometry = it.toGeometry() + mapController.markerHandle.addMarker(geoPoint, markerTitle) + } } /** * //获取问题分类列表 */ fun getClassTypeList() { + viewModelScope.launch(Dispatchers.IO) { val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList() list?.let { - //通知页面更新 - liveDataClassTypeList.postValue(it) - //如果右侧栏没数据,给个默认值 - if (liveDataCurrentClassType.value == null) { - liveDataCurrentClassType.postValue(it[0]) + if (list.isNotEmpty()) { + //通知页面更新 + liveDataLeftTypeList.postValue(it) + val classType = it[0] + //如果右侧栏没数据,给个默认值 + if (liveDataQsRecordBean.value!!.classType.isEmpty()) { + liveDataQsRecordBean.value!!.classType = classType + } + getProblemList(classType) } - getProblemList(it[0]) } } @@ -133,27 +112,26 @@ class EvaluationResultViewModel @Inject constructor( val list = roomAppDatabase.getScRootCauseAnalysisDao().findAllData() list?.let { tl -> if (tl.isNotEmpty()) { - val typeTitleList = mutableListOf() - val phenomenonRightList = mutableListOf() + val middleList = mutableListOf() + val rightList = mutableListOf() for (item in tl) { - if (!typeTitleList.contains(item.problemLink)) { - typeTitleList.add(item.problemLink) + if (!middleList.contains(item.problemLink)) { + middleList.add(item.problemLink) } - phenomenonRightList.add( - PhenomenonMiddleBean( + rightList.add( + RightBean( title = item.problemLink, text = item.problemCause, isSelect = false ) ) } - - if (liveDataCurrentProblemLink.value == null) { - liveDataCurrentProblemLink.postValue(phenomenonRightList[0].text) + if (liveDataQsRecordBean.value!!.problemLink.isEmpty()) { + liveDataQsRecordBean.value!!.problemLink = middleList[0] } - if (liveDataCurrentCause.value == null) { - liveDataCurrentCause.postValue(typeTitleList[0]) + if (liveDataQsRecordBean.value!!.cause.isEmpty()) { + liveDataQsRecordBean.value!!.cause = rightList[0].text } - liveDataProblemTypeList.postValue(typeTitleList) - liveDataPhenomenonRightList.postValue(phenomenonRightList) + liveDataMiddleTypeList.postValue(middleList) + liveDataRightTypeList.postValue(rightList) } } } @@ -167,76 +145,90 @@ class EvaluationResultViewModel @Inject constructor( typeList?.let { tl -> if (tl.isNotEmpty()) { val typeTitleList = mutableListOf() - val phenomenonRightList = mutableListOf() + val phenomenonRightList = mutableListOf() for (item in tl) { if (!typeTitleList.contains(item.problemType)) { typeTitleList.add(item.problemType) } phenomenonRightList.add( - PhenomenonMiddleBean( + RightBean( title = item.problemType, text = item.phenomenon, isSelect = false ) ) } - if (liveDataCurrentPhenomenon.value == null) { - liveDataCurrentPhenomenon.postValue(phenomenonRightList[0].text) - } - if (liveDataCurrentProblemType.value == null) { - liveDataCurrentProblemType.postValue(typeTitleList[0]) - } - liveDataProblemTypeList.postValue(typeTitleList) - liveDataPhenomenonRightList.postValue(phenomenonRightList) + liveDataMiddleTypeList.postValue(typeTitleList) + liveDataRightTypeList.postValue(phenomenonRightList) } } } /** - * 查询问题类型 + * 查询问题类型列表 */ fun getProblemTypeList(classType: String) { viewModelScope.launch(Dispatchers.IO) { - liveDataCurrentClassType.postValue(classType) getProblemList(classType) } } - fun setPhenomenonMiddleBean(bean: PhenomenonMiddleBean) { - if (liveDataCurrentPhenomenon.value != bean.text) liveDataCurrentPhenomenon.value = - bean.text - if (liveDataCurrentProblemType.value != bean.title) liveDataCurrentProblemType.value = - bean.title - + /** + * 监听右侧栏的点击事件,修改数据 + */ + fun setPhenomenonMiddleBean(adapterBean: RightBean) { + liveDataQsRecordBean.value!!.phenomenon = adapterBean.text + liveDataQsRecordBean.value!!.problemType = adapterBean.title } - fun setProblemLinkMiddleBean(bean: PhenomenonMiddleBean) { - if (liveDataCurrentProblemLink.value != bean.text) liveDataCurrentProblemLink.value = - bean.text - if (liveDataCurrentCause.value != bean.title) liveDataCurrentCause.value = bean.title + fun setProblemLinkMiddleBean(adapterBean: RightBean) { + liveDataQsRecordBean.value!!.cause = adapterBean.text + liveDataQsRecordBean.value!!.problemLink = adapterBean.title } fun saveData() { 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() realm.executeTransaction { - it.copyToRealmOrUpdate(qsRecord) + it.copyToRealmOrUpdate(liveDataQsRecordBean.value) } realm.close() - mapController.mMapView.updateMap() + mapController.layerManagerHandler.addOrUpdateQsRecordMark(liveDataQsRecordBean.value!!) liveDataFinish.postValue(true) } } fun deleteData() { +// 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() +// realm.executeTransaction { +// it.copyToRealmOrUpdate(qsRecord) +// } +// realm.close() +// mapController.layerManagerHandler.addOrUpdateQsRecordMark(qsRecord) +// liveDataFinish.postValue(true) +// } + } + /** + * 根据数据id,查询数据 + */ + fun loadData(id: String) { + viewModelScope.launch(Dispatchers.IO) { + val realm = Realm.getDefaultInstance() + val objects = realm.where().equalTo("id", id).findFirst() + + if (objects != null) { + liveDataQsRecordBean.postValue(realm.copyFromRealm(objects)) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonLeftAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/LeftAdapter.kt similarity index 95% rename from app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonLeftAdapter.kt rename to app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/LeftAdapter.kt index 572a3c5f..0ff2468b 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonLeftAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/LeftAdapter.kt @@ -7,7 +7,7 @@ import com.navinfo.omqs.databinding.TextItemSelectBinding import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter 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() { private var selectTitle = "" diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonMiddleAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/MiddleAdapter.kt similarity index 95% rename from app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonMiddleAdapter.kt rename to app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/MiddleAdapter.kt index 997b8b83..d3020c80 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonMiddleAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/MiddleAdapter.kt @@ -7,7 +7,7 @@ import com.navinfo.omqs.databinding.TextItemSelectBinding import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter 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() { private var selectTitle = "" diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonFragment.kt index 9eef25da..042c1411 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonFragment.kt @@ -5,13 +5,9 @@ import android.util.Log import android.view.LayoutInflater import android.view.View 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.RecyclerView import androidx.recyclerview.widget.RecyclerView.OnScrollListener -import com.navinfo.omqs.R import com.navinfo.omqs.databinding.FragmentPhenomenonBinding import com.navinfo.omqs.ui.fragment.BaseFragment import com.navinfo.omqs.ui.other.shareViewModels @@ -41,12 +37,15 @@ class PhenomenonFragment : //左侧菜单 binding.phenomenonLeftRecyclerview.setHasFixedSize(true) binding.phenomenonLeftRecyclerview.layoutManager = LinearLayoutManager(requireContext()) - val leftAdapter = PhenomenonLeftAdapter { _, text -> + /** + * 监听左侧栏的点击事件 + */ + val leftAdapter = LeftAdapter { _, text -> viewModel.getProblemTypeList(text) } binding.phenomenonLeftRecyclerview.adapter = leftAdapter //左侧菜单查询结果监听 - viewModel.liveDataClassTypeList.observe(viewLifecycleOwner) { + viewModel.liveDataLeftTypeList.observe(viewLifecycleOwner) { leftAdapter.refreshData(it) } @@ -55,26 +54,34 @@ class PhenomenonFragment : var rightLayoutManager = LinearLayoutManager(requireContext()) binding.phenomenonRightRecyclerview.layoutManager = rightLayoutManager - val rightAdapter = PhenomenonRightGroupHeaderAdapter { _, bean -> + /** + * 监听右侧栏的点击事件 + */ + val rightAdapter = RightGroupHeaderAdapter { _, bean -> viewModel.setPhenomenonMiddleBean(bean) } binding.phenomenonRightRecyclerview.adapter = rightAdapter //右侧菜单增加组标题 binding.phenomenonRightRecyclerview.addItemDecoration( - PhenomenonRightGroupHeaderDecoration( + RightGroupHeaderDecoration( requireContext() ) ) //右侧菜单查询数据监听 - viewModel.liveDataPhenomenonRightList.observe(viewLifecycleOwner) { + viewModel.liveDataRightTypeList.observe(viewLifecycleOwner) { rightAdapter.refreshData(it) } - val middleAdapter = PhenomenonMiddleAdapter { _, title -> + /** + * 监听中间栏的点击事件 + */ + val middleAdapter = MiddleAdapter { _, title -> rightLayoutManager.scrollToPositionWithOffset(rightAdapter.getGroupTopIndex(title), 0) - } + /** + * 监控右侧滚动,更新左侧 + */ binding.phenomenonRightRecyclerview.addOnScrollListener(object : OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { @@ -98,7 +105,7 @@ class PhenomenonFragment : binding.phenomenonMiddleRecyclerview.layoutManager = LinearLayoutManager(requireContext()) binding.phenomenonMiddleRecyclerview.adapter = middleAdapter //中间侧菜单查询结果监听 - viewModel.liveDataProblemTypeList.observe(viewLifecycleOwner) { + viewModel.liveDataMiddleTypeList.observe(viewLifecycleOwner) { middleAdapter.refreshData(it) } binding.phenomenonDrawer.setOnClickListener { diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonMiddleBean.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonMiddleBean.kt deleted file mode 100644 index 5f77e434..00000000 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonMiddleBean.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.navinfo.omqs.ui.fragment.evaluationresult - -/** - * 问题现象列表 - */ -data class PhenomenonMiddleBean(val title: String, val text: String, var isSelect: Boolean = false) diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/ProblemLinkFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/ProblemLinkFragment.kt index d10fe1ef..26286848 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/ProblemLinkFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/ProblemLinkFragment.kt @@ -35,22 +35,22 @@ class ProblemLinkFragment : BaseFragment() { var rightLayoutManager = LinearLayoutManager(requireContext()) binding.linkRightRecyclerview.layoutManager = rightLayoutManager - val rightAdapter = PhenomenonRightGroupHeaderAdapter { _, bean -> + val rightAdapter = RightGroupHeaderAdapter { _, bean -> viewModel.setProblemLinkMiddleBean(bean) } binding.linkRightRecyclerview.adapter = rightAdapter //右侧菜单增加组标题 binding.linkRightRecyclerview.addItemDecoration( - PhenomenonRightGroupHeaderDecoration( + RightGroupHeaderDecoration( requireContext() ) ) //右侧菜单查询数据监听 - viewModel.liveDataPhenomenonRightList.observe(viewLifecycleOwner) { + viewModel.liveDataRightTypeList.observe(viewLifecycleOwner) { rightAdapter.refreshData(it) } - val middleAdapter = PhenomenonMiddleAdapter { _, title -> + val middleAdapter = MiddleAdapter { _, title -> rightLayoutManager.scrollToPositionWithOffset(rightAdapter.getGroupTopIndex(title), 0) } @@ -72,7 +72,7 @@ class ProblemLinkFragment : BaseFragment() { binding.linkMiddleRecyclerview.layoutManager = LinearLayoutManager(requireContext()) binding.linkMiddleRecyclerview.adapter = middleAdapter //中间侧菜单查询结果监听 - viewModel.liveDataProblemTypeList.observe(viewLifecycleOwner) { + viewModel.liveDataMiddleTypeList.observe(viewLifecycleOwner) { middleAdapter.refreshData(it) } binding.linkDrawer.setOnClickListener { diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightBean.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightBean.kt new file mode 100644 index 00000000..090cf251 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightBean.kt @@ -0,0 +1,6 @@ +package com.navinfo.omqs.ui.fragment.evaluationresult + +/** + * 问题现象列表 + */ +data class RightBean(val title: String, val text: String, var isSelect: Boolean = false) diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonRightGroupHeaderAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightGroupHeaderAdapter.kt similarity index 92% rename from app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonRightGroupHeaderAdapter.kt rename to app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightGroupHeaderAdapter.kt index 1b57d518..d2d77b76 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonRightGroupHeaderAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightGroupHeaderAdapter.kt @@ -7,8 +7,8 @@ import com.navinfo.omqs.databinding.TextItemSelectBinding import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter import com.navinfo.omqs.ui.other.BaseViewHolder -class PhenomenonRightGroupHeaderAdapter(private var itemListener: ((Int, PhenomenonMiddleBean) -> Unit?)? = null) : - BaseRecyclerViewAdapter() { +class RightGroupHeaderAdapter(private var itemListener: ((Int, RightBean) -> Unit?)? = null) : + BaseRecyclerViewAdapter() { private var groupTitleList = mutableListOf() override fun getItemViewRes(position: Int): Int { return R.layout.text_item_select @@ -85,7 +85,7 @@ class PhenomenonRightGroupHeaderAdapter(private var itemListener: ((Int, Phenome return 0 } - override fun refreshData(newData: List) { + override fun refreshData(newData: List) { super.refreshData(newData) groupTitleList.clear() for (item in newData) { diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonRightGroupHeaderDecoration.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightGroupHeaderDecoration.kt similarity index 91% rename from app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonRightGroupHeaderDecoration.kt rename to app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightGroupHeaderDecoration.kt index 23b60c68..8cf32e01 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/PhenomenonRightGroupHeaderDecoration.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/RightGroupHeaderDecoration.kt @@ -5,7 +5,6 @@ import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Rect -import android.util.Log import android.view.View import androidx.recyclerview.widget.LinearLayoutManager 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 mTextPaddingLeft: Int @@ -48,8 +47,8 @@ class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration() * @param state */ override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { - if (parent.adapter is PhenomenonRightGroupHeaderAdapter) { - val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter + if (parent.adapter is RightGroupHeaderAdapter) { + val adapter = parent.adapter as RightGroupHeaderAdapter val count = parent.childCount //获取可见范围内Item的总数 for (i in 0 until count) { val view: View = parent.getChildAt(i) @@ -99,8 +98,8 @@ class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration() * @param state */ override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { - if (parent.adapter is PhenomenonRightGroupHeaderAdapter) { - val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter + if (parent.adapter is RightGroupHeaderAdapter) { + val adapter = parent.adapter as RightGroupHeaderAdapter val position = (parent.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition() parent.findViewHolderForAdapterPosition(position)?.let { @@ -169,8 +168,8 @@ class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration() parent: RecyclerView, state: RecyclerView.State ) { - if (parent.adapter is PhenomenonRightGroupHeaderAdapter) { - val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter + if (parent.adapter is RightGroupHeaderAdapter) { + val adapter = parent.adapter as RightGroupHeaderAdapter //获取当前view在整个列表中的位置 val position = parent.getChildLayoutPosition(view) //是不是改组的第一个 @@ -180,7 +179,7 @@ class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration() if (adapter.isLastGroupTitle(position)) { lastGroupView = view } - } else if (position == (parent.adapter as PhenomenonRightGroupHeaderAdapter).itemCount - 1) { + } else if (position == (parent.adapter as RightGroupHeaderAdapter).itemCount - 1) { //判断这条是不是最后一条 //如果是最后一个,找到他所在组的第一个 lastGroupView?.let { diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt index d96f9b67..c9a14726 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt @@ -71,15 +71,16 @@ class PersonalCenterViewModel @Inject constructor( val list = mutableListOf() for (i in 1 until rowCount) { val row: Row = it.getRow(i) // 获取行 - val cellCount: Int = row.physicalNumberOfCells // 获取列数 - if (cellCount == 3) { - val bean = ScProblemTypeBean() - bean.classType = row.getCell(0).stringCellValue - bean.problemType = row.getCell(1).stringCellValue - bean.phenomenon = row.getCell(2).stringCellValue - list.add(bean) - Log.e("jingo", bean.toString()) - } +// val cellCount: Int = row.physicalNumberOfCells // 获取列数 + val bean = ScProblemTypeBean( + elementType = row.getCell(0).stringCellValue, + elementCode = row.getCell(1).numericCellValue.toString(), + classType = row.getCell(2).stringCellValue, + problemType = row.getCell(3).stringCellValue, + phenomenon = row.getCell(4).stringCellValue + ) + list.add(bean) + Log.e("jingo", bean.toString()) } roomAppDatabase.getScProblemTypeDao().insertOrUpdateList(list) } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f15ff59a..7193cd33 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -98,10 +98,9 @@ diff --git a/app/src/main/res/layout/fragment_evaluation_result.xml b/app/src/main/res/layout/fragment_evaluation_result.xml index c9829571..dca0534c 100644 --- a/app/src/main/res/layout/fragment_evaluation_result.xml +++ b/app/src/main/res/layout/fragment_evaluation_result.xml @@ -1,97 +1,120 @@ - + xmlns:tools="http://schemas.android.com/tools"> - + + + + + + android:layout_height="match_parent" + android:background="@color/white" + tools:context=".ui.fragment.evaluationresult.EvaluationResultFragment"> - + android:layout_height="wrap_content" + app:layout_constraintTop_toTopOf="parent"> - - - - - - - - - + android:layout_height="?attr/actionBarSize" + android:background="@color/default_blue" + app:menu="@menu/evaluation_bar_mean" + app:navigationIcon="@drawable/btn_back_xml" + app:title="测评结果" /> - + + + + + android:layout_height="match_parent" + android:orientation="vertical"> - + - + - + - - - - - + - - - - - - - + - \ No newline at end of file + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/right_fragment_nav_graph.xml b/app/src/main/res/navigation/right_fragment_nav_graph.xml index 25383197..a8b5714f 100644 --- a/app/src/main/res/navigation/right_fragment_nav_graph.xml +++ b/app/src/main/res/navigation/right_fragment_nav_graph.xml @@ -15,5 +15,10 @@ android:id="@+id/EvaluationResultFragment" android:name="com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment" android:label="评测页面" - tools:layout="@layout/fragment_evaluation_result"> + tools:layout="@layout/fragment_evaluation_result"> + + \ No newline at end of file diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/QsRecordBean.kt b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/QsRecordBean.kt index 550239e2..30491286 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/QsRecordBean.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/QsRecordBean.kt @@ -36,7 +36,7 @@ open class QsRecordBean @JvmOverloads constructor( /** * 问题类型 */ - var type: String = "", + var problemType: String = "", /** * 问题现象 diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/cluster/ClusterMarkerItem.kt b/collect-library/src/main/java/com/navinfo/collect/library/map/cluster/ClusterMarkerItem.kt index f466c4f1..9e13f496 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/cluster/ClusterMarkerItem.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/cluster/ClusterMarkerItem.kt @@ -10,15 +10,7 @@ import org.oscim.layers.marker.MarkerItem *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) { var clusterList: List = ArrayList() - - constructor(title: String?, description: String?, geoPoint: GeoPoint?) : this( - null, - title, - description, - geoPoint - ) { - } } \ No newline at end of file diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt index 6e6e65fb..7e68eaa0 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt @@ -34,10 +34,12 @@ import org.oscim.layers.marker.* import org.oscim.layers.tile.buildings.BuildingLayer import org.oscim.layers.tile.vector.VectorTileLayer import org.oscim.layers.tile.vector.labeling.LabelLayer +import org.oscim.map.Map.UpdateListener import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory import org.oscim.tiling.source.mapfile.MapFileTileSource import java.io.File import java.util.* +import java.util.stream.Collectors /** * Layer 操作 @@ -62,7 +64,8 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : private lateinit var canvas: org.oscim.backend.canvas.Canvas private lateinit var itemizedLayer: MyItemizedLayer private lateinit var markerRendererFactory: MarkerRendererFactory - private val markerItemsNames = mutableListOf() + private var resId = R.mipmap.map_icon_point_add + private var itemListener: OnQsRecordItemClickListener? = null /** * 文字大小 @@ -79,11 +82,16 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : private fun initMap() { loadBaseMap() - mMapView.switchTileVectorLayerTheme(NIMapView.MAP_THEME.DEFAULT) //初始化之间数据图层 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 + } + }) } @@ -144,7 +152,45 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : for (layer in it.layers) { addLayer(layer, NIMapView.LAYER_GROUPS.BASE) } - mMapView.updateMap() + } + } + mMapView.switchTileVectorLayerTheme(NIMapView.MAP_THEME.DEFAULT) + 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 deleteQsRecordMark(data: QsRecordBean) { + for (item in itemizedLayer.itemList) { + if (item is MarkerItem) { + if (item.title == data.id) { + itemizedLayer.itemList.remove(item) + mMapView.updateMap() + return + } } } } @@ -153,6 +199,7 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : * 初始话质检数据图层 */ private fun initQsRecordDataLayer() { + canvas = CanvasAdapter.newCanvas() paint = CanvasAdapter.newPaint() paint.setTypeface(Paint.FontFamily.DEFAULT, Paint.FontStyle.NORMAL) @@ -182,50 +229,67 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : } } - var resId = R.mipmap.map_icon_point_add + itemizedLayer = + MyItemizedLayer( + mMapView.vtmMap, + mutableListOf(), + markerRendererFactory, + object : MyItemizedLayer.OnItemGestureListener { + override fun onItemSingleTapUp( + list: MutableList, + nearest: Int + ): Boolean { + itemListener?.let { + val idList = mutableListOf() + 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 + } + override fun onItemLongPress( + list: MutableList?, + nearest: Int + ): Boolean { + return true + } + }) + addLayer(itemizedLayer, NIMapView.LAYER_GROUPS.OPERATE) mContext.lifecycleScope.launch(Dispatchers.IO) { var list = mutableListOf() val realm = Realm.getDefaultInstance() realm.executeTransaction { - val objects =realm.where().findAll() + val objects = realm.where().findAll() list = realm.copyFromRealm(objects) } realm.close() - itemizedLayer = - MyItemizedLayer( - mMapView.vtmMap, - mutableListOf(), - markerRendererFactory, - object : MyItemizedLayer.OnItemGestureListener { - override fun onItemSingleTapUp( - layer: MyItemizedLayer?, - list: MutableList?, - nearest: Int - ): Boolean { - return true - } - - override fun onItemLongPress( - layer: MyItemizedLayer?, - list: MutableList?, - nearest: Int - ): Boolean { - return true - } - }) - for (item in list) { - val bitmap: Bitmap = createTextMarkerBitmap(mContext, item.description, resId) - if (item.t_lifecycle != 2) { - val geometry: Geometry? = GeometryTools.createGeometry(item.geometry) - if (geometry != null) { - var geoPoint: GeoPoint? = null - if (geometry.geometryType != null) { - when (geometry.geometryType.uppercase(Locale.getDefault())) { - "POINT" -> geoPoint = - GeoPoint(geometry.coordinate.y, geometry.coordinate.x) + createMarkerItem(item) + } + } + + } + + private suspend fun createMarkerItem(item: QsRecordBean) { + val bitmap: Bitmap = createTextMarkerBitmap(mContext, item.description, resId) + if (item.t_lifecycle != 2) { + val geometry: Geometry? = GeometryTools.createGeometry(item.geometry) + if (geometry != null) { + var geoPoint: GeoPoint? = null + if (geometry.geometryType != null) { + when (geometry.geometryType.uppercase(Locale.getDefault())) { + "POINT" -> geoPoint = + GeoPoint(geometry.coordinate.y, geometry.coordinate.x) // "LINESTRING" -> { // val lineString = geometry as LineString // if (lineString != null && lineString.coordinates.size > 0) { @@ -254,14 +318,14 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : // dataVectorLayer.add(drawablePolygon) // } // } - } - } - if (geoPoint != null) { - var geoMarkerItem: MarkerItem + } + } + if (geoPoint != null) { + var geoMarkerItem: MarkerItem // if (item.getType() === 1) { - geoMarkerItem = ClusterMarkerItem( - 1, item.id, item.description, geoPoint - ) + geoMarkerItem = ClusterMarkerItem( + 1, item.id, item.description, geoPoint + ) // } else { // geoMarkerItem = MarkerItem( // ePointTemp.getType(), @@ -270,22 +334,21 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : // geoPoint // ) // } - markerItemsNames.add(geoMarkerItem) - val markerSymbol = - MarkerSymbol(bitmap, MarkerSymbol.HotspotPlace.CENTER) - geoMarkerItem.marker = markerSymbol - } - } + val markerSymbol = + MarkerSymbol(bitmap, MarkerSymbol.HotspotPlace.CENTER) + geoMarkerItem.marker = markerSymbol + itemizedLayer.itemList.add(geoMarkerItem) } } - itemizedLayer.addItems(markerItemsNames) - addLayer(itemizedLayer, NIMapView.LAYER_GROUPS.OPERATE) - withContext(Dispatchers.Main) { - itemizedLayer.map().updateMap(true) - } } + withContext(Dispatchers.Main) { + itemizedLayer.update() + } + + itemizedLayer.populate() } + /** * 文字和图片拼装,文字换行 * @@ -498,6 +561,9 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : } +interface OnQsRecordItemClickListener { + fun onQsRecordList(list: MutableList) +} /** * 基础 diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/layers/MyItemizedLayer.java b/collect-library/src/main/java/com/navinfo/collect/library/map/layers/MyItemizedLayer.java index 0452ab8c..cae265b8 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/layers/MyItemizedLayer.java +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/layers/MyItemizedLayer.java @@ -50,7 +50,7 @@ public class MyItemizedLayer extends ItemizedLayer { public boolean run(List list1, int nearest) { if (mOnItemGestureListener != null) { - return mOnItemGestureListener.onItemSingleTapUp(MyItemizedLayer.this, list1, nearest); + return mOnItemGestureListener.onItemSingleTapUp(list1, nearest); } return false; } @@ -62,7 +62,7 @@ public class MyItemizedLayer extends ItemizedLayer { public boolean run(List list1, int nearest) { if (mOnItemGestureListener != null) { - return mOnItemGestureListener.onItemLongPress(MyItemizedLayer.this, list1, nearest); + return mOnItemGestureListener.onItemLongPress(list1, nearest); } return false; } @@ -155,8 +155,8 @@ public class MyItemizedLayer extends ItemizedLayer { } public interface OnItemGestureListener { - boolean onItemSingleTapUp(MyItemizedLayer layer, List list, int nearest); + boolean onItemSingleTapUp(List list, int nearest); - boolean onItemLongPress(MyItemizedLayer layer, List list, int nearest); + boolean onItemLongPress(List list, int nearest); } } From d8735d67d6079fbded807e07d352c8722909f890 Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Fri, 21 Apr 2023 14:10:15 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E6=8D=95=E6=8D=89=E6=95=B0=E6=8D=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/fragment/evaluationresult/EvaluationResultViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt index 1e162cb1..b0ed0936 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt @@ -85,7 +85,6 @@ class EvaluationResultViewModel @Inject constructor( * //获取问题分类列表 */ fun getClassTypeList() { - viewModelScope.launch(Dispatchers.IO) { val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList() list?.let { From d46f5f422379ad2ec96730c39057d10f7004a22f Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Fri, 21 Apr 2023 14:22:12 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E6=8D=95=E6=8D=89=E6=95=B0=E6=8D=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/navinfo/omqs/ui/activity/PermissionsActivity.kt | 8 +++----- .../com/navinfo/omqs/ui/activity/map/MainViewModel.kt | 2 -- .../evaluationresult/EvaluationResultViewModel.kt | 5 ++++- collect-library/build.gradle | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt index 51e671ec..36ec694e 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt @@ -29,13 +29,11 @@ open class PermissionsActivity : BaseActivity() { //定位权限 permissionList.add(Permission.ACCESS_FINE_LOCATION) permissionList.add(Permission.ACCESS_COARSE_LOCATION) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { -// permissionList.add(Permission.ACCESS_BACKGROUND_LOCATION) //android10 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) // 设置权限请求拦截器(局部设置) @@ -75,7 +73,7 @@ open class PermissionsActivity : BaseActivity() { onPermissionsDenied() } } - })*/ + }) } /** diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt index 2e5836a5..47687450 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt @@ -5,7 +5,6 @@ import android.content.DialogInterface import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.navinfo.collect.library.data.entity.NiLocation import com.blankj.utilcode.util.ToastUtils import com.navinfo.collect.library.data.entity.NiLocation import com.navinfo.collect.library.map.NIMapController @@ -21,7 +20,6 @@ import com.navinfo.omqs.ui.manager.TakePhotoManager import dagger.hilt.android.lifecycle.HiltViewModel import io.realm.RealmSet import org.videolan.libvlc.LibVlcUtil -import java.util.* import javax.inject.Inject /** diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt index b0ed0936..dd1bef32 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt @@ -85,8 +85,10 @@ class EvaluationResultViewModel @Inject constructor( * //获取问题分类列表 */ fun getClassTypeList() { + Log.e("jingo", "getClassTypeList S") viewModelScope.launch(Dispatchers.IO) { val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList() + Log.e("jingo", "getClassTypeList ${list?.size}") list?.let { if (list.isNotEmpty()) { //通知页面更新 @@ -94,13 +96,14 @@ class EvaluationResultViewModel @Inject constructor( val classType = it[0] //如果右侧栏没数据,给个默认值 if (liveDataQsRecordBean.value!!.classType.isEmpty()) { + Log.e("jingo", "getClassTypeList $classType") liveDataQsRecordBean.value!!.classType = classType } getProblemList(classType) } } } - + Log.e("jingo", "getClassTypeList E") } /** diff --git a/collect-library/build.gradle b/collect-library/build.gradle index c125ed9d..42dd53e5 100644 --- a/collect-library/build.gradle +++ b/collect-library/build.gradle @@ -105,7 +105,7 @@ dependencies { implementation "com.badlogicgames.gdx:gdx:1.11.0" implementation "com.badlogicgames.gdx:gdx-backend-android:1.11.0" implementation "com.caverock:androidsvg:1.4" - implementation "org.mapsforge:vtm-jts:$vtmVersion" + api "org.mapsforge:vtm-jts:$vtmVersion" implementation 'org.locationtech.jts:jts-core:1.19.0' implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.11' implementation 'com.squareup.okio:okio:3.3.0' From a1170db7a9aa35869849c864f8d067a3f131e5ab Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Sun, 23 Apr 2023 16:35:45 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=92=8C=E4=B8=8B=E8=BD=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/navinfo/omqs/Constant.kt | 2 +- .../java/com/navinfo/omqs/OMQSApplication.kt | 4 +- .../com/navinfo/omqs/bean/HadLinkDvoBean.kt | 21 +++ .../navinfo/omqs/bean/OfflineMapCityBean.kt | 13 +- .../java/com/navinfo/omqs/bean/TaskBean.kt | 64 +++++++ .../java/com/navinfo/omqs/db/MyRealmModule.kt | 8 +- .../navinfo/omqs/hilt/MainActivityModule.kt | 11 ++ .../navinfo/omqs/http/DefaultTaskResponse.kt | 7 + .../com/navinfo/omqs/http/NetworkService.kt | 5 + .../navinfo/omqs/http/NetworkServiceImpl.kt | 20 +++ .../omqs/http/RetrofitNetworkServiceAPI.kt | 11 +- .../OfflineMapDownloadManager.kt | 2 - .../OfflineMapDownloadScope.kt | 25 ++- .../http/taskdownload/TaskDownloadManager.kt | 113 ++++++++++++ .../http/taskdownload/TaskDownloadScope.kt | 168 ++++++++++++++++++ .../com/navinfo/omqs/tools/FileManager.kt | 20 ++- .../omqs/ui/activity/map/MainActivity.kt | 19 +- .../omqs/ui/activity/map/MainViewModel.kt | 73 ++++++-- .../EvaluationResultFragment.kt | 4 +- .../EvaluationResultViewModel.kt | 64 ++++--- .../offlinemap/OfflineMapCityListAdapter.kt | 20 ++- .../fragment/offlinemap/OfflineMapFragment.kt | 3 +- .../personalcenter/PersonalCenterFragment.kt | 41 +++-- .../ui/fragment/tasklist/TaskListAdapter.kt | 132 ++++++++++++++ .../ui/fragment/tasklist/TaskListFragment.kt | 55 ++++++ .../ui/fragment/tasklist/TaskListViewModel.kt | 61 +++++++ .../com/navinfo/omqs/ui/widget/MyEditeText.kt | 53 ++++++ app/src/main/res/layout/adapter_task_list.xml | 67 +++++++ .../res/layout/fragment_evaluation_result.xml | 25 ++- .../layout/fragment_offline_map_city_list.xml | 6 +- .../main/res/layout/fragment_task_list.xml | 27 +++ .../main/res/menu/personal_center_menu.xml | 9 +- .../res/navigation/left_drawer_nav_graph.xml | 16 +- .../library/data/entity/QsRecordBean.kt | 22 +++ .../map/handler/LayerManagerHandler.kt | 29 +-- 35 files changed, 1083 insertions(+), 137 deletions(-) create mode 100644 app/src/main/java/com/navinfo/omqs/bean/HadLinkDvoBean.kt create mode 100644 app/src/main/java/com/navinfo/omqs/bean/TaskBean.kt create mode 100644 app/src/main/java/com/navinfo/omqs/http/DefaultTaskResponse.kt create mode 100644 app/src/main/java/com/navinfo/omqs/http/taskdownload/TaskDownloadManager.kt create mode 100644 app/src/main/java/com/navinfo/omqs/http/taskdownload/TaskDownloadScope.kt create mode 100644 app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListAdapter.kt create mode 100644 app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListFragment.kt create mode 100644 app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListViewModel.kt create mode 100644 app/src/main/java/com/navinfo/omqs/ui/widget/MyEditeText.kt create mode 100644 app/src/main/res/layout/adapter_task_list.xml create mode 100644 app/src/main/res/layout/fragment_task_list.xml diff --git a/app/src/main/java/com/navinfo/omqs/Constant.kt b/app/src/main/java/com/navinfo/omqs/Constant.kt index 306ff4e3..6612fdc2 100644 --- a/app/src/main/java/com/navinfo/omqs/Constant.kt +++ b/app/src/main/java/com/navinfo/omqs/Constant.kt @@ -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 diff --git a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt index 85afd8be..9d0ea133 100644 --- a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt +++ b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt @@ -3,6 +3,7 @@ package com.navinfo.omqs import android.app.Application import android.util.Log import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase +import com.navinfo.omqs.db.MyRealmModule import com.navinfo.omqs.db.TraceDataBase import com.navinfo.omqs.tools.FileManager import com.navinfo.omqs.ui.manager.TakePhotoManager @@ -29,12 +30,11 @@ class OMQSApplication : Application() { val password = "encryp".encodeToByteArray().copyInto(ByteArray(64)) // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Log.d("OMQSApplication", "密码是: ${byteArrayToHexString(password)}") - // 1110000011000010111001101110011011101110110111101110010011001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 val config = RealmConfiguration.Builder() .directory(File(Constant.DATA_PATH)) .name("OMQS.realm") .encryptionKey(password) -// .modules(Realm.getDefaultModule(), MyRealmModule()) + .modules(Realm.getDefaultModule(), MyRealmModule()) .schemaVersion(1) .build() Realm.setDefaultConfiguration(config) diff --git a/app/src/main/java/com/navinfo/omqs/bean/HadLinkDvoBean.kt b/app/src/main/java/com/navinfo/omqs/bean/HadLinkDvoBean.kt new file mode 100644 index 00000000..110307dc --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/bean/HadLinkDvoBean.kt @@ -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() \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityBean.kt b/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityBean.kt index cb269e60..98c6d785 100644 --- a/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityBean.kt +++ b/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityBean.kt @@ -3,6 +3,7 @@ package com.navinfo.omqs.bean import android.os.Parcelable import androidx.room.Entity import androidx.room.PrimaryKey +import com.navinfo.omqs.tools.FileManager import kotlinx.parcelize.Parcelize @@ -17,19 +18,9 @@ data class OfflineMapCityBean @JvmOverloads constructor( var version: Long = 0L, var fileSize: Long = 0L, var currentSize: Long = 0L, - var status: Int = NONE + var status: Int = FileManager.Companion.FileDownloadStatus.NONE ) : 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的转换对象 // var statusEnum: StatusEnum // get() { diff --git a/app/src/main/java/com/navinfo/omqs/bean/TaskBean.kt b/app/src/main/java/com/navinfo/omqs/bean/TaskBean.kt new file mode 100644 index 00000000..9fed8d44 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/bean/TaskBean.kt @@ -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 = RealmList(), + /** + * 文件大小 + */ + 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" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/db/MyRealmModule.kt b/app/src/main/java/com/navinfo/omqs/db/MyRealmModule.kt index 0b1cb8a3..15350948 100644 --- a/app/src/main/java/com/navinfo/omqs/db/MyRealmModule.kt +++ b/app/src/main/java/com/navinfo/omqs/db/MyRealmModule.kt @@ -1,7 +1,9 @@ package com.navinfo.omqs.db 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]) -//class MyRealmModule { -//} \ No newline at end of file +@io.realm.annotations.RealmModule(classes = [TaskBean::class, HadLinkDvoBean::class]) +class MyRealmModule { +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt b/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt index cffe1f47..7d353b88 100644 --- a/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt +++ b/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt @@ -5,6 +5,7 @@ import com.navinfo.omqs.db.RealmOperateHelper import com.navinfo.omqs.db.RoomAppDatabase import com.navinfo.omqs.http.RetrofitNetworkServiceAPI import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager +import com.navinfo.omqs.http.taskdownload.TaskDownloadManager import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -34,6 +35,16 @@ class MainActivityModule { ): OfflineMapDownloadManager = OfflineMapDownloadManager(networkServiceAPI, roomAppDatabase, mapController) + /** + * 注入任务下载 + */ + @ActivityRetainedScoped + @Provides + fun providesTaskListDownloadManager( + networkServiceAPI: RetrofitNetworkServiceAPI, + ): TaskDownloadManager = + TaskDownloadManager(networkServiceAPI) + /** * 实验失败,这样创建,viewmodel不会在activity销毁的时候同时销毁 * 4-14:因为没有传入activity的 owner,无法检测生命周期, diff --git a/app/src/main/java/com/navinfo/omqs/http/DefaultTaskResponse.kt b/app/src/main/java/com/navinfo/omqs/http/DefaultTaskResponse.kt new file mode 100644 index 00000000..a51f8098 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/http/DefaultTaskResponse.kt @@ -0,0 +1,7 @@ +package com.navinfo.omqs.http + +class DefaultTaskResponse { + var success: Boolean = false + var msg: String = "" + var obj: T? = null +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt b/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt index fde1d736..82238b8e 100644 --- a/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt +++ b/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt @@ -1,6 +1,7 @@ package com.navinfo.omqs.http import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.omqs.bean.TaskBean /** @@ -11,4 +12,8 @@ interface NetworkService { * 获取离线地图城市列表 */ suspend fun getOfflineMapCityList():NetResult> + /** + * 获取任务列表 + */ + suspend fun getTaskList(evaluatorNo:String): NetResult>> } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt b/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt index 4a67bf83..306ea857 100644 --- a/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt +++ b/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt @@ -1,6 +1,7 @@ package com.navinfo.omqs.http import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.omqs.bean.TaskBean import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import javax.inject.Inject @@ -32,4 +33,23 @@ class NetworkServiceImpl @Inject constructor( NetResult.Error(e) } } + + override suspend fun getTaskList(evaluatorNo: String): NetResult>> = + //在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) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt b/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt index c4463b6d..2761f3b5 100644 --- a/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt +++ b/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt @@ -1,10 +1,12 @@ package com.navinfo.omqs.http import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.omqs.bean.TaskBean import okhttp3.ResponseBody import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Header +import retrofit2.http.Query import retrofit2.http.Streaming import retrofit2.http.Url @@ -46,8 +48,15 @@ interface RetrofitNetworkServiceAPI { */ @Streaming @GET - suspend fun retrofitDownLoadFile(@Header("RANGE") start: String? = "0", @Url url: String):Response + suspend fun retrofitDownLoadFile( + @Header("RANGE") start: String? = "0", + @Url url: String + ): Response + @GET("/devcp/task?evaluatType=2") + suspend fun retrofitGetTaskList( + @Query("evaluatorNo") evaluatorNo: String, + ): Response>> /** * @FormUrlEncoded 请求格式注解,请求实体是一个From表单,每个键值对需要使用@Field注解 diff --git a/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadManager.kt b/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadManager.kt index 87907e6e..8b6fbdf2 100644 --- a/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadManager.kt +++ b/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadManager.kt @@ -112,6 +112,4 @@ class OfflineMapDownloadManager( scopeMap[id]!!.removeObserver() } } - - } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadScope.kt b/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadScope.kt index 0e133dff..03e5ed74 100644 --- a/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadScope.kt +++ b/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadScope.kt @@ -6,6 +6,8 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer import com.navinfo.omqs.Constant import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.omqs.tools.FileManager +import com.navinfo.omqs.tools.FileManager.Companion.FileDownloadStatus import kotlinx.coroutines.* import java.io.File import java.io.IOException @@ -23,7 +25,7 @@ class OfflineMapDownloadScope( private val downloadManager: OfflineMapDownloadManager, val cityBean: OfflineMapCityBean, ) : - CoroutineScope by CoroutineScope(Dispatchers.IO) { + CoroutineScope by CoroutineScope(Dispatchers.IO + CoroutineName("OfflineMapDownLoad")) { /** *下载任务,用来取消的 */ @@ -46,7 +48,7 @@ class OfflineMapDownloadScope( //改进的代码 fun start() { - change(OfflineMapCityBean.WAITING) + change(FileDownloadStatus.WAITING) downloadManager.launchScope(this@OfflineMapDownloadScope) } @@ -56,7 +58,7 @@ class OfflineMapDownloadScope( */ fun pause() { downloadJob?.cancel("pause") - change(OfflineMapCityBean.PAUSE) + change(FileDownloadStatus.PAUSE) } /** @@ -65,11 +67,8 @@ class OfflineMapDownloadScope( */ fun launch() { downloadJob = launch() { - Log.e("jingo", "启动下载1") download() - Log.e("jingo", "启动下载2") downloadManager.launchNext(cityBean.id) - Log.e("jingo", "启动下载3") } } @@ -78,7 +77,7 @@ class OfflineMapDownloadScope( * 是否是等待任务 */ fun isWaiting(): Boolean { - return cityBean.status == OfflineMapCityBean.WAITING + return cityBean.status == FileDownloadStatus.WAITING } /** @@ -86,7 +85,7 @@ class OfflineMapDownloadScope( * @param status [OfflineMapCityBean.Status] */ private fun change(status: Int) { - if (cityBean.status != status || status == OfflineMapCityBean.LOADING) { + if (cityBean.status != status || status == FileDownloadStatus.LOADING) { cityBean.status = status downloadData.postValue(cityBean) launch(Dispatchers.IO) { @@ -128,7 +127,7 @@ class OfflineMapDownloadScope( url = cityBean.url ) val responseBody = response.body() - change(OfflineMapCityBean.LOADING) + change(FileDownloadStatus.LOADING) responseBody ?: throw IOException("jingo ResponseBody is null") //写入文件 randomAccessFile = RandomAccessFile(fileTemp, "rwd") @@ -144,7 +143,7 @@ class OfflineMapDownloadScope( if (readLength != -1) { randomAccessFile.write(buffer, 0, readLength) cityBean.currentSize += readLength - change(OfflineMapCityBean.LOADING) + change(FileDownloadStatus.LOADING) } else { break } @@ -155,15 +154,15 @@ class OfflineMapDownloadScope( val res = fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}")) Log.e("jingo", "文件下载完成 修改文件 $res") - change(OfflineMapCityBean.DONE) + change(FileDownloadStatus.DONE) withContext(Dispatchers.Main) { downloadManager.mapController.layerManagerHandler.loadBaseMap() } } else { - change(OfflineMapCityBean.PAUSE) + change(FileDownloadStatus.PAUSE) } } catch (e: Throwable) { - change(OfflineMapCityBean.ERROR) + change(FileDownloadStatus.ERROR) } finally { inputStream?.close() randomAccessFile?.close() diff --git a/app/src/main/java/com/navinfo/omqs/http/taskdownload/TaskDownloadManager.kt b/app/src/main/java/com/navinfo/omqs/http/taskdownload/TaskDownloadManager.kt new file mode 100644 index 00000000..57da8cd8 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/http/taskdownload/TaskDownloadManager.kt @@ -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 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { + ConcurrentHashMap() + } + + /** + * 存储正在下载的城市队列 + */ + private val taskScopeMap: ConcurrentHashMap by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { + ConcurrentHashMap() + } + + + /** + * 启动下载任务 + * 请不要直接使用此方法启动下载任务,它是交由[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 + ) { + if (scopeMap.containsKey(id)) { + scopeMap[id]!!.observer(lifecycleOwner, observer) + } + } + + fun removeObserver(id: Int) { + if (scopeMap.containsKey(id)) { + scopeMap[id]!!.removeObserver() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/http/taskdownload/TaskDownloadScope.kt b/app/src/main/java/com/navinfo/omqs/http/taskdownload/TaskDownloadScope.kt new file mode 100644 index 00000000..6e698de6 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/http/taskdownload/TaskDownloadScope.kt @@ -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 {} +// private var lifecycleOwner: LifecycleOwner? = null + + /** + *通知UI更新 + */ + private val downloadData = MutableLiveData() + + 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) { + 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 +// } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/tools/FileManager.kt b/app/src/main/java/com/navinfo/omqs/tools/FileManager.kt index 0f0c0244..df942398 100644 --- a/app/src/main/java/com/navinfo/omqs/tools/FileManager.kt +++ b/app/src/main/java/com/navinfo/omqs/tools/FileManager.kt @@ -6,7 +6,19 @@ import com.navinfo.omqs.bean.OfflineMapCityBean import java.io.File class FileManager { + 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){ // 在SD卡创建项目目录 @@ -51,7 +63,7 @@ class FileManager { if (item.isFile && item.name.startsWith(cityBean.id)) { //如果本地文件与从网络获取到版本号一致,表示这个文件已经下载完毕,不用处理了 if (item.name.contains("_${cityBean.version}.map")) { - cityBean.status = OfflineMapCityBean.DONE + cityBean.status = FileDownloadStatus.DONE return } //文件存在,版本号不对应,留给下面流程处理 @@ -72,16 +84,16 @@ class FileManager { if (item.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}"))) { //删除旧版本数据 mapFile?.delete() - cityBean.status = OfflineMapCityBean.DONE + cityBean.status = FileDownloadStatus.DONE return } } else { // 临时文件大小和目标不一致,说明下载了一半 - cityBean.status = OfflineMapCityBean.PAUSE + cityBean.status = FileDownloadStatus.PAUSE cityBean.currentSize = item.length() return } } else { //虽然省市id开头一致,但是版本号不一致,说明之前版本下载了一部分,现在要更新了,原来下载的文件直接删除 - cityBean.status = OfflineMapCityBean.UPDATE + cityBean.status = FileDownloadStatus.UPDATE item.delete() return } diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt index 56abfa21..503705cf 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt @@ -5,6 +5,7 @@ import android.util.Log import androidx.activity.viewModels import androidx.core.view.WindowCompat import androidx.databinding.DataBindingUtil +import androidx.lifecycle.ViewModelProvider import com.blankj.utilcode.util.ToastUtils import androidx.lifecycle.lifecycleScope import androidx.lifecycle.viewModelScope @@ -18,6 +19,8 @@ import com.navinfo.omqs.db.TraceDataBase import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager import com.navinfo.omqs.system.SystemConstant 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 javax.inject.Inject @@ -57,12 +60,8 @@ class MainActivity : BaseActivity() { binding.viewModel = viewModel viewModel.liveDataQsRecordIdList.observe(this) { - if (it.size == 1) { - val bundle = Bundle() - bundle.putString("QsId", it[0]) - val naviController = findNavController(R.id.main_activity_right_fragment) - naviController.navigate(R.id.EvaluationResultFragment, bundle) - } + //处理页面跳转 + viewModel.navigation(this, it) } } @@ -74,11 +73,11 @@ class MainActivity : BaseActivity() { mapController.locationLayerHandler.startLocation() //启动轨迹存储 mapController.locationLayerHandler.setNiLocationListener(NiLocationListener { - binding!!.viewModel!!.addSaveTrace(it) - binding!!.viewModel!!.startSaveTraceThread(this) + viewModel.addSaveTrace(it) +// binding.viewModel!!.startSaveTraceThread(this) }) //显示轨迹图层 - mapController.layerManagerHandler.showNiLocationLayer(Constant.DATA_PATH+ SystemConstant.USER_ID+"/trace.sqlite") +// mapController.layerManagerHandler.showNiLocationLayer(Constant.DATA_PATH+ SystemConstant.USER_ID+"/trace.sqlite") } override fun onPause() { @@ -108,7 +107,7 @@ class MainActivity : BaseActivity() { * 打开相机预览 */ fun openCamera() { - binding!!.viewModel!!.onClickCameraButton(this) + binding.viewModel!!.onClickCameraButton(this) } /** diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt index 47687450..d5f357e0 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt @@ -2,9 +2,11 @@ package com.navinfo.omqs.ui.activity.map import android.content.Context import android.content.DialogInterface +import android.os.Bundle import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.navigation.findNavController import com.blankj.utilcode.util.ToastUtils import com.navinfo.collect.library.data.entity.NiLocation import com.navinfo.collect.library.map.NIMapController @@ -33,7 +35,7 @@ class MainViewModel @Inject constructor( val liveDataQsRecordIdList = MutableLiveData>() private var mCameraDialog: CommonDialog? = null - private var niLocationList:MutableList = ArrayList() + private var niLocationList: MutableList = ArrayList() init { mapController.layerManagerHandler.setOnQsRecordItemClickListener(object : @@ -56,14 +58,21 @@ class MainViewModel @Inject constructor( } //点击相机按钮 - fun onClickCameraButton(context: Context){ + fun onClickCameraButton(context: Context) { Log.e("qj", LibVlcUtil.hasCompatibleCPU(context).toString()) ToastUtils.showShort("点击了相机") 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!!.openCamear(mCameraDialog!!.getmShareUtil().continusTakePhotoState) @@ -72,10 +81,11 @@ class MainViewModel @Inject constructor( mCameraDialog!!.hideLoading() mCameraDialog!!.stopVideo() try { - if (!mCameraDialog!!.getmShareUtil().connectstate){ + if (!mCameraDialog!!.getmShareUtil().connectstate) { mCameraDialog!!.updateCameraResources(1, mCameraDialog!!.getmDeviceNum()) } - TakePhotoManager.getInstance().getCameraVedioClent(mCameraDialog!!.getmDeviceNum()).StopSearch() + TakePhotoManager.getInstance().getCameraVedioClent(mCameraDialog!!.getmDeviceNum()) + .StopSearch() } catch (e: Exception) { } }) @@ -87,12 +97,12 @@ class MainViewModel @Inject constructor( }) } - fun startSaveTraceThread(context: Context){ + fun startSaveTraceThread(context: Context) { Thread(Runnable { try { - while (true){ + while (true) { - if(niLocationList!=null&&niLocationList.size>0){ + if (niLocationList != null && niLocationList.size > 0) { var niLocation = niLocationList[0] var doubleArray = doubleArrayOf() @@ -112,23 +122,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) - Log.e("qj","saveTrace") + Log.e("qj", "saveTrace") } Thread.sleep(30) } } catch (e: InterruptedException) { e.printStackTrace() - Log.e("qj","异常==${e.message}") + Log.e("qj", "异常==${e.message}") } }).start() } //增加轨迹存储 - fun addSaveTrace(niLocation: NiLocation){ - if(niLocation!=null&&niLocationList!=null){ + fun addSaveTrace(niLocation: NiLocation) { + if (niLocation != null && niLocationList != null) { niLocationList.add(niLocation) } } + + fun navigation(activity: MainActivity, list: List) { + //获取右侧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) + } + } + } + } + + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultFragment.kt index eeac9c80..3e8a366b 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultFragment.kt @@ -61,10 +61,10 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener { if (id != null) { viewModel.loadData(id) } else { - viewModel.loadMetadata() + viewModel.initNewData() } } else { - viewModel.loadMetadata() + viewModel.initNewData() } // //监听大分类数据变化 diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt index dd1bef32..9f2cc68e 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt @@ -4,9 +4,8 @@ import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel 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.map.NIMapController import com.navinfo.omqs.db.RoomAppDatabase import dagger.hilt.android.lifecycle.HiltViewModel import io.realm.Realm @@ -46,8 +45,10 @@ class EvaluationResultViewModel @Inject constructor( var liveDataQsRecordBean = MutableLiveData() + var oldBean: QsRecordBean? = null + init { - liveDataQsRecordBean.value = QsRecordBean(id = UUID.randomUUID().toString(), classType = "89193") + liveDataQsRecordBean.value = QsRecordBean(id = UUID.randomUUID().toString()) Log.e("jingo", "EvaluationResultViewModel 创建了 ${hashCode()}") mapController.markerHandle.apply { setOnMapClickListener { @@ -69,7 +70,7 @@ class EvaluationResultViewModel @Inject constructor( /** * 查询数据库,获取问题分类 */ - fun loadMetadata() { + fun initNewData() { viewModelScope.launch(Dispatchers.IO) { getClassTypeList() getProblemLinkList() @@ -88,7 +89,6 @@ class EvaluationResultViewModel @Inject constructor( Log.e("jingo", "getClassTypeList S") viewModelScope.launch(Dispatchers.IO) { val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList() - Log.e("jingo", "getClassTypeList ${list?.size}") list?.let { if (list.isNotEmpty()) { //通知页面更新 @@ -110,6 +110,7 @@ class EvaluationResultViewModel @Inject constructor( * 获取问题环节列表和初步问题 */ fun getProblemLinkList() { + Log.e("jingo", "getProblemLinkList S") viewModelScope.launch(Dispatchers.IO) { val list = roomAppDatabase.getScRootCauseAnalysisDao().findAllData() list?.let { tl -> @@ -128,21 +129,26 @@ class EvaluationResultViewModel @Inject constructor( } if (liveDataQsRecordBean.value!!.problemLink.isEmpty()) { liveDataQsRecordBean.value!!.problemLink = middleList[0] + Log.e("jingo", "getProblemLinkList ${middleList[0]}") } if (liveDataQsRecordBean.value!!.cause.isEmpty()) { liveDataQsRecordBean.value!!.cause = rightList[0].text + Log.e("jingo", "getProblemLinkList ${rightList[0].text}") } + liveDataQsRecordBean.postValue(liveDataQsRecordBean.value) liveDataMiddleTypeList.postValue(middleList) liveDataRightTypeList.postValue(rightList) } } } + Log.e("jingo", "getProblemLinkList E") } /** * 获取问题类型列表和问题现象 */ private suspend fun getProblemList(classType: String) { + Log.e("jingo", "getProblemList S") val typeList = roomAppDatabase.getScProblemTypeDao().findProblemTypeList(classType) typeList?.let { tl -> if (tl.isNotEmpty()) { @@ -158,10 +164,20 @@ class EvaluationResultViewModel @Inject constructor( ) ) } + if (liveDataQsRecordBean.value!!.problemType.isEmpty()) { + liveDataQsRecordBean.value!!.problemType = typeTitleList[0] + Log.e("jingo", "getProblemList ${typeTitleList[0]}") + } liveDataMiddleTypeList.postValue(typeTitleList) + if (liveDataQsRecordBean.value!!.phenomenon.isEmpty()) { + liveDataQsRecordBean.value!!.phenomenon = phenomenonRightList[0].text + Log.e("jingo", "getProblemList ${phenomenonRightList[0].text}") + } + liveDataQsRecordBean.postValue(liveDataQsRecordBean.value) liveDataRightTypeList.postValue(phenomenonRightList) } } + Log.e("jingo", "getProblemList E") } /** @@ -179,45 +195,42 @@ class EvaluationResultViewModel @Inject constructor( fun setPhenomenonMiddleBean(adapterBean: RightBean) { liveDataQsRecordBean.value!!.phenomenon = adapterBean.text liveDataQsRecordBean.value!!.problemType = adapterBean.title + liveDataQsRecordBean.postValue(liveDataQsRecordBean.value) } fun setProblemLinkMiddleBean(adapterBean: RightBean) { liveDataQsRecordBean.value!!.cause = adapterBean.text liveDataQsRecordBean.value!!.problemLink = adapterBean.title - + liveDataQsRecordBean.postValue(liveDataQsRecordBean.value) } fun saveData() { viewModelScope.launch(Dispatchers.IO) { val realm = Realm.getDefaultInstance() + Log.e("jingo","realm hashCOde ${realm.hashCode()}") realm.executeTransaction { it.copyToRealmOrUpdate(liveDataQsRecordBean.value) } - realm.close() +// realm.close() mapController.layerManagerHandler.addOrUpdateQsRecordMark(liveDataQsRecordBean.value!!) liveDataFinish.postValue(true) } } fun deleteData() { -// 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() -// realm.executeTransaction { -// it.copyToRealmOrUpdate(qsRecord) -// } + 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.addOrUpdateQsRecordMark(qsRecord) -// liveDataFinish.postValue(true) -// } + mapController.layerManagerHandler.removeQsRecordMark(liveDataQsRecordBean.value!!) + liveDataFinish.postValue(true) + } } /** @@ -229,7 +242,8 @@ class EvaluationResultViewModel @Inject constructor( val objects = realm.where().equalTo("id", id).findFirst() if (objects != null) { - liveDataQsRecordBean.postValue(realm.copyFromRealm(objects)) + oldBean = realm.copyFromRealm(objects) + liveDataQsRecordBean.postValue(oldBean!!.copy()) } } } diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListAdapter.kt index 0800abce..08ebcae5 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListAdapter.kt @@ -10,6 +10,8 @@ import com.navinfo.omqs.R import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding import com.navinfo.omqs.bean.OfflineMapCityBean 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.BaseViewHolder import javax.inject.Inject @@ -31,11 +33,11 @@ class OfflineMapCityListAdapter( if (it.tag != null) { val cityBean = data[it.tag as Int] when (cityBean.status) { - OfflineMapCityBean.NONE, OfflineMapCityBean.UPDATE, OfflineMapCityBean.PAUSE, OfflineMapCityBean.ERROR -> { + FileDownloadStatus.NONE, FileDownloadStatus.UPDATE, FileDownloadStatus.PAUSE, FileDownloadStatus.ERROR -> { Log.e("jingo", "开始下载 ${cityBean.status}") downloadManager.start(cityBean.id) } - OfflineMapCityBean.LOADING, OfflineMapCityBean.WAITING -> { + FileDownloadStatus.LOADING, FileDownloadStatus.WAITING -> { Log.e("jingo", "暂停 ${cityBean.status}") downloadManager.pause(cityBean.id) } @@ -88,37 +90,37 @@ class OfflineMapCityListAdapter( binding.offlineMapProgress.progress = (cityBean.currentSize * 100 / cityBean.fileSize).toInt() when (cityBean.status) { - OfflineMapCityBean.NONE -> { + FileDownloadStatus.NONE -> { if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility = View.INVISIBLE binding.offlineMapDownloadBtn.text = "下载" } - OfflineMapCityBean.WAITING -> { + FileDownloadStatus.WAITING -> { if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility = View.VISIBLE binding.offlineMapDownloadBtn.text = "等待中" } - OfflineMapCityBean.LOADING -> { + FileDownloadStatus.LOADING -> { if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility = View.VISIBLE binding.offlineMapDownloadBtn.text = "暂停" } - OfflineMapCityBean.PAUSE -> { + FileDownloadStatus.PAUSE -> { if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility = View.VISIBLE binding.offlineMapDownloadBtn.text = "继续" } - OfflineMapCityBean.ERROR -> { + FileDownloadStatus.ERROR -> { if (binding.offlineMapProgress.visibility != View.VISIBLE) binding.offlineMapProgress.visibility = View.VISIBLE binding.offlineMapDownloadBtn.text = "重试" } - OfflineMapCityBean.DONE -> { + FileDownloadStatus.DONE -> { if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility = View.INVISIBLE binding.offlineMapDownloadBtn.text = "已完成" } - OfflineMapCityBean.UPDATE -> { + FileDownloadStatus.UPDATE -> { if (binding.offlineMapProgress.visibility == View.VISIBLE) binding.offlineMapProgress.visibility = View.INVISIBLE binding.offlineMapDownloadBtn.text = "更新" diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapFragment.kt index 9755b2e4..c04ceb9d 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapFragment.kt @@ -8,11 +8,12 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import com.google.android.material.tabs.TabLayoutMediator import com.navinfo.omqs.databinding.FragmentOfflineMapBinding +import com.navinfo.omqs.ui.fragment.BaseFragment /** * 离线地图总页面 */ -class OfflineMapFragment : Fragment() { +class OfflineMapFragment : BaseFragment() { private var _binding: FragmentOfflineMapBinding? = null diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt index b4d7f882..77e85f60 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt @@ -23,6 +23,7 @@ import com.navinfo.omqs.db.ImportOMDBHelper import com.navinfo.omqs.hilt.ImportOMDBHiltFactory import com.navinfo.omqs.tools.CoroutineUtils import com.navinfo.omqs.ui.activity.BaseActivity +import com.navinfo.omqs.ui.fragment.BaseFragment import dagger.hilt.android.AndroidEntryPoint import io.realm.Realm import io.realm.RealmDictionary @@ -38,12 +39,13 @@ import javax.inject.Inject * 个人中心 */ @AndroidEntryPoint -class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { +class PersonalCenterFragment : BaseFragment(), FSAFActivityCallbacks { private var _binding: FragmentPersonalCenterBinding? = null private val binding get() = _binding!! private val fileChooser by lazy { FileChooser(requireContext()) } private val viewModel by lazy { viewModels().value } + @Inject lateinit var importOMDBHiltFactory: ImportOMDBHiltFactory @@ -61,9 +63,9 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { binding.root.setNavigationItemSelectedListener { when (it.itemId) { 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文件 - fileChooser.openChooseFileDialog(object: FileChooserCallback() { + fileChooser.openChooseFileDialog(object : FileChooserCallback() { override fun onCancel(reason: String) { } @@ -71,31 +73,47 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { val file = UriUtils.uri2File(uri) // 开始导入数据 // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - val job = CoroutineUtils.launchWithLoading(requireContext(), loadingMessage = "生成数据...") { - val importOMDBHelper: ImportOMDBHelper = importOMDBHiltFactory.obtainImportOMDBHelper(requireContext(), file, File(file.parentFile, "config.json")) + val job = CoroutineUtils.launchWithLoading( + requireContext(), + loadingMessage = "生成数据..." + ) { + val importOMDBHelper: ImportOMDBHelper = + importOMDBHiltFactory.obtainImportOMDBHelper( + requireContext(), + file, + File(file.parentFile, "config.json") + ) viewModel.obtainOMDBZipData(importOMDBHelper) } } }) } R.id.personal_center_menu_import_data -> { // 导入zip数据 - fileChooser.openChooseFileDialog(object: FileChooserCallback() { + fileChooser.openChooseFileDialog(object : FileChooserCallback() { override fun onCancel(reason: String) { } override fun onResult(uri: Uri) { val file = UriUtils.uri2File(uri) // 开始导入数据 - CoroutineUtils.launchWithLoading(requireContext(), loadingMessage = "导入数据...") { - val importOMDBHelper: ImportOMDBHelper = importOMDBHiltFactory.obtainImportOMDBHelper(requireContext(), file, File(file.parentFile, "config.json")) + CoroutineUtils.launchWithLoading( + requireContext(), + loadingMessage = "导入数据..." + ) { + val importOMDBHelper: ImportOMDBHelper = + importOMDBHiltFactory.obtainImportOMDBHelper( + requireContext(), + file, + File(file.parentFile, "config.json") + ) 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) { } @@ -108,6 +126,9 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { R.id.personal_center_menu_test -> { viewModel.readRealmData() } + R.id.personal_center_menu_task_list -> { + findNavController().navigate(R.id.TaskListFragment) + } } true } diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListAdapter.kt new file mode 100644 index 00000000..8c03439a --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListAdapter.kt @@ -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() { + + + 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 { + 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 + } +} + + diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListFragment.kt new file mode 100644 index 00000000..682318cf --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListFragment.kt @@ -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() + 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 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListViewModel.kt new file mode 100644 index 00000000..3aab833b --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListViewModel.kt @@ -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>() + + 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() + } + + } + +} diff --git a/app/src/main/java/com/navinfo/omqs/ui/widget/MyEditeText.kt b/app/src/main/java/com/navinfo/omqs/ui/widget/MyEditeText.kt new file mode 100644 index 00000000..3d6d85cf --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/widget/MyEditeText.kt @@ -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) + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_task_list.xml b/app/src/main/res/layout/adapter_task_list.xml new file mode 100644 index 00000000..e40e1db4 --- /dev/null +++ b/app/src/main/res/layout/adapter_task_list.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_evaluation_result.xml b/app/src/main/res/layout/fragment_evaluation_result.xml index dca0534c..d5abcfde 100644 --- a/app/src/main/res/layout/fragment_evaluation_result.xml +++ b/app/src/main/res/layout/fragment_evaluation_result.xml @@ -59,7 +59,7 @@ + + diff --git a/app/src/main/res/layout/fragment_offline_map_city_list.xml b/app/src/main/res/layout/fragment_offline_map_city_list.xml index 930bd830..3df96142 100644 --- a/app/src/main/res/layout/fragment_offline_map_city_list.xml +++ b/app/src/main/res/layout/fragment_offline_map_city_list.xml @@ -17,8 +17,10 @@ + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/offline_map_search" + app:layout_constraintVertical_bias="0.0" + tools:layout_editor_absoluteX="0dp" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_task_list.xml b/app/src/main/res/layout/fragment_task_list.xml new file mode 100644 index 00000000..fbd4259d --- /dev/null +++ b/app/src/main/res/layout/fragment_task_list.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/personal_center_menu.xml b/app/src/main/res/menu/personal_center_menu.xml index 3dd10a72..c86cf5a5 100644 --- a/app/src/main/res/menu/personal_center_menu.xml +++ b/app/src/main/res/menu/personal_center_menu.xml @@ -32,6 +32,10 @@ android:checkableBehavior="single"> + - + + app:destination="@id/OfflineMapFragment" /> - + + + \ No newline at end of file diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/QsRecordBean.kt b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/QsRecordBean.kt index 30491286..58d4bb8a 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/QsRecordBean.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/QsRecordBean.kt @@ -4,6 +4,7 @@ import com.navinfo.collect.library.utils.GeometryToolsKt import io.realm.RealmObject import io.realm.RealmSet import io.realm.annotations.PrimaryKey +import io.realm.annotations.RealmClass /** @@ -88,6 +89,27 @@ open class QsRecordBean @JvmOverloads constructor( ) : 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() // x方向的tile编码 private val tileY = RealmSet() // y方向的tile编码 diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt index ac76de66..bf3395ad 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt @@ -4,13 +4,13 @@ import android.content.Context import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.Color +import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.core.content.res.ResourcesCompat import androidx.lifecycle.lifecycleScope import com.navinfo.collect.library.R import com.navinfo.collect.library.data.entity.QsRecordBean import com.navinfo.collect.library.map.NIMapView -import com.navinfo.collect.library.map.NIMapView.LAYER_GROUPS import com.navinfo.collect.library.map.cluster.ClusterMarkerItem import com.navinfo.collect.library.map.cluster.ClusterMarkerRenderer import com.navinfo.collect.library.map.layers.MyItemizedLayer @@ -32,17 +32,19 @@ import org.oscim.backend.canvas.Bitmap import org.oscim.backend.canvas.Paint import org.oscim.core.GeoPoint import org.oscim.layers.GroupLayer -import org.oscim.layers.marker.* +import org.oscim.layers.marker.MarkerInterface +import org.oscim.layers.marker.MarkerItem +import org.oscim.layers.marker.MarkerRendererFactory +import org.oscim.layers.marker.MarkerSymbol import org.oscim.layers.tile.buildings.BuildingLayer import org.oscim.layers.tile.vector.VectorTileLayer import org.oscim.layers.tile.vector.labeling.LabelLayer -import org.oscim.map.Map.UpdateListener import org.oscim.layers.tile.vector.labeling.LabelTileLoaderHook +import org.oscim.map.Map.UpdateListener import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory import org.oscim.tiling.source.mapfile.MapFileTileSource import java.io.File import java.util.* -import java.util.stream.Collectors /** * Layer 操作 @@ -196,17 +198,19 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : withContext(Dispatchers.Main) { mMapView.updateMap(true) } + } + /** * 删除marker */ - suspend fun deleteQsRecordMark(data: QsRecordBean) { + suspend fun removeQsRecordMark(data: QsRecordBean) { for (item in itemizedLayer.itemList) { if (item is MarkerItem) { if (item.title == data.id) { itemizedLayer.itemList.remove(item) - mMapView.updateMap() + itemizedLayer.populate() return } } @@ -285,11 +289,12 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : mContext.lifecycleScope.launch(Dispatchers.IO) { var list = mutableListOf() val realm = Realm.getDefaultInstance() + Log.e("jingo","realm hashCOde ${realm.hashCode()}") realm.executeTransaction { val objects = realm.where().findAll() list = realm.copyFromRealm(objects) } - realm.close() +// realm.close() for (item in list) { createMarkerItem(item) @@ -359,11 +364,7 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : } } } - withContext(Dispatchers.Main) { - itemizedLayer.update() - } - -// itemizedLayer.populate() + itemizedLayer.populate() } @@ -583,7 +584,8 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : mapLifeNiLocationTileSource = MapLifeNiLocationTileSource(mContext, dbName) } if (vectorNiLocationTileLayer == null) { - vectorNiLocationTileLayer = VectorTileLayer(mMapView.vtmMap, mapLifeNiLocationTileSource) + vectorNiLocationTileLayer = + VectorTileLayer(mMapView.vtmMap, mapLifeNiLocationTileSource) } if (labelNiLocationLayer == null) { labelNiLocationLayer = @@ -596,6 +598,7 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) : fun hideNiLocationLayer() { removeLayer(labelNiLocationLayer) } + } interface OnQsRecordItemClickListener { From b5a3d72107af5a6d641d77c68fcc6c9b40379ca7 Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Sun, 23 Apr 2023 16:42:57 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/navinfo/omqs/OMQSApplication.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt index cfaf898c..1531a3d9 100644 --- a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt +++ b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt @@ -2,9 +2,7 @@ package com.navinfo.omqs import android.app.Application import android.util.Log -import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase import com.navinfo.omqs.db.MyRealmModule -import com.navinfo.omqs.db.TraceDataBase import com.navinfo.omqs.tools.FileManager import com.navinfo.omqs.ui.manager.TakePhotoManager import com.navinfo.omqs.util.NetUtils