增加realm 在离线地图中的使用

This commit is contained in:
squallzhjch
2023-04-06 10:46:19 +08:00
parent dbb1572688
commit fa4ad254a5
29 changed files with 422 additions and 384 deletions

View File

@@ -3,15 +3,9 @@ package com.navinfo.omqs.ui
import android.content.Intent
import android.os.Bundle
import androidx.core.view.WindowCompat
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import android.view.Menu
import android.view.MenuItem
import com.github.k1rakishou.fsaf.FileChooser
import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.ActivityMainBinding
import com.navinfo.omqs.ui.activity.PermissionsActivity

View File

@@ -13,10 +13,13 @@ import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.ActivityLoginBinding
import com.navinfo.omqs.ui.activity.PermissionsActivity
import com.navinfo.omqs.ui.activity.map.MainActivity
import dagger.hilt.android.AndroidEntryPoint
/**
* 登陆页面
*/
@AndroidEntryPoint
class LoginActivity : PermissionsActivity() {
private lateinit var binding: ActivityLoginBinding
@@ -65,6 +68,9 @@ class LoginActivity : PermissionsActivity() {
loginDialog?.dismiss()
loginDialog = null
}
LoginStatus.LOGIN_STATUS_NET_OFFLINE_MAP -> {
loginDialog("检查离线地图...")
}
}
}

View File

@@ -5,17 +5,17 @@ import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.navinfo.omqs.Constant
import com.navinfo.omqs.bean.LoginUserBean
import io.realm.Realm
import io.realm.RealmConfiguration
import com.navinfo.omqs.http.NetResult
import com.navinfo.omqs.http.NetworkService
import com.navinfo.omqs.tools.FileManager
import com.navinfo.omqs.tools.RealmCoroutineScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import okio.IOException
import java.io.File
import java.math.BigInteger
import javax.inject.Inject
enum class LoginStatus {
/**
@@ -23,6 +23,11 @@ enum class LoginStatus {
*/
LOGIN_STATUS_NET_LOADING,
/**
* 访问离线地图列表
*/
LOGIN_STATUS_NET_OFFLINE_MAP,
/**
* 初始化文件夹
*/
@@ -49,7 +54,10 @@ enum class LoginStatus {
LOGIN_STATUS_CANCEL,
}
class LoginViewModel(
@HiltViewModel
class LoginViewModel @Inject constructor(
private val networkService: NetworkService,
private val realmManager: RealmCoroutineScope
) : ViewModel() {
//用户信息
val loginUser: MutableLiveData<LoginUserBean> = MutableLiveData()
@@ -63,17 +71,6 @@ class LoginViewModel(
loginUser.value = LoginUserBean(username = "admin", password = "123456")
}
private fun initRealm() {
val password = "password".encodeToByteArray().copyInto(ByteArray(64))
// 1110000011000010111001101110011011101110110111101110010011001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Log.d("", "密码是: ${BigInteger(1, password).toString(2).padStart(64, '0')}")
val config = RealmConfiguration.Builder()
.directory(File(Constant.DATA_PATH))
.name("HDData")
// .encryptionKey(password)
.build()
Constant.realm = Realm.getInstance(config)
}
/**
* 处理注册按钮
@@ -113,46 +110,56 @@ class LoginViewModel(
//文件夹初始化
try {
loginStatus.postValue(LoginStatus.LOGIN_STATUS_FOLDER_INIT)
createRootFolder(context)
createUserFolder(context)
// 初始化Realm
initRealm()
} catch (e: IOException) {
loginStatus.postValue(LoginStatus.LOGIN_STATUS_FOLDER_FAILURE)
}
//假装解压文件等
delay(1000)
loginStatus.postValue(LoginStatus.LOGIN_STATUS_SUCCESS)
loginStatus.postValue(LoginStatus.LOGIN_STATUS_NET_OFFLINE_MAP)
when (val result = networkService.getOfflineMapCityList()) {
is NetResult.Success -> {
// }
if (result.data != null) {
for (cityBean in result.data) {
FileManager.checkOfflineMapFileInfo(cityBean)
}
realmManager.launch {
realmManager.insertOrUpdate(result.data)
}
}
}
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()
}
}
NetResult.Loading -> {}
}
loginStatus.postValue(LoginStatus.LOGIN_STATUS_SUCCESS)
}
/**
* 创建用户目录
*/
@Throws(IOException::class)
private fun createRootFolder(context: Context) {
// 在SD卡创建项目目录
val sdCardPath = context.getExternalFilesDir(null)
sdCardPath?.let {
Constant.ROOT_PATH = sdCardPath.absolutePath
Constant.MAP_PATH = Constant.ROOT_PATH + "/map/"
Constant.OFFLINE_MAP_PATH = Constant.MAP_PATH + "offline/"
val file = File(Constant.MAP_PATH)
if (!file.exists()) {
file.mkdirs()
Constant.DATA_PATH = Constant.ROOT_PATH + "/data/"
with(File(Constant.MAP_PATH)) {
if(!this.exists()) this.mkdirs()
}
with(File(Constant.DATA_PATH)) {
if(!this.exists()) this.mkdirs()
}
}
private fun createUserFolder(context: Context) {
// 在SD卡创建用户目录,解压资源等
}
/**
* 取消登录
*/
fun cancelLogin() {
Log.e("jingo", "取消了?${Thread.currentThread().name}")
jobLogin?.let {
it.cancel()
loginStatus.value = LoginStatus.LOGIN_STATUS_CANCEL
@@ -163,6 +170,4 @@ class LoginViewModel(
super.onCleared()
cancelLogin()
}
}

View File

@@ -69,7 +69,6 @@ class MainActivity : BaseActivity() {
super.onDestroy()
mapController.mMapView.onDestroy()
mapController.locationLayerHandler.stopLocation()
Log.e("jingo", "MainActivity 销毁")
}
override fun onResume() {

View File

@@ -25,7 +25,6 @@ class MainViewModel @Inject constructor(
}
override fun onCleared() {
Log.e("jingo","MainViewModel 被释放了")
super.onCleared()
}
}

View File

@@ -6,8 +6,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
@@ -32,14 +32,16 @@ class OfflineMapCityListAdapter @Inject constructor(
val cityBean = data[it.tag as Int]
when (cityBean.status) {
OfflineMapCityBean.NONE, OfflineMapCityBean.UPDATE, OfflineMapCityBean.PAUSE, OfflineMapCityBean.ERROR -> {
Log.e("jingo", "开始下载 ${cityBean.status}")
downloadManager.start(cityBean.id)
}
OfflineMapCityBean.LOADING, OfflineMapCityBean.WAITING -> {
Log.e("jingo", "暂停 ${cityBean.status}")
downloadManager.pause(cityBean.id)
}
// OfflineMapCityBean.WAITING->{
// downloadManager.cancel(cityBean.id)
// }
else -> {
Log.e("jingo", "暂停 ${cityBean.status}")
}
}
}
}
@@ -50,24 +52,38 @@ class OfflineMapCityListAdapter @Inject constructor(
return BaseViewHolder(viewBinding)
}
override fun onViewRecycled(holder: BaseViewHolder) {
super.onViewRecycled(holder)
//页面滑动时会用holder重构页面但是对进度条的监听回调会一直返回扰乱UI所以当当前holder去重构的时候移除监听
downloadManager.removeObserver(holder.tag)
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val binding: AdapterOfflineMapCityBinding =
holder.viewBinding as AdapterOfflineMapCityBinding
//牺牲性能立刻刷新UI解决闪烁 这里不用
// binding.executePendingBindings()
val cityBean = data[position]
//tag 方便onclick里拿到数据
holder.tag = cityBean.id
changeViews(binding, cityBean)
downloadManager.addTask(cityBean)
downloadManager.observer(cityBean.id, holder, DownloadObserver(cityBean.id, binding))
binding.offlineMapDownloadBtn.tag = position
binding.offlineMapDownloadBtn.setOnClickListener(downloadBtnClick)
binding.offlineMapCityName.text = cityBean.name
binding.offlineMapCitySize.text = cityBean.getFileSizeText()
downloadManager.addTask(cityBean)
changeViews(binding, cityBean)
downloadManager.observer(cityBean.id, holder) {
if (cityBean.id == it.id)
changeViews(binding, it)
}
inner class DownloadObserver(val id: String, val binding: AdapterOfflineMapCityBinding) :
Observer<OfflineMapCityBean> {
override fun onChanged(t: OfflineMapCityBean?) {
if (id == t?.id)
changeViews(binding, t)
}
}
private fun changeViews(binding: AdapterOfflineMapCityBinding, cityBean: OfflineMapCityBean) {
binding.offlineMapProgress.progress =
(cityBean.currentSize * 100 / cityBean.fileSize).toInt()

View File

@@ -57,6 +57,5 @@ class OfflineMapCityListFragment : Fragment() {
override fun onDestroyView() {
super.onDestroyView()
_binding = null
Log.e("jingo", "OfflineMapCityListFragment onDestroyView")
}
}

View File

@@ -1,16 +1,18 @@
package com.navinfo.omqs.ui.fragment.offlinemap
import android.app.Application
import android.content.Context
import android.widget.Toast
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.navinfo.omqs.http.NetResult
import com.navinfo.omqs.http.NetworkService
import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
import com.navinfo.omqs.tools.FileManager
import com.navinfo.omqs.tools.RealmCoroutineScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import io.realm.Realm
import io.realm.Sort
import io.realm.kotlin.where
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -19,8 +21,7 @@ import javax.inject.Inject
*/
@HiltViewModel
class OfflineMapCityListViewModel @Inject constructor(
private val networkService: NetworkService,
@ApplicationContext val context: Context
@ApplicationContext val context: Context,
) : ViewModel() {
val cityListLiveData = MutableLiveData<List<OfflineMapCityBean>>()
@@ -29,21 +30,15 @@ class OfflineMapCityListViewModel @Inject constructor(
* 去获取离线地图列表
*/
fun getCityList() {
viewModelScope.launch {
when (val result = networkService.getOfflineMapCityList()) {
is NetResult.Success -> {
cityListLiveData.postValue(result.data?.sortedBy { bean -> bean.id })
}
is NetResult.Error -> {
Toast.makeText(context, "${result.exception.message}", Toast.LENGTH_SHORT)
.show()
}
is NetResult.Failure -> {
Toast.makeText(context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT)
.show()
}
NetResult.Loading -> {}
viewModelScope.launch(Dispatchers.IO) {
val realm = Realm.getDefaultInstance()
val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
val list = realm.copyFromRealm(objects)
realm.close()
for (item in list) {
FileManager.checkOfflineMapFileInfo(item)
}
cityListLiveData.postValue(list)
}
}
}

View File

@@ -61,6 +61,5 @@ class OfflineMapFragment : Fragment() {
override fun onDestroyView() {
super.onDestroyView()
_binding = null
Log.e("jingo","OfflineMapFragment onDestroyView")
}
}

View File

@@ -33,6 +33,5 @@ class OfflineMapStateListFragment : Fragment() {
override fun onDestroyView() {
super.onDestroyView()
_binding = null
Log.e("jingo","OfflineMapStateListFragment onDestroyView")
}
}

View File

@@ -3,21 +3,16 @@ package com.navinfo.omqs.ui.fragment.personalcenter
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.viewModels
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.get
import androidx.navigation.fragment.findNavController
import com.blankj.utilcode.util.UriUtils
import com.github.k1rakishou.fsaf.FileChooser
import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks
import com.github.k1rakishou.fsaf.callback.FileChooserCallback
import com.google.android.material.snackbar.Snackbar
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.FragmentPersonalCenterBinding
@@ -42,7 +37,6 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.e("jingo", "NIMapController PersonalCenterFragment onViewCreated")
binding.root.setNavigationItemSelectedListener {
when (it.itemId) {
R.id.personal_center_menu_offline_map ->

View File

@@ -14,6 +14,7 @@ import androidx.viewbinding.ViewBinding
open class BaseViewHolder(val viewBinding: ViewBinding) :
RecyclerView.ViewHolder(viewBinding.root), LifecycleOwner {
private val lifecycleRegistry = LifecycleRegistry(this)
var tag = ""
init {
// dataBinding.lifecycleOwner = this

View File

@@ -62,9 +62,10 @@ class MyProgressBar : ProgressBar {
// int x = (getWidth()/2) - rect.centerX();
// int y = (getHeight()/2) - rect.centerY();
var x = (width * rate).toInt()
if (x == width) {
val dx = width - rect.right
if (x > dx) {
// 如果为百分之百则在左边绘制。
x = width - rect.right
x = dx
}
mPaint.textSize = 24f
val y: Int = 10 - rect.top