diff --git a/app/src/main/java/com/navinfo/volvo/MyApplication.kt b/app/src/main/java/com/navinfo/volvo/MyApplication.kt index 05e3780..d076fd5 100644 --- a/app/src/main/java/com/navinfo/volvo/MyApplication.kt +++ b/app/src/main/java/com/navinfo/volvo/MyApplication.kt @@ -5,7 +5,4 @@ import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp open class MyApplication : Application() { - override fun onCreate() { - super.onCreate() - } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/database/dao/GreetingMessageDao.kt b/app/src/main/java/com/navinfo/volvo/database/dao/GreetingMessageDao.kt index ccae7c7..5d87e0c 100644 --- a/app/src/main/java/com/navinfo/volvo/database/dao/GreetingMessageDao.kt +++ b/app/src/main/java/com/navinfo/volvo/database/dao/GreetingMessageDao.kt @@ -1,27 +1,42 @@ package com.navinfo.volvo.database.dao import androidx.paging.PagingSource -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query +import androidx.room.* import com.navinfo.volvo.database.entity.GreetingMessage import kotlinx.coroutines.flow.Flow @Dao interface GreetingMessageDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insert(vararg check: GreetingMessage) - @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insert(list: List) + @Insert + fun insert(message: GreetingMessage): Long - @Query("SELECT * FROM GreetingMessage where id =:id") - fun findCheckManagerById(id: Long): GreetingMessage? + @Update(onConflict = OnConflictStrategy.REPLACE) + fun update(message: GreetingMessage) - @Query("SELECT * FROM GreetingMessage") - fun findAllByFlow(): Flow> + @Query("SELECT count(id) FROM GreetingMessage WHERE read = 0") + fun countUnreadByFlow(): Flow + + /** + * 分页查询 + */ @Query("SELECT * FROM GreetingMessage") fun findAllByDataSource(): PagingSource + + /** + * 检查某条数据是否存在 + */ + @Query("SELECT id From GreetingMessage WHERE id = :id LIMIT 1") + fun getMessageId(id: Long): Long + + @Transaction + suspend fun insertOrUpdate(list: List) { + for (message in list) { + val id = getMessageId(message.id) + if (id == 0L) { + insert(message) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/database/entity/GreetingMessage.kt b/app/src/main/java/com/navinfo/volvo/database/entity/GreetingMessage.kt index cf1841f..4bca705 100644 --- a/app/src/main/java/com/navinfo/volvo/database/entity/GreetingMessage.kt +++ b/app/src/main/java/com/navinfo/volvo/database/entity/GreetingMessage.kt @@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull @TypeConverters(AttachmentConverters::class) data class GreetingMessage @JvmOverloads constructor( @PrimaryKey(autoGenerate = true) - var uuid:Long = 0, + var uuid: Long = 0, var id: Long = 0, var searchValue: String? = "", var createBy: String? = "", @@ -41,5 +41,6 @@ data class GreetingMessage @JvmOverloads constructor( /** * 附件列表 */ - var attachment: MutableList = mutableListOf() + var attachment: MutableList = mutableListOf(), + var read: Boolean = false, ) diff --git a/app/src/main/java/com/navinfo/volvo/di/module/ViewModelModule.kt b/app/src/main/java/com/navinfo/volvo/di/module/ViewModelModule.kt index 36cea4c..ec45c18 100644 --- a/app/src/main/java/com/navinfo/volvo/di/module/ViewModelModule.kt +++ b/app/src/main/java/com/navinfo/volvo/di/module/ViewModelModule.kt @@ -3,6 +3,7 @@ package com.navinfo.volvo.di.module import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.navinfo.volvo.di.key.ViewModelKey +import com.navinfo.volvo.ui.MainActivityViewModel import com.navinfo.volvo.ui.fragments.home.HomeViewModel import com.navinfo.volvo.ui.fragments.login.LoginViewModel import com.navinfo.volvo.ui.fragments.message.ObtainMessageViewModel @@ -19,6 +20,11 @@ abstract class ViewModelModule { @Binds abstract fun bindViewModelFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory + @IntoMap + @Binds + @ViewModelKey(MainActivityViewModel::class) + abstract fun bindMainViewModel(viewModel: MainActivityViewModel): ViewModel + @IntoMap @Binds @ViewModelKey(LoginViewModel::class) @@ -33,4 +39,6 @@ abstract class ViewModelModule { @Binds @ViewModelKey(ObtainMessageViewModel::class) abstract fun bindObtainMessageFragmentViewModel(viewModel: ObtainMessageViewModel): ViewModel + + } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/repository/database/DatabaseRepositoryImp.kt b/app/src/main/java/com/navinfo/volvo/repository/database/DatabaseRepositoryImp.kt index 77948d0..fcbba0d 100644 --- a/app/src/main/java/com/navinfo/volvo/repository/database/DatabaseRepositoryImp.kt +++ b/app/src/main/java/com/navinfo/volvo/repository/database/DatabaseRepositoryImp.kt @@ -3,13 +3,15 @@ package com.navinfo.volvo.repository.database import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.PagingData +import com.navinfo.volvo.database.AppDatabase import com.navinfo.volvo.database.dao.GreetingMessageDao import com.navinfo.volvo.database.entity.GreetingMessage import kotlinx.coroutines.flow.Flow import javax.inject.Inject class DatabaseRepositoryImp @Inject constructor( - private val messageDao: GreetingMessageDao + private val messageDao: GreetingMessageDao, + private val database: AppDatabase ) : DatabaseRepository { companion object { const val PAGE_SIZE = 20 @@ -20,4 +22,5 @@ class DatabaseRepositoryImp @Inject constructor( messageDao.findAllByDataSource() }.flow } + } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/repository/network/NetworkRepositoryImp.kt b/app/src/main/java/com/navinfo/volvo/repository/network/NetworkRepositoryImp.kt index bbdea93..5fd1e2f 100644 --- a/app/src/main/java/com/navinfo/volvo/repository/network/NetworkRepositoryImp.kt +++ b/app/src/main/java/com/navinfo/volvo/repository/network/NetworkRepositoryImp.kt @@ -28,7 +28,9 @@ class NetworkRepositoryImp @Inject constructor( val result = netWorkService.queryCardListByApp(stringBody) if (result.isSuccessful) { val body = result.body() - messageDao.insert(body!!.data!!.rows) + if(body!!.data != null && body.data!!.rows != null){ + messageDao.insertOrUpdate(body.data!!.rows) + } NetResult.Success(body) } else { NetResult.Success(null) diff --git a/app/src/main/java/com/navinfo/volvo/ui/BaseActivity.kt b/app/src/main/java/com/navinfo/volvo/ui/BaseActivity.kt new file mode 100644 index 0000000..77c1577 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/ui/BaseActivity.kt @@ -0,0 +1,11 @@ +package com.navinfo.volvo.ui + +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import javax.inject.Inject + +abstract class BaseActivity : AppCompatActivity() { + @Inject + lateinit var viewModelFactoryProvider: ViewModelProvider.Factory +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/ui/MainActivity.kt b/app/src/main/java/com/navinfo/volvo/ui/MainActivity.kt index 24889ba..276c772 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/MainActivity.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/MainActivity.kt @@ -4,7 +4,11 @@ import android.content.DialogInterface import android.os.Bundle import android.view.View import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.viewModelScope import androidx.navigation.findNavController import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupActionBarWithNavController @@ -30,18 +34,23 @@ import com.navinfo.volvo.R import com.navinfo.volvo.databinding.ActivityMainBinding import com.navinfo.volvo.utils.SystemConstant import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch +import javax.inject.Inject @AndroidEntryPoint -class MainActivity : AppCompatActivity() { +class MainActivity : BaseActivity() { private lateinit var binding: ActivityMainBinding + private val viewModel by viewModels { viewModelFactoryProvider } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) - setupNavigation() + XXPermissions.with(this) // 申请单个权限 @@ -61,6 +70,7 @@ class MainActivity : AppCompatActivity() { } // 在SD卡创建项目目录 createRootFolder() + setupNavigation() } override fun onDenied(permissions: MutableList, never: Boolean) { @@ -89,6 +99,20 @@ class MainActivity : AppCompatActivity() { ) setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) + + lifecycleScope.launch{ + viewModel.getUnreadCount().collect { + runOnUiThread{ + if(it == 0L){ + navView.removeBadge(R.id.navigation_home) + }else{ + var badge = navView.getOrCreateBadge(R.id.navigation_home); + badge.number = it.toInt() + } + } + } + } + navController.addOnDestinationChangedListener { controller, destination, arguments -> if (destination.id == R.id.navigation_home || destination.id == R.id.navigation_dashboard diff --git a/app/src/main/java/com/navinfo/volvo/ui/MainActivityViewModel.kt b/app/src/main/java/com/navinfo/volvo/ui/MainActivityViewModel.kt new file mode 100644 index 0000000..b0ffafe --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/ui/MainActivityViewModel.kt @@ -0,0 +1,17 @@ +package com.navinfo.volvo.ui + +import androidx.lifecycle.ViewModel +import androidx.paging.PagingData +import com.navinfo.volvo.database.dao.GreetingMessageDao +import com.navinfo.volvo.database.entity.GreetingMessage +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class MainActivityViewModel @Inject constructor( + private val messageDao: GreetingMessageDao, +) : ViewModel() { + + + fun getUnreadCount(): Flow = messageDao.countUnreadByFlow() + +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/ui/BaseFragment.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/BaseFragment.kt similarity index 85% rename from app/src/main/java/com/navinfo/volvo/ui/BaseFragment.kt rename to app/src/main/java/com/navinfo/volvo/ui/fragments/BaseFragment.kt index bf288d6..b112973 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/BaseFragment.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/BaseFragment.kt @@ -1,4 +1,4 @@ -package com.navinfo.volvo.ui +package com.navinfo.volvo.ui.fragments import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider diff --git a/app/src/main/java/com/navinfo/volvo/ui/fragments/home/HomeFragment.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/home/HomeFragment.kt index cd5cfe2..d78a6e7 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/fragments/home/HomeFragment.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/home/HomeFragment.kt @@ -12,7 +12,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.navinfo.volvo.R import com.navinfo.volvo.databinding.FragmentHomeBinding import com.navinfo.volvo.tools.DisplayUtil -import com.navinfo.volvo.ui.BaseFragment +import com.navinfo.volvo.ui.fragments.BaseFragment import com.yanzhenjie.recyclerview.* import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest @@ -21,27 +21,30 @@ import kotlinx.coroutines.launch @AndroidEntryPoint class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListener { + private var _binding: FragmentHomeBinding? = null + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + private val viewModel by viewModels { viewModelFactoryProvider } private lateinit var messageAdapter: HomeAdapter - private lateinit var mDataBinding: FragmentHomeBinding override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - mDataBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false) - mDataBinding.lifecycleOwner = this + _binding = FragmentHomeBinding.inflate(inflater, container, false) + val root: View = binding.root initView() - return mDataBinding.root + return root } - private fun initView() { - mDataBinding.homeViewModel = viewModel +// mDataBinding.homeViewModel = viewModel messageAdapter = HomeAdapter(this) - val recyclerview: SwipeRecyclerView = mDataBinding.homeRecyclerview + val recyclerview: SwipeRecyclerView = binding.homeRecyclerview recyclerview.adapter = null //先设置null,否则会报错 //创建菜单选项 //注意:使用滑动菜单不能开启滑动删除,否则只有滑动删除没有滑动菜单 @@ -96,6 +99,7 @@ class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListene override fun onDestroyView() { super.onDestroyView() + _binding = null } override fun onItemClick(view: View?, adapterPosition: Int) { diff --git a/app/src/main/java/com/navinfo/volvo/ui/fragments/login/LoginFragment.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/login/LoginFragment.kt index 35250a0..ae95127 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/fragments/login/LoginFragment.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/login/LoginFragment.kt @@ -4,14 +4,11 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels -import androidx.navigation.Navigation -import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController import com.navinfo.volvo.R import com.navinfo.volvo.databinding.FragmentLoginBinding -import com.navinfo.volvo.ui.BaseFragment +import com.navinfo.volvo.ui.fragments.BaseFragment import dagger.hilt.android.AndroidEntryPoint diff --git a/app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageViewModel.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageViewModel.kt index 863132d..82dc8a3 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageViewModel.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageViewModel.kt @@ -13,9 +13,10 @@ import okhttp3.MultipartBody import okhttp3.RequestBody import java.io.File import java.util.* +import javax.inject.Inject -class ObtainMessageViewModel: ViewModel() { +class ObtainMessageViewModel @Inject constructor() : ViewModel() { private val msgLiveData: MutableLiveData by lazy { MutableLiveData() } @@ -40,7 +41,7 @@ class ObtainMessageViewModel: ViewModel() { for (attachment in this.msgLiveData.value!!.attachment) { if (attachment.attachmentType == AttachmentType.PIC) { - if (picUrl==null||picUrl.isEmpty()) { + if (picUrl == null || picUrl.isEmpty()) { this.msgLiveData.value!!.attachment.remove(attachment) } else { attachment.pathUrl = picUrl @@ -48,8 +49,14 @@ class ObtainMessageViewModel: ViewModel() { hasPic = true } } - if (!hasPic&&picUrl!=null) { - this.msgLiveData.value!!.attachment.add(Attachment(UUID.randomUUID().toString(), picUrl, AttachmentType.PIC)) + if (!hasPic && picUrl != null) { + this.msgLiveData.value!!.attachment.add( + Attachment( + UUID.randomUUID().toString(), + picUrl, + AttachmentType.PIC + ) + ) } this.msgLiveData.postValue(this.msgLiveData.value) } @@ -59,7 +66,7 @@ class ObtainMessageViewModel: ViewModel() { var hasAudio = false for (attachment in this.msgLiveData.value!!.attachment) { if (attachment.attachmentType == AttachmentType.AUDIO) { - if (audioUrl==null||audioUrl.isEmpty()) { + if (audioUrl == null || audioUrl.isEmpty()) { this.msgLiveData.value!!.attachment.remove(attachment) } else { attachment.pathUrl = audioUrl @@ -67,8 +74,14 @@ class ObtainMessageViewModel: ViewModel() { hasAudio = true } } - if (!hasAudio&&audioUrl!=null) { - this.msgLiveData.value!!.attachment.add(Attachment(UUID.randomUUID().toString(), audioUrl, AttachmentType.AUDIO)) + if (!hasAudio && audioUrl != null) { + this.msgLiveData.value!!.attachment.add( + Attachment( + UUID.randomUUID().toString(), + audioUrl, + AttachmentType.AUDIO + ) + ) } this.msgLiveData.postValue(this.msgLiveData.value) } @@ -97,7 +110,11 @@ class ObtainMessageViewModel: ViewModel() { try { val requestFile: RequestBody = RequestBody.create("multipart/form-data".toMediaTypeOrNull(), attachmentFile) - val body = MultipartBody.Part.createFormData("picture", attachmentFile.getName(), requestFile) + val body = MultipartBody.Part.createFormData( + "picture", + attachmentFile.getName(), + requestFile + ) val result = NavinfoVolvoCall.getApi().uploadAttachment(body) XLog.d(result.code) if (result.code == 200) { // 请求成功 diff --git a/app/src/main/res/drawable/shape_circular.xml b/app/src/main/res/drawable/shape_circular.xml new file mode 100644 index 0000000..dcbbd79 --- /dev/null +++ b/app/src/main/res/drawable/shape_circular.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_home.xml b/app/src/main/res/layout/adapter_home.xml index 78e7b4e..7a24c31 100644 --- a/app/src/main/res/layout/adapter_home.xml +++ b/app/src/main/res/layout/adapter_home.xml @@ -1,5 +1,6 @@ - @@ -15,6 +16,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> + + + + app:layout_constraintRight_toLeftOf="@id/message_send_time" + app:layout_constraintTop_toTopOf="@id/message_head_icon" /> + app:layout_constraintLeft_toRightOf="@id/message_head_icon" + app:layout_constraintRight_toLeftOf="@id/message_status" /> @@ -60,7 +79,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" - android:text="@{greetingMessage.status,default=消息状态}" + android:text="@{greetingMessage.status,default=消息状态很长的文字}" app:layout_constraintBottom_toBottomOf="@id/message_head_icon" app:layout_constraintEnd_toEndOf="parent" /> diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 6e92011..d8365c6 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -1,20 +1,40 @@ - + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ui.fragments.home.HomeFragment"> - + - - - - + + - + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_marginTop="10dp" + android:paddingLeft="5dp" + android:paddingRight="5dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toBottomOf="@id/home_search" /> + + + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 6f9bd6f..4e6668a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,6 +1,6 @@ NavinfoVolvo - Home + 问候 Dashboard Notifications 删除 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 919f896..aaba65a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ NavinfoVolvo - Home + Message Dashboard Notifications Del