Merge branch 'master' of gitlab.navinfo.com:vivo/navinfovivo

This commit is contained in:
2023-01-04 15:40:50 +08:00
59 changed files with 1151 additions and 185 deletions

View File

@@ -0,0 +1,14 @@
package com.navinfo.volvo
import java.lang.Boolean
class Constant {
companion object{
/**
* 服务器地址
*/
const val SERVER_ADDRESS = "http://ec2-52-81-73-5.cn-north-1.compute.amazonaws.com.cn:8088/"
val DEBUG = Boolean.parseBoolean("true")
}
}

View File

@@ -0,0 +1,11 @@
package com.navinfo.volvo
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
open class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
}
}

View File

@@ -0,0 +1,20 @@
package com.navinfo.volvo.database
import androidx.room.Database
import androidx.room.RoomDatabase
import com.navinfo.volvo.database.dao.MessageDao
import com.navinfo.volvo.database.dao.UserDao
import com.navinfo.volvo.model.Attachment
import com.navinfo.volvo.model.Message
import com.navinfo.volvo.model.User
@Database(
entities = [Message::class, Attachment::class, User::class],
version = 1,
exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
abstract fun getMessageDao(): MessageDao
abstract fun getUserDao(): UserDao
}

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.db.dao;
package com.navinfo.volvo.database;
import android.content.Context;
@@ -10,10 +10,11 @@ import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
import com.navinfo.volvo.db.dao.entity.Message;
import com.navinfo.volvo.db.dao.entity.Attachment;
import com.navinfo.volvo.db.dao.entity.Message;
import com.navinfo.volvo.db.dao.entity.User;
import com.navinfo.volvo.database.dao.MessageDao;
import com.navinfo.volvo.database.dao.UserDao;
import com.navinfo.volvo.model.Message;
import com.navinfo.volvo.model.Attachment;
import com.navinfo.volvo.model.User;
import com.tencent.wcdb.database.SQLiteCipherSpec;
import com.tencent.wcdb.database.SQLiteDatabase;
@@ -39,6 +40,8 @@ public abstract class MapLifeDataBase extends RoomDatabase {
*/
public abstract MessageDao getMessageDao();
public abstract UserDao getUserDao();
/**
* 数据库秘钥
*/

View File

@@ -1,10 +1,10 @@
package com.navinfo.volvo.db.dao
package com.navinfo.volvo.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.navinfo.volvo.db.dao.entity.Message
import com.navinfo.volvo.model.Message
@Dao
interface MessageDao {

View File

@@ -0,0 +1,12 @@
package com.navinfo.volvo.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import com.navinfo.volvo.model.User
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUser(vararg user: User)
}

View File

@@ -1,13 +0,0 @@
package com.navinfo.volvo.db.dao.entity
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "User")
data class User(
@PrimaryKey()
val id:String,
var name:String,
var nickname:String,
)

View File

@@ -0,0 +1,16 @@
package com.navinfo.volvo.di.key
import androidx.lifecycle.ViewModel
import dagger.MapKey
import kotlin.reflect.KClass
@MustBeDocumented
@MapKey
@Retention(AnnotationRetention.RUNTIME)
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER
)
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)

View File

@@ -0,0 +1,57 @@
package com.navinfo.volvo.di.module
import android.content.Context
import androidx.room.Room
import com.navinfo.volvo.database.AppDatabase
import com.navinfo.volvo.database.dao.MessageDao
import com.navinfo.volvo.database.dao.UserDao
import com.tencent.wcdb.database.SQLiteCipherSpec
import com.tencent.wcdb.room.db.WCDBOpenHelperFactory
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module
class DatabaseModule {
@Singleton
@Provides
fun provideDatabase(context: Context): AppDatabase {
val DB_PASSWORD = "123456";
val cipherSpec = SQLiteCipherSpec()
.setPageSize(1024)
.setSQLCipherVersion(3)
val factory = WCDBOpenHelperFactory()
.passphrase(DB_PASSWORD.toByteArray()) // passphrase to the database, remove this line for plain-text
.cipherSpec(cipherSpec) // cipher to use, remove for default settings
.writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed
.asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed
return Room.databaseBuilder(context, AppDatabase::class.java, "NavinfoVolvoDb")
// [WCDB] Specify open helper to use WCDB database implementation instead
// of the Android framework.
.openHelperFactory(factory)
// Wipes and rebuilds instead of migrating if no Migration object.
// Migration is not part of this codelab.
// .fallbackToDestructiveMigration().addCallback(sRoomDatabaseCallback)
.build();
}
@Singleton
@Provides
fun provideMessageDao(database: AppDatabase): MessageDao {
return database.getMessageDao()
}
@Singleton
@Provides
fun provideUserDao(database: AppDatabase): UserDao {
return database.getUserDao()
}
}

View File

@@ -0,0 +1,29 @@
package com.navinfo.volvo.di.module
import com.navinfo.volvo.di.scope.DefaultDispatcher
import com.navinfo.volvo.di.scope.IoDispatcher
import com.navinfo.volvo.di.scope.MainDispatcher
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
@InstallIn(SingletonComponent::class)
@Module
object DispatcherModule {
@Provides
@DefaultDispatcher
fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default
@Provides
@IoDispatcher
fun providesIODispatcher(): CoroutineDispatcher = Dispatchers.IO
@Provides
@MainDispatcher
fun providesMainDispatcher(): CoroutineDispatcher = Dispatchers.Main
}

View File

@@ -0,0 +1,15 @@
package com.navinfo.volvo.di.module
import com.navinfo.volvo.repository.NetworkDataSource
import com.navinfo.volvo.repository.NetworkDataSourceImp
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@InstallIn(SingletonComponent::class)
@Module
abstract class NetworkDataModule {
@Binds
abstract fun bindNetworkData(networkDataSourceImp: NetworkDataSourceImp): NetworkDataSource
}

View File

@@ -0,0 +1,104 @@
package com.navinfo.volvo.di.module
import android.app.Application
import android.content.Context
import com.google.gson.Gson
import com.navinfo.volvo.Constant
import com.navinfo.volvo.repository.service.NetworkService
import com.navinfo.volvo.tools.GsonUtil
import dagger.Lazy
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module
class NetworkUtilModule {
@Provides
@Singleton
fun provideContext(application: Application): Context {
return application.applicationContext
}
@Provides
@Singleton
fun provideOkHttpClient(interceptor: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder().addInterceptor(interceptor).build()
}
@Provides
@Singleton
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().apply {
level = if (Constant.DEBUG) {
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE
}
}
}
@Provides
@Singleton
fun provideRetrofit(
client: Lazy<OkHttpClient>,
converterFactory: GsonConverterFactory,
context: Context
): Retrofit {
val retrofitBuilder = Retrofit.Builder()
.baseUrl(Constant.SERVER_ADDRESS)
.client(client.get())
.addConverterFactory(converterFactory)
// val okHttpClientBuilder = OkHttpClient.Builder()
// .addInterceptor { chain ->
//
// val original = chain.request()
// val originalHttpUrl = original.url
//
// val url = originalHttpUrl.newBuilder()
// .addQueryParameter("appid", BuildConfig.API_KEY)
// .build()
//
// Timber.d("Started making network call")
//
// val requestBuilder = original.newBuilder()
// .url(url)
//
// val request = requestBuilder.build()
// return@addInterceptor chain.proceed(request)
// }
// .readTimeout(60, TimeUnit.SECONDS)
// if (Constant.DEBUG) {
// okHttpClientBuilder.addInterceptor(ChuckInterceptor(context))
// }
// return retrofitBuilder.client(okHttpClientBuilder.build()).build()
return retrofitBuilder.build()
}
@Provides
@Singleton
fun provideGson(): Gson = GsonUtil.getInstance()
@Provides
@Singleton
fun provideGsonConverterFactory(gson: Gson): GsonConverterFactory {
return GsonConverterFactory.create(gson)
}
@Provides
@Singleton
fun provideNetworkService(retrofit: Retrofit): NetworkService {
return retrofit.create(NetworkService::class.java)
}
}

View File

@@ -0,0 +1,20 @@
package com.navinfo.volvo.di.module
import android.content.Context
import com.navinfo.volvo.util.SharedPreferenceHelper
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module
class UtilModule {
@Provides
@Singleton
fun provideSharedPreferencesHelper(context: Context): SharedPreferenceHelper {
return SharedPreferenceHelper.getInstance(context)
}
}

View File

@@ -0,0 +1,35 @@
package com.navinfo.volvo.di.module
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
/**
* Factory for all ViewModels.
* reference : https://github.com/googlesamples/android-architecture-components
*/
@Singleton
class ViewModelFactory @Inject constructor(
private val viewModelMap: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var viewModel = viewModelMap[modelClass]
if (viewModel == null) {
for (entry in viewModelMap) {
if (modelClass.isAssignableFrom(entry.key)) {
viewModel = entry.value
break
}
}
}
if (viewModel == null) throw IllegalArgumentException("Unknown model class $modelClass")
return viewModel.get() as T
}
}

View File

@@ -0,0 +1,30 @@
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.fragments.home.MessageViewModel
import com.navinfo.volvo.ui.fragments.login.LoginViewModel
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoMap
@InstallIn(SingletonComponent::class)
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory
@IntoMap
@Binds
@ViewModelKey(LoginViewModel::class)
abstract fun bindLoginFragmentViewModel(viewModel: LoginViewModel): ViewModel
@IntoMap
@Binds
@ViewModelKey(MessageViewModel::class)
abstract fun bindMessageFragmentViewModel(viewModel: MessageViewModel): ViewModel
}

View File

@@ -0,0 +1,15 @@
package com.navinfo.volvo.di.scope
import javax.inject.Qualifier
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class DefaultDispatcher
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class IoDispatcher
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class MainDispatcher

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.db.dao.entity
package com.navinfo.volvo.model
import androidx.room.Entity
import androidx.room.PrimaryKey

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.db.dao.entity
package com.navinfo.volvo.model
import androidx.room.Entity
import androidx.room.PrimaryKey

View File

@@ -0,0 +1,52 @@
package com.navinfo.volvo.model
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverter
import androidx.room.TypeConverters
import com.google.gson.reflect.TypeToken
import com.navinfo.volvo.tools.GsonUtil
import org.jetbrains.annotations.NotNull
import java.time.LocalDateTime
import java.time.LocalTime
import javax.inject.Inject
@Entity(tableName = "User")
@TypeConverters()
data class User(
@PrimaryKey()
@NotNull
val id: String,
var name: String,
var nickname: String,
){
@Inject constructor():this("${System.currentTimeMillis()}","df","sdfds")
}
class UserConverters() {
@TypeConverter
fun stringToUser(value: String): User {
val type = object : TypeToken<User>() {
}.type
return GsonUtil.getInstance().fromJson(value, type)
}
@TypeConverter
fun userToString(user: User): String {
return GsonUtil.getInstance().toJson(user)
}
@TypeConverter
fun userListToString(list: List<User>): String {
return GsonUtil.getInstance().toJson(list)
}
@TypeConverter
fun stringToUserList(value: String): List<User> {
val type = object : TypeToken<List<User>>() {
}.type
return GsonUtil.getInstance().fromJson(value, type)
}
}

View File

@@ -0,0 +1,15 @@
package com.navinfo.volvo.model.network
data class NetworkPostMessage(
val name: String,//问候名称,非必填项
val who: String, //我是谁
val toWho: String, //发送给谁
val startTime: String, //2023-01-02 15:49:50", //创建开始时间 非必填项 暂不支持按时间查询
val endTime: String,//" 2023-01-03 15:52:50", //创建结束时间 非必填项 暂不支持按时间查询
val pageSize: String, //查询数量
val pageNum: String, //分页查询
) {
constructor(who: String, toWho: String) : this("", who, toWho, "", "", "10", "1") {
}
}

View File

@@ -0,0 +1,9 @@
package com.navinfo.volvo.repository
import com.navinfo.volvo.model.Message
import com.navinfo.volvo.model.network.NetworkPostMessage
import com.navinfo.volvo.util.NetResult
interface NetworkDataSource {
suspend fun getCardList(message: NetworkPostMessage): NetResult<List<Message>>
}

View File

@@ -0,0 +1,40 @@
package com.navinfo.volvo.repository
import com.navinfo.volvo.di.scope.IoDispatcher
import com.navinfo.volvo.model.Message
import com.navinfo.volvo.model.network.NetworkPostMessage
import com.navinfo.volvo.repository.service.NetworkService
import com.navinfo.volvo.tools.GsonUtil
import com.navinfo.volvo.util.NetResult
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import okhttp3.FormBody
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import javax.inject.Inject
class NetworkDataSourceImp @Inject constructor(
private val netWorkService: NetworkService,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
) : NetworkDataSource {
override suspend fun getCardList(message: NetworkPostMessage): NetResult<List<Message>> =
withContext(ioDispatcher) {
return@withContext try {
val stringBody = GsonUtil.getInstance().toJson(message).toRequestBody("application/json;charset=utf-8".toMediaType())
val result = netWorkService.queryCardListByApp(stringBody)
if (result.isSuccessful) {
val list = result.body()
NetResult.Success(list)
} else {
NetResult.Success(null)
}
} catch (e: Exception) {
NetResult.Error(e)
}
}
}

View File

@@ -0,0 +1,12 @@
package com.navinfo.volvo.repository.service
import com.navinfo.volvo.model.Message
import okhttp3.RequestBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
interface NetworkService {
@POST("/navi/cardDelivery/queryCardListByApp")
suspend fun queryCardListByApp(@Body body: RequestBody): Response<List<Message>>
}

View File

@@ -0,0 +1,10 @@
package com.navinfo.volvo.ui
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import javax.inject.Inject
abstract class BaseFragment : Fragment() {
@Inject
lateinit var viewModelFactoryProvider: ViewModelProvider.Factory
}

View File

@@ -1,7 +1,8 @@
package com.navinfo.volvo
package com.navinfo.volvo.ui
import android.content.DialogInterface
import android.content.Intent
import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import android.widget.Toast
@@ -10,58 +11,23 @@ import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.easytools.tools.FileUtils
import com.elvishew.xlog.LogConfiguration
import com.elvishew.xlog.LogLevel
import com.elvishew.xlog.XLog
import com.elvishew.xlog.interceptor.BlacklistTagsFilterInterceptor
import com.elvishew.xlog.printer.AndroidPrinter
import com.elvishew.xlog.printer.ConsolePrinter
import com.elvishew.xlog.printer.Printer
import com.elvishew.xlog.printer.file.FilePrinter
import com.elvishew.xlog.printer.file.backup.NeverBackupStrategy
import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.navinfo.volvo.R
import com.navinfo.volvo.databinding.ActivityMainBinding
import com.navinfo.volvo.ui.message.MessageActivity
import com.navinfo.volvo.utils.SystemConstant
import dagger.hilt.android.AndroidEntryPoint
//@RuntimePermissions
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
public override fun onCreate(savedInstanceState: Bundle?) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navView: BottomNavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_main)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications, R.id.navigation_obtain_message
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
findViewById<View>(R.id.fab_new_message).apply {
this.setOnClickListener {
// 跳转到Message的Fragment
val messageIntent:Intent = Intent(this@MainActivity, MessageActivity::class.java)
startActivity(messageIntent)
// findNavController(R.id.layer_main_child_fragment).navigate(R.id.navigation_obtain_message)
}
}
setupNavigation()
XXPermissions.with(this)
// 申请单个权限
@@ -93,9 +59,43 @@ class MainActivity : AppCompatActivity() {
}
}
})
}
// @NeedsPermission(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
private fun setupNavigation() {
val navView: BottomNavigationView = binding.navView
val newMessageView = binding.newMessageFab
val navController = findNavController(R.id.nav_host_fragment_activity_main)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_message, R.id.navigation_dashboard, R.id.navigation_notifications,
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
navController.addOnDestinationChangedListener { controller, destination, arguments ->
if (destination.id == R.id.navigation_message
|| destination.id == R.id.navigation_dashboard
|| destination.id == R.id.navigation_notifications
|| destination.id == R.id.navigation_obtain_message
) {
runOnUiThread {
navView.visibility = View.VISIBLE
newMessageView.visibility = View.VISIBLE
}
} else {
runOnUiThread {
navView.visibility = View.GONE
newMessageView.visibility = View.GONE
}
}
}
}
override fun onSupportNavigateUp() =
findNavController(R.id.nav_host_fragment_activity_main).navigateUp()
// @NeedsPermission(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
fun createRootFolder() {
// 在SD卡创建项目目录
val sdCardPath = getExternalFilesDir(null)
@@ -145,7 +145,7 @@ class MainActivity : AppCompatActivity() {
)
}
// @OnShowRationale(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
// @OnShowRationale(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
fun showRationaleForSDCard(permissions: MutableList<String>) {
// showRationaleDialog(R.string.permission_camera_rationale, request)
// Toast.makeText(context, "当前操作需要您授权相机权限!", Toast.LENGTH_SHORT).show()
@@ -159,7 +159,7 @@ class MainActivity : AppCompatActivity() {
.show()
}
// @OnPermissionDenied(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
// @OnPermissionDenied(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
fun onSDCardDenied() {
Toast.makeText(this, "当前操作需要您授权读写SD卡权限", Toast.LENGTH_SHORT).show()
}

View File

@@ -7,7 +7,7 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.navinfo.volvo.R
import com.navinfo.volvo.db.dao.entity.Message
import com.navinfo.volvo.model.Message
class MessageAdapter : RecyclerView.Adapter<MessageAdapter.MyViewHolder>() {

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.ui.dashboard
package com.navinfo.volvo.ui.fragments.dashboard
import android.os.Bundle
import android.view.LayoutInflater
@@ -23,7 +23,7 @@ class DashboardFragment : Fragment() {
savedInstanceState: Bundle?
): View {
val dashboardViewModel =
ViewModelProvider(this).get(DashboardViewModel::class.java)
ViewModelProvider(this)[DashboardViewModel::class.java]
_binding = FragmentDashboardBinding.inflate(inflater, container, false)
val root: View = binding.root

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.ui.dashboard
package com.navinfo.volvo.ui.fragments.dashboard
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

View File

@@ -1,11 +1,10 @@
package com.navinfo.volvo.ui.home
package com.navinfo.volvo.ui.fragments.home
import android.os.Bundle
import android.view.Display
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.DividerItemDecoration
@@ -13,12 +12,14 @@ 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.adapter.MessageAdapter
import com.navinfo.volvo.ui.message.ObtainMessageViewModel
import com.navinfo.volvo.ui.fragments.message.ObtainMessageViewModel
import com.yanzhenjie.recyclerview.*
import com.yanzhenjie.recyclerview.SwipeRecyclerView.LoadMoreListener
import dagger.hilt.android.AndroidEntryPoint
class HomeFragment : Fragment(), OnItemClickListener, OnItemMenuClickListener {
@AndroidEntryPoint
class MessageFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListener {
private var _binding: FragmentHomeBinding? = null
@@ -26,28 +27,26 @@ class HomeFragment : Fragment(), OnItemClickListener, OnItemMenuClickListener {
// onDestroyView.
private val binding get() = _binding!!
private val viewModel by viewModels<MessageViewModel> { viewModelFactoryProvider }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
val obtainMessageViewModel = ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java)
// val homeViewModel =
// ViewModelProvider(this)[MessageViewModel::class.java]
// val obtainMessageViewModel =
// ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java)
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
initView()
return root
}
// val textView: TextView = binding.tvNewMessage
// textView.setOnClickListener {
// val message = Message(1, "新建标题", "", "", "", 0, "1", "2", mutableListOf())
// obtainMessageViewModel.setCurrentMessage(message)
// // 跳转到新建Message的Fragment
// Navigation.findNavController(it).navigate(R.id.home_2_obtain_message)
// }
// homeViewModel.text.observe(viewLifecycleOwner) {
//
// }
private fun initView() {
val recyclerview: SwipeRecyclerView = binding.homeMessageRecyclerview
recyclerview.adapter = null //先设置null否则会报错
//创建菜单选项
@@ -70,8 +69,6 @@ class HomeFragment : Fragment(), OnItemClickListener, OnItemMenuClickListener {
shareItem.text = context!!.getString(R.string.share)
shareItem.setTextColor(R.color.white)
rightMenu.addMenuItem(shareItem)
}
val layoutManager = LinearLayoutManager(context)
val adapter = MessageAdapter()
@@ -84,12 +81,21 @@ class HomeFragment : Fragment(), OnItemClickListener, OnItemMenuClickListener {
}
recyclerview.adapter = adapter
homeViewModel.getMessageList().observe(viewLifecycleOwner, Observer { contacts ->
adapter.setItem(contacts)
})
return root
// homeViewModel.getMessageList().observe(viewLifecycleOwner, Observer { contacts ->
// adapter.setItem(contacts)
// })
}
override fun onStart() {
super.onStart()
getMessageList()
}
private fun getMessageList() {
viewModel.getMessageList()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null

View File

@@ -0,0 +1,47 @@
package com.navinfo.volvo.ui.fragments.home
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.navinfo.volvo.model.Message
import com.navinfo.volvo.model.network.NetworkPostMessage
import com.navinfo.volvo.repository.NetworkDataSource
import com.navinfo.volvo.util.NetResult
import com.navinfo.volvo.util.asLiveData
import kotlinx.coroutines.launch
import javax.inject.Inject
class MessageViewModel @Inject constructor(
private val repository: NetworkDataSource
) : ViewModel() {
private val _isLoading = MutableLiveData<Boolean>()
val isLoading = _isLoading.asLiveData()
private val _messageList = MutableLiveData<List<Message>>()
val messageList = _messageList.asLiveData()
fun getMessageList() {
_isLoading.postValue(true)
viewModelScope.launch {
val messagePost = NetworkPostMessage(who = "北京测试", toWho = "volvo测试")
when (val result = repository.getCardList(messagePost)) {
is NetResult.Success -> {
_isLoading.value = false
if (result.data != null) {
val list = result.data
_messageList.value = list
}
}
is NetResult.Error -> {
_isLoading.value = false
}
is NetResult.Loading -> {
_isLoading.postValue(true)
}
}
}
}
}

View File

@@ -0,0 +1,51 @@
package com.navinfo.volvo.ui.fragments.login
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 dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class LoginFragment : BaseFragment() {
// private var loginViewModel:LoginViewModel by viewModel(get())
private var viewBinding: FragmentLoginBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = viewBinding!!
private val viewModel by viewModels<LoginViewModel> { viewModelFactoryProvider }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewBinding = FragmentLoginBinding.inflate(inflater, container, false)
val root: View = binding.root
binding.loginFragmentRegisterButton.setOnClickListener {
}
binding.loginFragmentLoginButton.setOnClickListener {
findNavController().navigate(R.id.action_login_to_home)
}
return root
}
override fun onDestroyView() {
viewBinding = null
super.onDestroyView()
}
}

View File

@@ -0,0 +1,25 @@
package com.navinfo.volvo.ui.fragments.login
import android.view.View
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.navinfo.volvo.database.AppDatabase
import com.navinfo.volvo.model.User
import javax.inject.Inject
class LoginViewModel @Inject constructor(private val dataBase: AppDatabase) : ViewModel() {
private val _user = MutableLiveData<User>().apply {
}
val user: LiveData<User> = _user
fun liveDataOnclick(view: View) {
}
fun userRegister(username: String, password: String) {
}
}

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.ui.message
package com.navinfo.volvo.ui.fragments.message
import android.content.DialogInterface
import android.os.Bundle

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.ui.message
package com.navinfo.volvo.ui.fragments.message
import androidx.lifecycle.*
import com.easytools.tools.ToastUtils

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.ui.notifications
package com.navinfo.volvo.ui.fragments.notifications
import android.os.Bundle
import android.view.LayoutInflater

View File

@@ -1,4 +1,4 @@
package com.navinfo.volvo.ui.notifications
package com.navinfo.volvo.ui.fragments.notifications
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

View File

@@ -1,34 +0,0 @@
package com.navinfo.volvo.ui.home
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.navinfo.volvo.db.dao.entity.Message
class HomeViewModel : ViewModel() {
private val messageList: LiveData<MutableList<Message>> =
MutableLiveData<MutableList<Message>>().apply {
value = mutableListOf<Message>()
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
value!!.add(Message())
}
fun getMessageList(): LiveData<MutableList<Message>> {
return messageList
}
}

View File

@@ -0,0 +1,28 @@
package com.navinfo.volvo.util
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
/**
* This functions helps in transforming a [MutableLiveData] of type [T]
* to a [LiveData] of type [T]
*/
fun <T> MutableLiveData<T>.asLiveData() = this as LiveData<T>
/**
* This function helps to observe a [LiveData] once
*/
fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
observe(
lifecycleOwner,
object : Observer<T> {
override fun onChanged(t: T?) {
observer.onChanged(t)
removeObserver(this)
}
}
)
}

View File

@@ -0,0 +1,24 @@
package com.navinfo.volvo.util
/**
* Created by Mayokun Adeniyi on 23/05/2020.
*/
/**
* A generic class that holds a value with its loading status.
* @param <T>
*/
sealed class NetResult<out R> {
data class Success<out T>(val data: T?) : NetResult<T>()
data class Error(val exception: Exception) : NetResult<Nothing>()
object Loading : NetResult<Nothing>()
override fun toString(): String {
return when (this) {
is Success<*> -> "Success[data=$data]"
is Error -> "Error[exception=$exception]"
is Loading -> "Loading"
}
}
}

View File

@@ -0,0 +1,131 @@
package com.navinfo.volvo.util
import android.content.Context
import android.content.SharedPreferences
import android.preference.PreferenceManager
import androidx.core.content.edit
import com.google.gson.Gson
class SharedPreferenceHelper {
companion object {
private const val WEATHER_PREF_TIME = "Weather pref time"
private const val WEATHER_FORECAST_PREF_TIME = "Forecast pref time"
private const val CITY_ID = "City ID"
private var prefs: SharedPreferences? = null
private const val LOCATION = "LOCATION"
@Volatile
private var instance: SharedPreferenceHelper? = null
/**
* This checks if there is an existing instance of the [SharedPreferences] in the
* specified [context] and creates one if there isn't or else, it returns the
* already existing instance. This function ensures that the [SharedPreferences] is
* accessed at any instance by a single thread.
*/
fun getInstance(context: Context): SharedPreferenceHelper {
synchronized(this) {
val _instance = instance
if (_instance == null) {
prefs = PreferenceManager.getDefaultSharedPreferences(context)
instance = _instance
}
return SharedPreferenceHelper()
}
}
}
/**
* This function saves the initial time [System.nanoTime] at which the weather information
* at the user's location is accessed.
* @param time the value of [System.nanoTime] when the weather information is received.
*/
fun saveTimeOfInitialWeatherFetch(time: Long) {
prefs?.edit(commit = true) {
putLong(WEATHER_PREF_TIME, time)
}
}
/**
* This function returns the saved value of [System.nanoTime] when the weather information
* at the user's location was accessed.
* @see saveTimeOfInitialWeatherFetch
*/
fun getTimeOfInitialWeatherFetch() = prefs?.getLong(WEATHER_PREF_TIME, 0L)
/**
* This function saves the initial time [System.nanoTime] at which the weather forecast
* at the user's location is accessed.
* @param time the value of [System.nanoTime] when the weather forecast is received.
*/
fun saveTimeOfInitialWeatherForecastFetch(time: Long) {
prefs?.edit(commit = true) {
putLong(WEATHER_FORECAST_PREF_TIME, time)
}
}
/**
* This function returns the saved value of [System.nanoTime] when the weather forecast
* at the user's location was accessed.
* @see saveTimeOfInitialWeatherForecastFetch
*/
fun getTimeOfInitialWeatherForecastFetch() = prefs?.getLong(WEATHER_FORECAST_PREF_TIME, 0L)
/**
* This function saves the [cityId] of the location whose weather information has been
* received.
* @param cityId the id of the location whose weather has been received
*/
fun saveCityId(cityId: Int) {
prefs?.edit(commit = true) {
putInt(CITY_ID, cityId)
}
}
/**
* This function returns the id of the location whose weather information has been received.
* @see saveCityId
*/
fun getCityId() = prefs?.getInt(CITY_ID, 0)
/**
* This function gets the value of the cache duration the user set in the
* Settings Fragment.
*/
fun getUserSetCacheDuration() = prefs?.getString("cache_key", "0")
/**
* This function gets the value of the app theme the user set in the
* Settings Fragment.
*/
fun getSelectedThemePref() = prefs?.getString("theme_key", "")
/**
* This function gets the value of the temperature unit the user set in the
* Settings Fragment.
*/
fun getSelectedTemperatureUnit() = prefs?.getString("unit_key", "")
// /**
// * This function saves a [LocationModel]
// */
// fun saveLocation(location: LocationModel) {
// prefs?.edit(commit = true) {
// val gson = Gson()
// val json = gson.toJson(location)
// putString(LOCATION, json)
// }
// }
// /**
// * This function gets the value of the saved [LocationModel]
// */
// fun getLocation(): LocationModel {
// val gson = Gson()
// val json = prefs?.getString(LOCATION, null)
// return gson.fromJson(json, LocationModel::class.java)
// }
}