diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 400aa4d..fed8fa3 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -8,7 +8,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 9fc9f50..214f513 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,9 +1,13 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'kotlin-android' + id 'kotlin-kapt' + id 'dagger.hilt.android.plugin' +// id 'com.google.dagger.hilt.android' } -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-kapt' + + //apply plugin: 'realm-android' android { namespace 'com.navinfo.volvo' @@ -21,7 +25,7 @@ android { // 指定room.schemaLocation生成的文件路径 javaCompileOptions { annotationProcessorOptions { - arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] + arguments += ["room.schemaLocation": "$projectDir/schemas".toString()] } } ndk { @@ -41,45 +45,84 @@ android { } kotlinOptions { jvmTarget = '1.8' + freeCompilerArgs += [ + "-Xjvm-default=all", + ] } buildFeatures { viewBinding true dataBinding true } + } dependencies { - implementation 'androidx.core:core-ktx:1.8.0' implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation "androidx.compose.material3:material3:1.0.0-alpha04" implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1" + implementation "androidx.lifecycle:lifecycle-common-java8:2.4.1" + implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1' implementation 'androidx.navigation:navigation-ui-ktx:2.4.1' + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.4' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' - + //room implementation 'com.tencent.wcdb:room:1.1-19' // 代替 room-runtime,同时也不需要再引用 wcdb-android - api 'androidx.sqlite:sqlite:2.2.0' implementation 'androidx.room:room-runtime:2.4.3' + implementation 'androidx.room:room-ktx:2.4.3' annotationProcessor 'androidx.room:room-compiler:2.4.3' annotationProcessor 'android.arch.persistence.room:compiler:1.1.1' kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler 需要用 room 的 kapt 'androidx.room:room-compiler:2.4.3' + kapt 'androidx.room:room-ktx:2.4.3' androidTestImplementation "android.arch.persistence.room:testing:1.1.1" // implementation "android.arch.lifecycle:extensions:1.1.1" // annotationProcessor "android.arch.lifecycle:compiler:1.1.1" implementation 'com.tencent.wcdb:wcdb-android:1.1-19' + + // 文件选择器 https://github.com/rosuH/AndroidFilePicker/blob/master/README_CN.md implementation 'me.rosuh:AndroidFilePicker:0.8.2' // 时间选择器 https://github.com/Gredicer/datetimepicker implementation 'com.github.Gredicer:datetimepicker:V1.0.0' - implementation 'com.google.code.gson:gson:2.10' implementation 'com.yanzhenjie.recyclerview:x:1.3.2' +// implementation 'androidx.appcompat:appcompat:1.5.1' + +// // Koin +// implementation("io.insert-koin:koin-android:3.3.2") +// implementation("io.insert-koin:koin-core:3.3.2") + + // Retrofit 网络请求相关 + implementation("com.squareup.retrofit2:retrofit:2.9.0") + implementation("com.squareup.retrofit2:converter-gson:2.9.0") + implementation("com.squareup.retrofit2:converter-gson:2.9.0") +// const val chuck = "com.readystatesoftware.chuck:library:${Versions.chuck}" +// const val chuckNoOp = "com.readystatesoftware.chuck:library-no-op:${Versions.chuck}" + implementation("com.squareup.okhttp3:okhttp:4.9.0") + implementation("com.squareup.okhttp3:logging-interceptor:4.9.0") + implementation("com.google.code.gson:gson:2.8.6") + + + //hilt + implementation "com.google.dagger:hilt-android:2.41" + kapt "com.google.dagger:hilt-compiler:2.41" +// implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03" +// androidTestImplementation "com.google.dagger:hilt-android-testing:2.41" +// kaptAndroidTest "com.google.dagger:hilt-android-compiler:2.41" + +} + +kapt { + correctErrorTypes true } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 59ecdb6..ed361f2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools"> @@ -28,5 +29,5 @@ android:value="" /> - + \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/Constant.kt b/app/src/main/java/com/navinfo/volvo/Constant.kt new file mode 100644 index 0000000..60c9260 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/Constant.kt @@ -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") + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/MyApplication.kt b/app/src/main/java/com/navinfo/volvo/MyApplication.kt new file mode 100644 index 0000000..05e3780 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/MyApplication.kt @@ -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() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/database/AppDatabase.kt b/app/src/main/java/com/navinfo/volvo/database/AppDatabase.kt new file mode 100644 index 0000000..0f288af --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/database/AppDatabase.kt @@ -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 +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/db/dao/MapLifeDataBase.java b/app/src/main/java/com/navinfo/volvo/database/MapLifeDataBase.java similarity index 96% rename from app/src/main/java/com/navinfo/volvo/db/dao/MapLifeDataBase.java rename to app/src/main/java/com/navinfo/volvo/database/MapLifeDataBase.java index 4c5b98a..857125f 100644 --- a/app/src/main/java/com/navinfo/volvo/db/dao/MapLifeDataBase.java +++ b/app/src/main/java/com/navinfo/volvo/database/MapLifeDataBase.java @@ -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(); + /** * 数据库秘钥 */ diff --git a/app/src/main/java/com/navinfo/volvo/db/dao/MessageDao.kt b/app/src/main/java/com/navinfo/volvo/database/dao/MessageDao.kt similarity index 83% rename from app/src/main/java/com/navinfo/volvo/db/dao/MessageDao.kt rename to app/src/main/java/com/navinfo/volvo/database/dao/MessageDao.kt index c4618a2..fa60d36 100644 --- a/app/src/main/java/com/navinfo/volvo/db/dao/MessageDao.kt +++ b/app/src/main/java/com/navinfo/volvo/database/dao/MessageDao.kt @@ -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 { diff --git a/app/src/main/java/com/navinfo/volvo/database/dao/UserDao.kt b/app/src/main/java/com/navinfo/volvo/database/dao/UserDao.kt new file mode 100644 index 0000000..fdbd156 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/database/dao/UserDao.kt @@ -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) +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/db/dao/entity/User.kt b/app/src/main/java/com/navinfo/volvo/db/dao/entity/User.kt deleted file mode 100644 index 91022fe..0000000 --- a/app/src/main/java/com/navinfo/volvo/db/dao/entity/User.kt +++ /dev/null @@ -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, - -) \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/di/key/ViewModelKey.kt b/app/src/main/java/com/navinfo/volvo/di/key/ViewModelKey.kt new file mode 100644 index 0000000..6941e15 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/key/ViewModelKey.kt @@ -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) diff --git a/app/src/main/java/com/navinfo/volvo/di/module/DatabaseModule.kt b/app/src/main/java/com/navinfo/volvo/di/module/DatabaseModule.kt new file mode 100644 index 0000000..bd2582e --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/module/DatabaseModule.kt @@ -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() + } +} diff --git a/app/src/main/java/com/navinfo/volvo/di/module/DispatcherModule.kt b/app/src/main/java/com/navinfo/volvo/di/module/DispatcherModule.kt new file mode 100644 index 0000000..6d79a5e --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/module/DispatcherModule.kt @@ -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 +} diff --git a/app/src/main/java/com/navinfo/volvo/di/module/NetworkDataModule.kt b/app/src/main/java/com/navinfo/volvo/di/module/NetworkDataModule.kt new file mode 100644 index 0000000..367df08 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/module/NetworkDataModule.kt @@ -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 +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/di/module/NetworkUtilModule.kt b/app/src/main/java/com/navinfo/volvo/di/module/NetworkUtilModule.kt new file mode 100644 index 0000000..f7acb9a --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/module/NetworkUtilModule.kt @@ -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, + 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) + } +} diff --git a/app/src/main/java/com/navinfo/volvo/di/module/UtilModule.kt b/app/src/main/java/com/navinfo/volvo/di/module/UtilModule.kt new file mode 100644 index 0000000..316e5c5 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/module/UtilModule.kt @@ -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) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/di/module/ViewModelFactory.kt b/app/src/main/java/com/navinfo/volvo/di/module/ViewModelFactory.kt new file mode 100644 index 0000000..079be5e --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/module/ViewModelFactory.kt @@ -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, @JvmSuppressWildcards Provider> +) : ViewModelProvider.Factory { + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): 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 + } +} 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 new file mode 100644 index 0000000..49a7be3 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/module/ViewModelModule.kt @@ -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 +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/di/scope/DispatcherScopes.kt b/app/src/main/java/com/navinfo/volvo/di/scope/DispatcherScopes.kt new file mode 100644 index 0000000..a1d7e1c --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/di/scope/DispatcherScopes.kt @@ -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 \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/db/dao/entity/Attachment.kt b/app/src/main/java/com/navinfo/volvo/model/Attachment.kt similarity index 96% rename from app/src/main/java/com/navinfo/volvo/db/dao/entity/Attachment.kt rename to app/src/main/java/com/navinfo/volvo/model/Attachment.kt index 0a64f2d..fefa2b3 100644 --- a/app/src/main/java/com/navinfo/volvo/db/dao/entity/Attachment.kt +++ b/app/src/main/java/com/navinfo/volvo/model/Attachment.kt @@ -1,4 +1,4 @@ -package com.navinfo.volvo.db.dao.entity +package com.navinfo.volvo.model import androidx.room.Entity import androidx.room.PrimaryKey diff --git a/app/src/main/java/com/navinfo/volvo/db/dao/entity/Message.kt b/app/src/main/java/com/navinfo/volvo/model/Message.kt similarity index 95% rename from app/src/main/java/com/navinfo/volvo/db/dao/entity/Message.kt rename to app/src/main/java/com/navinfo/volvo/model/Message.kt index 77ad8dd..82c591d 100644 --- a/app/src/main/java/com/navinfo/volvo/db/dao/entity/Message.kt +++ b/app/src/main/java/com/navinfo/volvo/model/Message.kt @@ -1,4 +1,4 @@ -package com.navinfo.volvo.db.dao.entity +package com.navinfo.volvo.model import androidx.room.Entity import androidx.room.PrimaryKey diff --git a/app/src/main/java/com/navinfo/volvo/model/User.kt b/app/src/main/java/com/navinfo/volvo/model/User.kt new file mode 100644 index 0000000..80a6c7a --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/model/User.kt @@ -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() { + + }.type + return GsonUtil.getInstance().fromJson(value, type) + } + + @TypeConverter + fun userToString(user: User): String { + return GsonUtil.getInstance().toJson(user) + } + + @TypeConverter + fun userListToString(list: List): String { + return GsonUtil.getInstance().toJson(list) + } + + @TypeConverter + fun stringToUserList(value: String): List { + val type = object : TypeToken>() { + + }.type + return GsonUtil.getInstance().fromJson(value, type) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/model/network/NetworkPostMessage.kt b/app/src/main/java/com/navinfo/volvo/model/network/NetworkPostMessage.kt new file mode 100644 index 0000000..8e452f6 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/model/network/NetworkPostMessage.kt @@ -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") { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/repository/NetworkDataSource.kt b/app/src/main/java/com/navinfo/volvo/repository/NetworkDataSource.kt new file mode 100644 index 0000000..0791642 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/repository/NetworkDataSource.kt @@ -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> +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/repository/NetworkDataSourceImp.kt b/app/src/main/java/com/navinfo/volvo/repository/NetworkDataSourceImp.kt new file mode 100644 index 0000000..9bf7e4b --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/repository/NetworkDataSourceImp.kt @@ -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> = + 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) + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/repository/service/NetworkService.kt b/app/src/main/java/com/navinfo/volvo/repository/service/NetworkService.kt new file mode 100644 index 0000000..df62a9c --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/repository/service/NetworkService.kt @@ -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> +} \ 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/BaseFragment.kt new file mode 100644 index 0000000..bf288d6 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/ui/BaseFragment.kt @@ -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 +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/MainActivity.kt b/app/src/main/java/com/navinfo/volvo/ui/MainActivity.kt similarity index 50% rename from app/src/main/java/com/navinfo/volvo/MainActivity.kt rename to app/src/main/java/com/navinfo/volvo/ui/MainActivity.kt index 7e56e08..0b439bd 100644 --- a/app/src/main/java/com/navinfo/volvo/MainActivity.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/MainActivity.kt @@ -1,17 +1,18 @@ -package com.navinfo.volvo +package com.navinfo.volvo.ui import android.os.Bundle import android.view.View -import com.google.android.material.bottomnavigation.BottomNavigationView import androidx.appcompat.app.AppCompatActivity -import androidx.navigation.Navigation import androidx.navigation.findNavController import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController +import com.google.android.material.bottomnavigation.BottomNavigationView import com.navinfo.volvo.R import com.navinfo.volvo.databinding.ActivityMainBinding +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding @@ -21,23 +22,39 @@ class MainActivity : AppCompatActivity() { binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) + setupNavigation() + } + private fun setupNavigation() { val navView: BottomNavigationView = binding.navView - + val newMessageView = binding.newMessageFab 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 + R.id.navigation_message, R.id.navigation_dashboard, R.id.navigation_notifications, ) ) setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) - findViewById(R.id.fab_new_message).apply { - this.setOnClickListener { - navController.navigate(R.id.fab_new_message) + 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() } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/ui/adapter/MessageAdapter.kt b/app/src/main/java/com/navinfo/volvo/ui/adapter/MessageAdapter.kt index 7a460c5..22875d9 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/adapter/MessageAdapter.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/adapter/MessageAdapter.kt @@ -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() { diff --git a/app/src/main/java/com/navinfo/volvo/ui/dashboard/DashboardFragment.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/dashboard/DashboardFragment.kt similarity index 90% rename from app/src/main/java/com/navinfo/volvo/ui/dashboard/DashboardFragment.kt rename to app/src/main/java/com/navinfo/volvo/ui/fragments/dashboard/DashboardFragment.kt index 9dda29c..5d0998b 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/dashboard/DashboardFragment.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/dashboard/DashboardFragment.kt @@ -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 diff --git a/app/src/main/java/com/navinfo/volvo/ui/dashboard/DashboardViewModel.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/dashboard/DashboardViewModel.kt similarity index 86% rename from app/src/main/java/com/navinfo/volvo/ui/dashboard/DashboardViewModel.kt rename to app/src/main/java/com/navinfo/volvo/ui/fragments/dashboard/DashboardViewModel.kt index 647da35..d127ea2 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/dashboard/DashboardViewModel.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/dashboard/DashboardViewModel.kt @@ -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 diff --git a/app/src/main/java/com/navinfo/volvo/ui/home/HomeFragment.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/home/MessageFragment.kt similarity index 72% rename from app/src/main/java/com/navinfo/volvo/ui/home/HomeFragment.kt rename to app/src/main/java/com/navinfo/volvo/ui/fragments/home/MessageFragment.kt index 89df690..33b9dc2 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/home/MessageFragment.kt @@ -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 { 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 diff --git a/app/src/main/java/com/navinfo/volvo/ui/fragments/home/MessageViewModel.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/home/MessageViewModel.kt new file mode 100644 index 0000000..4bbe309 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/home/MessageViewModel.kt @@ -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() + val isLoading = _isLoading.asLiveData() + + private val _messageList = MutableLiveData>() + 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) + } + } + } + } + +} \ No newline at end of file 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 new file mode 100644 index 0000000..35250a0 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/login/LoginFragment.kt @@ -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 { 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() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/ui/fragments/login/LoginViewModel.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/login/LoginViewModel.kt new file mode 100644 index 0000000..5c02c3e --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/login/LoginViewModel.kt @@ -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().apply { + + } + val user: LiveData = _user + + fun liveDataOnclick(view: View) { + + } + + fun userRegister(username: String, password: String) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/ui/message/ObtainMessageFragment.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageFragment.kt similarity index 86% rename from app/src/main/java/com/navinfo/volvo/ui/message/ObtainMessageFragment.kt rename to app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageFragment.kt index d90d8cf..d0c23e3 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/message/ObtainMessageFragment.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageFragment.kt @@ -1,4 +1,4 @@ -package com.navinfo.volvo.ui.message +package com.navinfo.volvo.ui.fragments.message import android.os.Bundle import android.view.LayoutInflater @@ -29,13 +29,13 @@ class ObtainMessageFragment: Fragment() { _binding = FragmentObtainMessageBinding.inflate(inflater, container, false) val root: View = binding.root - obtainMessageViewModel?.getMessageLiveData()?.observe( + obtainMessageViewModel.getMessageLiveData()?.observe( viewLifecycleOwner, Observer { // 初始化界面显示内容 if(it.title!=null) - binding.tvMessageTitle?.setText(it.title) + binding.tvMessageTitle.setText(it.title) if (it.sendDate!=null) { - binding.btnSendTime.setText(it.sendDate) + binding.btnSendTime.text = it.sendDate } } ) @@ -43,7 +43,7 @@ class ObtainMessageFragment: Fragment() { return root } - fun initView() { + private fun initView() { // 设置问候信息提示的红色星号 binding.tiLayoutTitle.markRequiredInRed() // 设置点击按钮选择发送时间 @@ -59,6 +59,9 @@ class ObtainMessageFragment: Fragment() { } // 点击按钮选择拍照 + binding.edtSendTo.setOnClickListener { + + } } override fun onDestroyView() { diff --git a/app/src/main/java/com/navinfo/volvo/ui/message/ObtainMessageViewModel.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageViewModel.kt similarity index 89% rename from app/src/main/java/com/navinfo/volvo/ui/message/ObtainMessageViewModel.kt rename to app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageViewModel.kt index 2ce11d2..b2343d5 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/message/ObtainMessageViewModel.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageViewModel.kt @@ -1,11 +1,9 @@ -package com.navinfo.volvo.ui.message +package com.navinfo.volvo.ui.fragments.message -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.liveData -import com.navinfo.volvo.db.dao.entity.Message -import com.navinfo.volvo.db.dao.entity.AttachmentType +import com.navinfo.volvo.model.Message +import com.navinfo.volvo.model.AttachmentType class ObtainMessageViewModel: ViewModel() { private val msgLiveData: MutableLiveData by lazy { diff --git a/app/src/main/java/com/navinfo/volvo/ui/notifications/NotificationsFragment.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/notifications/NotificationsFragment.kt similarity index 95% rename from app/src/main/java/com/navinfo/volvo/ui/notifications/NotificationsFragment.kt rename to app/src/main/java/com/navinfo/volvo/ui/fragments/notifications/NotificationsFragment.kt index 80b8a27..19bfb9c 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/notifications/NotificationsFragment.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/notifications/NotificationsFragment.kt @@ -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 diff --git a/app/src/main/java/com/navinfo/volvo/ui/notifications/NotificationsViewModel.kt b/app/src/main/java/com/navinfo/volvo/ui/fragments/notifications/NotificationsViewModel.kt similarity index 85% rename from app/src/main/java/com/navinfo/volvo/ui/notifications/NotificationsViewModel.kt rename to app/src/main/java/com/navinfo/volvo/ui/fragments/notifications/NotificationsViewModel.kt index 92a3e47..7a87e25 100644 --- a/app/src/main/java/com/navinfo/volvo/ui/notifications/NotificationsViewModel.kt +++ b/app/src/main/java/com/navinfo/volvo/ui/fragments/notifications/NotificationsViewModel.kt @@ -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 diff --git a/app/src/main/java/com/navinfo/volvo/ui/home/HomeViewModel.kt b/app/src/main/java/com/navinfo/volvo/ui/home/HomeViewModel.kt deleted file mode 100644 index 24af3e1..0000000 --- a/app/src/main/java/com/navinfo/volvo/ui/home/HomeViewModel.kt +++ /dev/null @@ -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> = - MutableLiveData>().apply { - value = mutableListOf() - 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> { - return messageList - } -} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/volvo/util/LiveDataUtils.kt b/app/src/main/java/com/navinfo/volvo/util/LiveDataUtils.kt new file mode 100644 index 0000000..5391f70 --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/util/LiveDataUtils.kt @@ -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 MutableLiveData.asLiveData() = this as LiveData + +/** + * This function helps to observe a [LiveData] once + */ +fun LiveData.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer) { + observe( + lifecycleOwner, + object : Observer { + override fun onChanged(t: T?) { + observer.onChanged(t) + removeObserver(this) + } + } + ) +} diff --git a/app/src/main/java/com/navinfo/volvo/util/NetResult.kt b/app/src/main/java/com/navinfo/volvo/util/NetResult.kt new file mode 100644 index 0000000..21c532c --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/util/NetResult.kt @@ -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 + */ +sealed class NetResult { + + data class Success(val data: T?) : NetResult() + data class Error(val exception: Exception) : NetResult() + object Loading : NetResult() + + override fun toString(): String { + return when (this) { + is Success<*> -> "Success[data=$data]" + is Error -> "Error[exception=$exception]" + is Loading -> "Loading" + } + } +} diff --git a/app/src/main/java/com/navinfo/volvo/util/SharedPreferenceHelper.kt b/app/src/main/java/com/navinfo/volvo/util/SharedPreferenceHelper.kt new file mode 100644 index 0000000..f4e5fdc --- /dev/null +++ b/app/src/main/java/com/navinfo/volvo/util/SharedPreferenceHelper.kt @@ -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) +// } +} diff --git a/app/src/main/res/anim/from_left.xml b/app/src/main/res/anim/from_left.xml new file mode 100644 index 0000000..db0b519 --- /dev/null +++ b/app/src/main/res/anim/from_left.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/from_right.xml b/app/src/main/res/anim/from_right.xml new file mode 100644 index 0000000..e3a0285 --- /dev/null +++ b/app/src/main/res/anim/from_right.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/to_left.xml b/app/src/main/res/anim/to_left.xml new file mode 100644 index 0000000..c2e06d7 --- /dev/null +++ b/app/src/main/res/anim/to_left.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/to_right.xml b/app/src/main/res/anim/to_right.xml new file mode 100644 index 0000000..d30d117 --- /dev/null +++ b/app/src/main/res/anim/to_right.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/shape_divider_linear.xml b/app/src/main/res/drawable-v24/shape_divider_linear.xml new file mode 100644 index 0000000..1a3f5a8 --- /dev/null +++ b/app/src/main/res/drawable-v24/shape_divider_linear.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable-v24/shape_radius5_white.xml b/app/src/main/res/drawable-v24/shape_radius5_white.xml new file mode 100644 index 0000000..f807c0c --- /dev/null +++ b/app/src/main/res/drawable-v24/shape_radius5_white.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_baseline_navigate_next_24.xml b/app/src/main/res/drawable/ic_baseline_navigate_next_24.xml new file mode 100644 index 0000000..e7cf886 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_navigate_next_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_star_8.xml b/app/src/main/res/drawable/ic_baseline_star_8.xml new file mode 100644 index 0000000..f064c89 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_star_8.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index e8c8e75..b56fc98 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,6 +6,7 @@ android:layout_height="match_parent"> + app:layout_constraintRight_toRightOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml index d137b00..ffa373e 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_dashboard.xml @@ -1,10 +1,11 @@ - + tools:context="com.navinfo.volvo.ui.fragments.dashboard.DashboardFragment"> + tools:context=".ui.fragments.home.MessageFragment"> diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml new file mode 100644 index 0000000..30aec55 --- /dev/null +++ b/app/src/main/res/layout/fragment_login.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_notifications.xml b/app/src/main/res/layout/fragment_notifications.xml index d417935..202e34f 100644 --- a/app/src/main/res/layout/fragment_notifications.xml +++ b/app/src/main/res/layout/fragment_notifications.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.notifications.NotificationsFragment"> + tools:context=".ui.fragments.notifications.NotificationsFragment"> - + tools:context=".ui.fragments.message.ObtainMessageFragment"> + + android:scrollbars="none" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent"> + @@ -24,10 +25,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/default_widget_padding" + android:hint="问候信息" app:counterEnabled="true" app:counterMaxLength="10" app:errorEnabled="true" - android:hint="问候信息" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" @@ -82,22 +83,24 @@ android:text="上传图片:"> + app:icon="@drawable/ic_baseline_camera_24"> + + + app:icon="@drawable/ic_baseline_image_search_24"> + app:icon="@drawable/ic_baseline_fiber_manual_record_24"> + + + app:icon="@drawable/ic_baseline_audio_file_24"> @@ -157,8 +162,12 @@ android:id="@+id/layer_send_info" android:layout_width="match_parent" android:layout_height="wrap_content" + android:animateLayoutChanges="true" + android:background="@drawable/shape_radius5_white" + android:divider="@drawable/shape_divider_linear" android:orientation="vertical" android:padding="@dimen/default_widget_padding" + android:showDividers="middle" app:layout_constraintTop_toBottomOf="@id/div_send_info"> - + android:drawableStart="@drawable/ic_baseline_star_8" + android:drawableEnd="@drawable/ic_baseline_navigate_next_24" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:text="发给谁:" /> - - - - - - + app:icon="@drawable/ic_baseline_access_time_24"> + + app:startDestination="@+id/navigation_login"> - - - + android:id="@+id/navigation_login" + android:name="com.navinfo.volvo.ui.fragments.login.LoginFragment" + android:label="login" + tools:layout="@layout/fragment_login"> + + \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index aada80e..d241e8c 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -1,6 +1,6 @@ -