├── .gitignore ├── .idea ├── .name ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── deploymentTargetDropDown.xml ├── dictionaries │ └── Administrator.xml ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── jarRepositories.xml ├── misc.xml └── vcs.xml ├── JetpackMvvm ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── hgj │ │ └── jetpackmvvm │ │ ├── base │ │ ├── BaseApp.kt │ │ ├── Ktx.kt │ │ ├── activity │ │ │ ├── BaseVmActivity.kt │ │ │ ├── BaseVmDbActivity.kt │ │ │ └── BaseVmVbActivity.kt │ │ ├── fragment │ │ │ ├── BaseVmDbFragment.kt │ │ │ ├── BaseVmFragment.kt │ │ │ └── BaseVmVbFragment.kt │ │ └── viewmodel │ │ │ └── BaseViewModel.kt │ │ ├── callback │ │ ├── databind │ │ │ ├── BooleanObservableField.kt │ │ │ ├── ByteObservableField.kt │ │ │ ├── DoubleObservableField.kt │ │ │ ├── FloatObservableField.kt │ │ │ ├── IntObservableField.kt │ │ │ ├── ShortObservableField.kt │ │ │ └── StringObservableField.kt │ │ └── livedata │ │ │ ├── BooleanLiveData.kt │ │ │ ├── ByteLiveData.kt │ │ │ ├── DoubleLiveData.kt │ │ │ ├── FloatLiveData.kt │ │ │ ├── IntLiveData.kt │ │ │ ├── ShortLiveData.kt │ │ │ ├── StringLiveData.kt │ │ │ ├── UnPeekLiveData.kt │ │ │ └── event │ │ │ └── EventLiveData.kt │ │ ├── ext │ │ ├── BaseViewModelExt.kt │ │ ├── GetViewModelExt.kt │ │ ├── NavigationExt.kt │ │ ├── ViewBindUtil.kt │ │ ├── download │ │ │ ├── DownLoadManager.kt │ │ │ ├── DownLoadPool.kt │ │ │ ├── DownLoadProgressListener.kt │ │ │ ├── DownLoadService.kt │ │ │ ├── DownloadResultState.kt │ │ │ ├── FileDownloaderExt.kt │ │ │ ├── FileTool.kt │ │ │ └── ShareDownLoadUtil.kt │ │ ├── lifecycle │ │ │ ├── KtxActivityManger.kt │ │ │ ├── KtxAppLifeObserver.kt │ │ │ ├── KtxHandler.kt │ │ │ └── KtxLifeCycleCallBack.kt │ │ ├── util │ │ │ ├── CommonExt.kt │ │ │ ├── LogExt.kt │ │ │ ├── StringExt.kt │ │ │ └── SystemServiceExt.kt │ │ └── view │ │ │ ├── EditTextViewExt.kt │ │ │ └── ViewExt.kt │ │ ├── navigation │ │ ├── FragmentNavigatorHideShow.kt │ │ └── NavHostFragmentHideShow.kt │ │ ├── network │ │ ├── AppException.kt │ │ ├── BaseNetworkApi.kt │ │ ├── BaseResponse.kt │ │ ├── CoroutineCallAdapterFactory.kt │ │ ├── Error.kt │ │ ├── ExceptionHandle.kt │ │ ├── NetworkUtil.java │ │ ├── interceptor │ │ │ ├── CacheInterceptor.kt │ │ │ └── logging │ │ │ │ ├── DefaultFormatPrinter.kt │ │ │ │ ├── FormatPrinter.kt │ │ │ │ └── LogInterceptor.kt │ │ └── manager │ │ │ ├── NetState.kt │ │ │ ├── NetworkStateManager.kt │ │ │ └── NetworkStateReceive.kt │ │ ├── state │ │ └── ResultState.kt │ │ └── util │ │ ├── ActivityMessenger.kt │ │ ├── CharacterHandler.kt │ │ ├── Drawables.java │ │ ├── LogUtils.kt │ │ ├── ProxyDrawable.java │ │ ├── UrlEncoderUtils.kt │ │ └── ZipHelper.kt │ └── res │ └── values │ └── strings.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── cxk.jks ├── priguardMapping.txt ├── proguard-rules.pro ├── release │ ├── app-release.apk │ └── output.json └── src │ ├── androidTest │ └── java │ │ └── me │ │ └── hgj │ │ └── jetpackmvvm │ │ └── demo │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── me │ │ │ └── hgj │ │ │ └── jetpackmvvm │ │ │ └── demo │ │ │ ├── app │ │ │ ├── App.kt │ │ │ ├── base │ │ │ │ ├── BaseActivity.kt │ │ │ │ ├── BaseActivity1.kt │ │ │ │ ├── BaseFragment.kt │ │ │ │ └── BaseFragment1.kt │ │ │ ├── event │ │ │ │ ├── AppViewModel.kt │ │ │ │ └── EventViewModel.kt │ │ │ ├── ext │ │ │ │ ├── AdapterExt.kt │ │ │ │ ├── AppExt.kt │ │ │ │ ├── CustomViewExt.kt │ │ │ │ └── LoadingDialogExt.kt │ │ │ ├── network │ │ │ │ ├── ApiService.kt │ │ │ │ ├── MyHeadInterceptor.kt │ │ │ │ ├── NetworkApi.kt │ │ │ │ ├── TokenOutInterceptor.kt │ │ │ │ └── stateCallback │ │ │ │ │ ├── CollectUiState.kt │ │ │ │ │ ├── ListDataUiState.kt │ │ │ │ │ └── UpdateUiState.kt │ │ │ ├── util │ │ │ │ ├── CacheDataManager.kt │ │ │ │ ├── CacheUtil.kt │ │ │ │ ├── ColorUtil.kt │ │ │ │ ├── DatetimeUtil.kt │ │ │ │ ├── SettingUtil.kt │ │ │ │ └── StatusBarUtil.kt │ │ │ └── weight │ │ │ │ ├── banner │ │ │ │ ├── HomeBannerAdapter.kt │ │ │ │ ├── HomeBannerViewHolder.kt │ │ │ │ ├── WelcomeBannerAdapter.kt │ │ │ │ └── WelcomeBannerViewHolder.kt │ │ │ │ ├── customview │ │ │ │ ├── CollectView.kt │ │ │ │ ├── MyView.kt │ │ │ │ └── PriorityDialog.kt │ │ │ │ ├── loadCallBack │ │ │ │ ├── EmptyCallback.kt │ │ │ │ ├── ErrorCallback.kt │ │ │ │ └── LoadingCallback.kt │ │ │ │ ├── preference │ │ │ │ ├── CheckBoxPreference.java │ │ │ │ ├── IconPreference.kt │ │ │ │ ├── MyColorCircleView.kt │ │ │ │ └── PreferenceCategory.java │ │ │ │ ├── recyclerview │ │ │ │ ├── DefineLoadMoreView.kt │ │ │ │ ├── FatScrollAwareFABBehavior.java │ │ │ │ ├── GridDividerItemDecoration.java │ │ │ │ └── SpaceItemDecoration.kt │ │ │ │ └── viewpager │ │ │ │ └── ScaleTransitionPagerTitleView.kt │ │ │ ├── data │ │ │ ├── bindadapter │ │ │ │ └── CustomBindAdapter.kt │ │ │ ├── model │ │ │ │ ├── bean │ │ │ │ │ ├── ApiPagerResponse.kt │ │ │ │ │ ├── ApiResponse.kt │ │ │ │ │ ├── AriticleResponse.kt │ │ │ │ │ ├── BannerResponse.kt │ │ │ │ │ ├── ClassifyResponse.kt │ │ │ │ │ ├── CoinInfoResponse.kt │ │ │ │ │ ├── CollectBus.kt │ │ │ │ │ ├── CollectResponse.kt │ │ │ │ │ ├── CollectUrlResponse.kt │ │ │ │ │ ├── IntegralHistoryResponse.kt │ │ │ │ │ ├── IntegralResponse.kt │ │ │ │ │ ├── MeItemEntity.kt │ │ │ │ │ ├── NavigationResponse.kt │ │ │ │ │ ├── SearchResponse.kt │ │ │ │ │ ├── ShareResponse.kt │ │ │ │ │ ├── SystemResponse.kt │ │ │ │ │ ├── TagsResponse.kt │ │ │ │ │ ├── TodoResponse.kt │ │ │ │ │ └── UserInfo.kt │ │ │ │ └── enums │ │ │ │ │ ├── CollectType.kt │ │ │ │ │ ├── MeItemType.kt │ │ │ │ │ └── TodoType.kt │ │ │ └── repository │ │ │ │ ├── local │ │ │ │ └── LocalDataManger.kt │ │ │ │ └── request │ │ │ │ └── HttpRequestManger.kt │ │ │ ├── ui │ │ │ ├── activity │ │ │ │ ├── ErrorActivity.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── TestActivity.kt │ │ │ │ └── WelcomeActivity.kt │ │ │ ├── adapter │ │ │ │ ├── AriticleAdapter.kt │ │ │ │ ├── CollectAdapter.kt │ │ │ │ ├── CollectUrlAdapter.kt │ │ │ │ ├── IntegralAdapter.kt │ │ │ │ ├── IntegralHistoryAdapter.kt │ │ │ │ ├── NavigationAdapter.kt │ │ │ │ ├── NavigationChildAdapter.kt │ │ │ │ ├── PriorityAdapter.kt │ │ │ │ ├── SearcHistoryAdapter.kt │ │ │ │ ├── SearcHotAdapter.kt │ │ │ │ ├── ShareAdapter.kt │ │ │ │ ├── SystemAdapter.kt │ │ │ │ ├── SystemChildAdapter.kt │ │ │ │ ├── TestAdapter.kt │ │ │ │ └── TodoAdapter.kt │ │ │ └── fragment │ │ │ │ ├── MainFragment.kt │ │ │ │ ├── collect │ │ │ │ ├── CollectAriticleFragment.kt │ │ │ │ ├── CollectFragment.kt │ │ │ │ └── CollectUrlFragment.kt │ │ │ │ ├── home │ │ │ │ └── HomeFragment.kt │ │ │ │ ├── integral │ │ │ │ ├── IntegralFragment.kt │ │ │ │ └── IntegralHistoryFragment.kt │ │ │ │ ├── login │ │ │ │ ├── LoginFragment.kt │ │ │ │ └── RegisterFrgment.kt │ │ │ │ ├── lookinfo │ │ │ │ └── LookInfoFragment.kt │ │ │ │ ├── me │ │ │ │ └── MeFragment.kt │ │ │ │ ├── project │ │ │ │ ├── ProjectChildFragment.kt │ │ │ │ └── ProjectFragment.kt │ │ │ │ ├── publicNumber │ │ │ │ ├── PublicChildFragment.kt │ │ │ │ └── PublicNumberFragment.kt │ │ │ │ ├── search │ │ │ │ ├── SearchFragment.kt │ │ │ │ └── SearchResultFragment.kt │ │ │ │ ├── setting │ │ │ │ └── SettingFragment.kt │ │ │ │ ├── share │ │ │ │ ├── AddAriticleFragment.kt │ │ │ │ └── AriticleFragment.kt │ │ │ │ ├── todo │ │ │ │ ├── AddTodoFragment.kt │ │ │ │ └── TodoListFragment.kt │ │ │ │ ├── tree │ │ │ │ ├── AskFragment.kt │ │ │ │ ├── NavigationFragment.kt │ │ │ │ ├── PlazaFragment.kt │ │ │ │ ├── SystemArrFragment.kt │ │ │ │ ├── SystemChildFragment.kt │ │ │ │ ├── SystemFragment.kt │ │ │ │ └── TreeArrFragment.kt │ │ │ │ └── web │ │ │ │ └── WebFragment.kt │ │ │ └── viewmodel │ │ │ ├── request │ │ │ ├── RequestAriticleViewModel.kt │ │ │ ├── RequestCollectViewModel.kt │ │ │ ├── RequestHomeViewModel.kt │ │ │ ├── RequestIntegralViewModel.kt │ │ │ ├── RequestLoginRegisterViewModel.kt │ │ │ ├── RequestLookInfoViewModel.kt │ │ │ ├── RequestMeViewModel.kt │ │ │ ├── RequestProjectViewModel.kt │ │ │ ├── RequestPublicNumberViewModel.kt │ │ │ ├── RequestSearchViewModel.kt │ │ │ ├── RequestTodoViewModel.kt │ │ │ └── RequestTreeViewModel.kt │ │ │ └── state │ │ │ ├── AriticleViewModel.kt │ │ │ ├── DemoViewModel.kt │ │ │ ├── HomeViewModel.kt │ │ │ ├── IntegralViewModel.kt │ │ │ ├── LoginRegisterViewModel.kt │ │ │ ├── LookInfoViewModel.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── MeViewModel.kt │ │ │ ├── ProjectViewModel.kt │ │ │ ├── PublicNumberViewModel.kt │ │ │ ├── SearchViewModel.kt │ │ │ ├── TodoViewModel.kt │ │ │ ├── TreeViewModel.kt │ │ │ └── WebViewModel.kt │ └── res │ │ ├── anim │ │ ├── push_bottom_in.xml │ │ ├── push_bottom_out.xml │ │ ├── slide_in_left.xml │ │ ├── slide_in_right.xml │ │ ├── slide_out_left.xml │ │ └── slide_out_right.xml │ │ ├── color │ │ └── bottom_selector.xml │ │ ├── drawable-v21 │ │ ├── flow_selector.xml │ │ ├── item_imgselector.xml │ │ └── item_selector.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xxxhdpi │ │ ├── collect.png │ │ ├── cxk.jpg │ │ ├── default_project_img.jpg │ │ ├── fab_up.png │ │ ├── ic_account.png │ │ ├── ic_add.png │ │ ├── ic_back.png │ │ ├── ic_clear.png │ │ ├── ic_close.png │ │ ├── ic_collect.png │ │ ├── ic_collected.png │ │ ├── ic_custom_drawable.png │ │ ├── ic_delete.png │ │ ├── ic_demo.png │ │ ├── ic_done.png │ │ ├── ic_favorite.png │ │ ├── ic_guize.png │ │ ├── ic_history.png │ │ ├── ic_more.png │ │ ├── ic_password_see.png │ │ ├── ic_password_see_on.png │ │ ├── ic_right.png │ │ ├── ic_search.png │ │ ├── ic_tag.png │ │ ├── ic_yiguoqi.png │ │ ├── jairu.png │ │ ├── jifen.png │ │ ├── load_empty.png │ │ ├── load_error.png │ │ ├── menu_main.png │ │ ├── menu_me.png │ │ ├── menu_project.png │ │ ├── menu_public.png │ │ ├── menu_tree.png │ │ ├── renwu.png │ │ ├── shezhi.png │ │ ├── web.png │ │ └── wenzhang.png │ │ ├── drawable │ │ ├── bottom_selector.xml │ │ ├── button_shap.xml │ │ ├── cardview_shap.xml │ │ ├── edit_shape.xml │ │ ├── flow_selector.xml │ │ ├── forground_shap.xml │ │ ├── ic_launcher_background.xml │ │ ├── item_imgselector.xml │ │ ├── item_selector.xml │ │ ├── keyvisibily_selector.xml │ │ ├── title_lable_shap.xml │ │ └── title_lable_shap1.xml │ │ ├── layout │ │ ├── activity_error.xml │ │ ├── activity_main.xml │ │ ├── activity_test.xml │ │ ├── activity_welcome.xml │ │ ├── banner_itemhome.xml │ │ ├── banner_itemwelcome.xml │ │ ├── customview.xml │ │ ├── flow_layout.xml │ │ ├── fragment_addtodo.xml │ │ ├── fragment_collect.xml │ │ ├── fragment_home.xml │ │ ├── fragment_integral.xml │ │ ├── fragment_list.xml │ │ ├── fragment_login.xml │ │ ├── fragment_lookinfo.xml │ │ ├── fragment_main.xml │ │ ├── fragment_me.xml │ │ ├── fragment_register.xml │ │ ├── fragment_search.xml │ │ ├── fragment_share_ariticle.xml │ │ ├── fragment_system.xml │ │ ├── fragment_viewpager.xml │ │ ├── fragment_web.xml │ │ ├── include_banner.xml │ │ ├── include_list.xml │ │ ├── include_recyclerview.xml │ │ ├── include_toolbar.xml │ │ ├── include_viewpager.xml │ │ ├── item_ariticle.xml │ │ ├── item_ariticlenew.xml │ │ ├── item_collecturl.xml │ │ ├── item_history.xml │ │ ├── item_icon_preference_preview.xml │ │ ├── item_integral.xml │ │ ├── item_integral_history.xml │ │ ├── item_project.xml │ │ ├── item_share_ariticle.xml │ │ ├── item_system.xml │ │ ├── item_todo.xml │ │ ├── item_todo_dialog.xml │ │ ├── layout_collect_view_checked.xml │ │ ├── layout_collect_view_unchecked.xml │ │ ├── layout_custom_progress_dialog_view.xml │ │ ├── layout_empty.xml │ │ ├── layout_error.xml │ │ ├── layout_fotter_loadmore.xml │ │ ├── layout_loading.xml │ │ └── todo_dialog.xml │ │ ├── menu │ │ ├── home_menu.xml │ │ ├── integral_menu.xml │ │ ├── menu_navigation.xml │ │ ├── menu_search.xml │ │ ├── share_menu.xml │ │ ├── todo_menu.xml │ │ └── web_menu.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── navigation │ │ └── main_navation.xml │ │ ├── values-sw360dp-v13 │ │ └── values-preference.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── network_security_config.xml │ │ └── root_preferences.xml │ └── test │ └── java │ └── me │ └── hgj │ └── jetpackmvvm │ └── demo │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | JetpackMvvmDemo -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/dictionaries/Administrator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | gson 5 | hegaojian 6 | jetpack 7 | mvvm 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /JetpackMvvm/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /JetpackMvvm/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/JetpackMvvm/consumer-rules.pro -------------------------------------------------------------------------------- /JetpackMvvm/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | 2 | -optimizationpasses 5 3 | 4 | -dontusemixedcaseclassnames 5 | 6 | -dontskipnonpubliclibraryclasses 7 | 8 | -dontskipnonpubliclibraryclassmembers 9 | 10 | -dontpreverify 11 | 12 | -verbose 13 | -printmapping priguardMapping.txt 14 | 15 | -optimizations !code/simplification/artithmetic,!field/*,!class/merging/* 16 | 17 | ################common############### 18 | 19 | 20 | #实体类不参与混淆 21 | -keep class * implements android.os.Parcelable { 22 | public static final android.os.Parcelable$Creator *; 23 | } 24 | -keepnames class * implements java.io.Serializable 25 | -keepattributes Signature 26 | -keep class **.R$* {*;} 27 | -ignorewarnings 28 | -keepclassmembers class **.R$* { 29 | public static ; 30 | } 31 | 32 | -keepclasseswithmembernames class * { # 保持native方法不被混淆 33 | native ; 34 | } 35 | 36 | -keepclassmembers enum * { # 使用enum类型时需要注意避免以下两个方法混淆,因为enum类的特殊性,以下两个方法会被反射调用, 37 | public static **[] values(); 38 | public static ** valueOf(java.lang.String); 39 | } 40 | 41 | ################support############### 42 | -keep class android.support.** { *; } 43 | -keep interface android.support.** { *; } 44 | -dontwarn android.support.** 45 | 46 | -keep class com.google.android.material.** {*;} 47 | -keep class androidx.** {*;} 48 | -keep public class * extends androidx.** 49 | -keep interface androidx.** {*;} 50 | -dontwarn com.google.android.material.** 51 | -dontnote com.google.android.material.** 52 | -dontwarn androidx.** 53 | 54 | ################retrofit############### 55 | -dontwarn retrofit2.** 56 | -keep class retrofit2.** { *; } 57 | -keepattributes Signature 58 | -keepattributes Exceptions 59 | ################RxPermissions################# 60 | -keep class com.tbruyelle.rxpermissions2.** { *; } 61 | -keep interface com.tbruyelle.rxpermissions2.** { *; } 62 | 63 | ################ ViewBinding & DataBinding ############### 64 | -keepclassmembers class * implements androidx.viewbinding.ViewBinding { 65 | public static * inflate(android.view.LayoutInflater); 66 | public static * inflate(android.view.LayoutInflater, android.view.ViewGroup, boolean); 67 | public static * bind(android.view.View); 68 | } 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/base/BaseApp.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.base 2 | 3 | import android.app.Application 4 | import androidx.lifecycle.ViewModelProvider 5 | import androidx.lifecycle.ViewModelStore 6 | import androidx.lifecycle.ViewModelStoreOwner 7 | 8 | /** 9 | * 作者 : hegaojian 10 | * 时间 : 2019/12/14 11 | * 描述 : 对于写BaseApp,其实我是拒绝的,但是需要提供一个很有用的功能--在Activity/fragment中获取Application级别的ViewModel 12 | * 所以才硬着头皮加的,如果你不想继承BaseApp,又想获取Application级别的ViewModel功能 13 | * 那么你可以复制该类的代码到你的自定义Application中去,然后可以自己写获取ViewModel的拓展函数即 : 14 | * GetViewModelExt类的getAppViewModel方法 15 | */ 16 | 17 | open class BaseApp : Application(), ViewModelStoreOwner { 18 | 19 | private lateinit var mAppViewModelStore: ViewModelStore 20 | 21 | private var mFactory: ViewModelProvider.Factory? = null 22 | 23 | override fun getViewModelStore(): ViewModelStore { 24 | return mAppViewModelStore 25 | } 26 | 27 | override fun onCreate() { 28 | super.onCreate() 29 | mAppViewModelStore = ViewModelStore() 30 | } 31 | 32 | /** 33 | * 获取一个全局的ViewModel 34 | */ 35 | fun getAppViewModelProvider(): ViewModelProvider { 36 | return ViewModelProvider(this, this.getAppFactory()) 37 | } 38 | 39 | private fun getAppFactory(): ViewModelProvider.Factory { 40 | if (mFactory == null) { 41 | mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(this) 42 | } 43 | return mFactory as ViewModelProvider.Factory 44 | } 45 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/base/activity/BaseVmDbActivity.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.base.activity 2 | 3 | import android.view.View 4 | import androidx.databinding.ViewDataBinding 5 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 6 | import me.hgj.jetpackmvvm.ext.inflateBindingWithGeneric 7 | 8 | /** 9 | * 作者 : hegaojian 10 | * 时间 : 2019/12/12 11 | * 描述 : 包含ViewModel 和Databind ViewModelActivity基类,把ViewModel 和Databind注入进来了 12 | * 需要使用Databind的清继承它 13 | */ 14 | abstract class BaseVmDbActivity : BaseVmActivity() { 15 | 16 | override fun layoutId() = 0 17 | 18 | lateinit var mDatabind: DB 19 | 20 | /** 21 | * 创建DataBinding 22 | */ 23 | override fun initDataBind(): View? { 24 | mDatabind = inflateBindingWithGeneric(layoutInflater) 25 | return mDatabind.root 26 | } 27 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/base/activity/BaseVmVbActivity.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.base.activity 2 | 3 | import android.view.View 4 | import androidx.viewbinding.ViewBinding 5 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 6 | import me.hgj.jetpackmvvm.ext.inflateBindingWithGeneric 7 | 8 | /** 9 | * 作者 : hegaojian 10 | * 时间 : 2019/12/12 11 | * 描述 : 包含 ViewModel 和 ViewBinding ViewModelActivity基类,把ViewModel 和 ViewBinding 注入进来了 12 | * 需要使用 ViewBinding 的清继承它 13 | */ 14 | abstract class BaseVmVbActivity : BaseVmActivity() { 15 | 16 | override fun layoutId(): Int = 0 17 | 18 | lateinit var mViewBind: VB 19 | 20 | /** 21 | * 创建DataBinding 22 | */ 23 | override fun initDataBind(): View? { 24 | mViewBind = inflateBindingWithGeneric(layoutInflater) 25 | return mViewBind.root 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/base/fragment/BaseVmDbFragment.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.base.fragment 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.databinding.ViewDataBinding 8 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 9 | import me.hgj.jetpackmvvm.ext.inflateBindingWithGeneric 10 | 11 | /** 12 | * 作者 : hegaojian 13 | * 时间 : 2019/12/12 14 | * 描述 : ViewModelFragment基类,自动把ViewModel注入Fragment和Databind注入进来了 15 | * 需要使用Databind的清继承它 16 | */ 17 | abstract class BaseVmDbFragment : BaseVmFragment() { 18 | 19 | override fun layoutId() = 0 20 | 21 | //该类绑定的ViewDataBinding 22 | private var _binding: DB? = null 23 | val mDatabind: DB get() = _binding!! 24 | 25 | override fun onCreateView( 26 | inflater: LayoutInflater, 27 | container: ViewGroup?, 28 | savedInstanceState: Bundle? 29 | ): View? { 30 | _binding = inflateBindingWithGeneric(inflater,container,false) 31 | return mDatabind.root 32 | } 33 | 34 | override fun onDestroyView() { 35 | super.onDestroyView() 36 | _binding = null 37 | } 38 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/base/fragment/BaseVmVbFragment.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.base.fragment 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.viewbinding.ViewBinding 8 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 9 | import me.hgj.jetpackmvvm.ext.inflateBindingWithGeneric 10 | 11 | /** 12 | * 作者 : hegaojian 13 | * 时间 : 2019/12/12 14 | * 描述 : ViewModelFragment基类,自动把ViewModel注入Fragment和 ViewBinding 注入进来了 15 | * 需要使用 ViewBinding 的清继承它 16 | */ 17 | abstract class BaseVmVbFragment : BaseVmFragment() { 18 | 19 | override fun layoutId() = 0 20 | 21 | //该类绑定的 ViewBinding 22 | private var _binding: VB? = null 23 | val mViewBind: VB get() = _binding!! 24 | 25 | override fun onCreateView( 26 | inflater: LayoutInflater, 27 | container: ViewGroup?, 28 | savedInstanceState: Bundle? 29 | ): View? { 30 | _binding = inflateBindingWithGeneric(inflater,container,false) 31 | return mViewBind.root 32 | } 33 | 34 | override fun onDestroyView() { 35 | super.onDestroyView() 36 | _binding = null 37 | } 38 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/base/viewmodel/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.base.viewmodel 2 | 3 | import androidx.lifecycle.ViewModel 4 | import me.hgj.jetpackmvvm.callback.livedata.event.EventLiveData 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2019/12/12 9 | * 描述 : ViewModel的基类 使用ViewModel类,放弃AndroidViewModel,原因:用处不大 完全有其他方式获取Application上下文 10 | */ 11 | open class BaseViewModel : ViewModel() { 12 | 13 | val loadingChange: UiLoadingChange by lazy { UiLoadingChange() } 14 | 15 | /** 16 | * 内置封装好的可通知Activity/fragment 显示隐藏加载框 因为需要跟网络请求显示隐藏loading配套才加的,不然我加他个鸡儿加 17 | */ 18 | inner class UiLoadingChange { 19 | //显示加载框 20 | val showDialog by lazy { EventLiveData() } 21 | //隐藏 22 | val dismissDialog by lazy { EventLiveData() } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/databind/BooleanObservableField.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.databind 2 | 3 | import androidx.databinding.ObservableField 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 : 自定义的Boolean类型ObservableField 提供了默认值,避免取值的时候还要判空 9 | */ 10 | class BooleanObservableField(value: Boolean = false) : ObservableField(value) { 11 | override fun get(): Boolean { 12 | return super.get()!! 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/databind/ByteObservableField.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.databind 2 | 3 | import androidx.databinding.ObservableField 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 :自定义的 Byte 类型 ObservableField 提供了默认值,避免取值的时候还要判空 9 | */ 10 | class ByteObservableField(value: Byte = 0) : ObservableField(value) { 11 | 12 | override fun get(): Byte { 13 | return super.get()!! 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/databind/DoubleObservableField.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.databind 2 | 3 | import androidx.databinding.ObservableField 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 :自定义的Int类型 ObservableField 提供了默认值,避免取值的时候还要判空 9 | */ 10 | class DoubleObservableField(value: Double = 0.0) : ObservableField(value) { 11 | 12 | override fun get(): Double { 13 | return super.get()!! 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/databind/FloatObservableField.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.databind 2 | 3 | import androidx.databinding.ObservableField 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 :自定义的 Float 类型 ObservableField 提供了默认值,避免取值的时候还要判空 9 | */ 10 | class FloatObservableField(value: Float = 0f) : ObservableField(value) { 11 | 12 | override fun get(): Float { 13 | return super.get()!! 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/databind/IntObservableField.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.databind 2 | 3 | import androidx.databinding.ObservableField 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 :自定义的Int类型 ObservableField 提供了默认值,避免取值的时候还要判空 9 | */ 10 | class IntObservableField(value: Int = 0) : ObservableField(value) { 11 | 12 | override fun get(): Int { 13 | return super.get()!! 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/databind/ShortObservableField.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.databind 2 | 3 | import androidx.databinding.ObservableField 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 :自定义的 Short 类型 ObservableField 提供了默认值,避免取值的时候还要判空 9 | */ 10 | class ShortObservableField(value: Short = 0) : ObservableField(value) { 11 | 12 | override fun get(): Short { 13 | return super.get()!! 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/databind/StringObservableField.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.databind 2 | 3 | import androidx.databinding.ObservableField 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 :自定义的String类型 ObservableField 提供了默认值,避免取值的时候还要判空 9 | */ 10 | open class StringObservableField(value: String = "") : ObservableField(value) { 11 | 12 | override fun get(): String { 13 | return super.get()!! 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/BooleanLiveData.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.livedata 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2019/12/17 9 | * 描述 :自定义的Boolean类型 MutableLiveData 提供了默认值,避免取值的时候还要判空 10 | */ 11 | class BooleanLiveData : MutableLiveData() { 12 | 13 | override fun getValue(): Boolean { 14 | return super.getValue() ?: false 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/ByteLiveData.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.livedata 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2019/12/17 9 | * 描述 :自定义的Short类型 MutableLiveData 提供了默认值,避免取值的时候还要判空 10 | */ 11 | class ByteLiveData : MutableLiveData() { 12 | override fun getValue(): Byte { 13 | return super.getValue() ?: 0 14 | } 15 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/DoubleLiveData.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.livedata 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2019/12/17 9 | * 描述 :自定义的Double类型 MutableLiveData 提供了默认值,避免取值的时候还要判空 10 | */ 11 | class DoubleLiveData : MutableLiveData() { 12 | override fun getValue(): Double { 13 | return super.getValue() ?: 0.0 14 | } 15 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/FloatLiveData.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.livedata 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2019/12/17 9 | * 描述 :自定义的Float类型 MutableLiveData 提供了默认值,避免取值的时候还要判空 10 | */ 11 | class FloatLiveData(value: Float = 0f) : MutableLiveData(value) { 12 | override fun getValue(): Float { 13 | return super.getValue()!! 14 | } 15 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/IntLiveData.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.livedata 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 :自定义的Boolean类型 MutableLiveData 提供了默认值,避免取值的时候还要判空 9 | */ 10 | class IntLiveData : MutableLiveData() { 11 | 12 | override fun getValue(): Int { 13 | return super.getValue() ?: 0 14 | } 15 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/ShortLiveData.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.livedata 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2019/12/17 9 | * 描述 :自定义的Short类型 MutableLiveData 提供了默认值,避免取值的时候还要判空 10 | */ 11 | class ShortLiveData : MutableLiveData() { 12 | override fun getValue(): Short { 13 | return super.getValue() ?: 0 14 | } 15 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/StringLiveData.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.livedata 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/17 8 | * 描述 :自定义的Double类型 MutableLiveData 提供了默认值,避免取值的时候还要判空 9 | */ 10 | class StringLiveData : MutableLiveData() { 11 | 12 | override fun getValue(): String { 13 | return super.getValue() ?: "" 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/event/EventLiveData.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.callback.livedata.event 2 | 3 | import com.kunminx.architecture.ui.callback.UnPeekLiveData 4 | 5 | /** 6 | * 最新版的发送消息LiveData使用 https://github.com/KunMinX/UnPeek-LiveData 的最新版,因为跟其他类名(UnPeekLiveData)一致 所以继承换了一个名字 7 | * 在Activity中observe 调用observeInActivity 在Fragment中使用调用 observeInFragment 8 | * 具体写法请参考 https://github.com/KunMinX/UnPeek-LiveData的示例 9 | */ 10 | class EventLiveData : UnPeekLiveData() -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/NavigationExt.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import androidx.fragment.app.Fragment 6 | import androidx.navigation.NavController 7 | import androidx.navigation.Navigation 8 | import androidx.navigation.fragment.NavHostFragment 9 | 10 | /** 11 | * 作者 : hegaojian 12 | * 时间 : 2020/5/2 13 | * 描述 : 14 | */ 15 | fun Fragment.nav(): NavController { 16 | return NavHostFragment.findNavController(this) 17 | } 18 | 19 | fun nav(view: View): NavController { 20 | return Navigation.findNavController(view) 21 | } 22 | 23 | var lastNavTime = 0L 24 | 25 | /** 26 | * 防止短时间内多次快速跳转Fragment出现的bug 27 | * @param resId 跳转的action Id 28 | * @param bundle 传递的参数 29 | * @param interval 多少毫秒内不可重复点击 默认0.5秒 30 | */ 31 | fun NavController.navigateAction(resId: Int, bundle: Bundle? = null, interval: Long = 500) { 32 | val currentTime = System.currentTimeMillis() 33 | if (currentTime >= lastNavTime + interval) { 34 | lastNavTime = currentTime 35 | try { 36 | navigate(resId, bundle) 37 | }catch (ignore:Exception){ 38 | //防止出现 当 fragment 中 action 的 duration设置为 0 时,连续点击两个不同的跳转会导致如下崩溃 #issue53 39 | } 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/download/DownLoadPool.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.download 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | import kotlinx.coroutines.cancel 5 | import kotlinx.coroutines.isActive 6 | import java.util.concurrent.ConcurrentHashMap 7 | 8 | 9 | /** 10 | * @author : hgj 11 | * @date : 2020/7/13 12 | */ 13 | 14 | object DownLoadPool { 15 | 16 | 17 | private val scopeMap: ConcurrentHashMap = ConcurrentHashMap() 18 | 19 | //下载位置 20 | private val pathMap: ConcurrentHashMap = ConcurrentHashMap() 21 | 22 | //监听 23 | private val listenerHashMap: ConcurrentHashMap = ConcurrentHashMap() 24 | 25 | fun add(key: String, job: CoroutineScope) { 26 | scopeMap[key] = job 27 | } 28 | 29 | //监听 30 | fun add(key: String, loadListener: OnDownLoadListener) { 31 | listenerHashMap[key] = loadListener 32 | } 33 | 34 | //下载位置 35 | fun add(key: String, path: String) { 36 | pathMap[key] = path 37 | } 38 | 39 | 40 | fun remove(key: String) { 41 | pause(key) 42 | scopeMap.remove(key) 43 | listenerHashMap.remove(key) 44 | pathMap.remove(key) 45 | ShareDownLoadUtil.remove(key) 46 | } 47 | 48 | 49 | fun pause(key: String) { 50 | val scope = scopeMap[key] 51 | if (scope != null && scope.isActive) { 52 | scope.cancel() 53 | } 54 | } 55 | 56 | fun removeExitSp(key: String) { 57 | scopeMap.remove(key) 58 | } 59 | 60 | 61 | fun getScopeFromKey(key: String): CoroutineScope? { 62 | return scopeMap[key] 63 | } 64 | 65 | fun getListenerFromKey(key: String): OnDownLoadListener? { 66 | return listenerHashMap[key] 67 | } 68 | 69 | fun getPathFromKey(key: String): String? { 70 | return pathMap[key] 71 | } 72 | 73 | fun getListenerMap(): ConcurrentHashMap { 74 | return listenerHashMap 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/download/DownLoadProgressListener.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.download 2 | 3 | /** 4 | * @author : hgj 5 | * @date : 2020/7/13 6 | */ 7 | 8 | interface DownLoadProgressListener { 9 | 10 | /** 11 | * 下载进度 12 | * @param key url 13 | * @param progress 进度 14 | * @param read 读取 15 | * @param count 总共长度 16 | * @param done 是否完成 17 | */ 18 | fun onUpdate( key: String,progress: Int, read: Long,count: Long,done: Boolean) 19 | } 20 | 21 | 22 | interface OnDownLoadListener : DownLoadProgressListener { 23 | 24 | //等待下载 25 | fun onDownLoadPrepare(key: String) 26 | 27 | //下载失败 28 | fun onDownLoadError(key: String, throwable: Throwable) 29 | 30 | //下载成功 31 | fun onDownLoadSuccess(key: String, path: String,size:Long) 32 | 33 | //下载暂停 34 | fun onDownLoadPause(key: String) 35 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/download/DownLoadService.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.download 2 | 3 | import okhttp3.ResponseBody 4 | import retrofit2.Response 5 | import retrofit2.http.GET 6 | import retrofit2.http.Header 7 | import retrofit2.http.Streaming 8 | import retrofit2.http.Url 9 | 10 | /** 11 | * @author : hgj 12 | * @date : 2020/7/13 13 | * 14 | */ 15 | interface DownLoadService { 16 | @Streaming 17 | @GET 18 | suspend fun downloadFile( 19 | @Header("RANGE") start: String, 20 | @Url url: String 21 | ): Response 22 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/download/DownloadResultState.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.download 2 | 3 | /** 4 | * @author : hgj 5 | * @date : 2020/7/13 6 | */ 7 | sealed class DownloadResultState { 8 | 9 | companion object { 10 | 11 | fun onPending(): DownloadResultState = Pending 12 | 13 | fun onProgress(soFarBytes: Long, totalBytes: Long, progress: Int): DownloadResultState = Progress(soFarBytes, totalBytes,progress) 14 | 15 | fun onSuccess(filePath: String,totalBytes:Long): DownloadResultState = Success(filePath,totalBytes) 16 | 17 | fun onPause(): DownloadResultState = Pause 18 | 19 | fun onError(errorMsg: String): DownloadResultState = Error(errorMsg) 20 | } 21 | 22 | object Pending : DownloadResultState() 23 | data class Progress(val soFarBytes: Long, val totalBytes: Long,val progress: Int) : DownloadResultState() 24 | data class Success(val filePath: String,val totalBytes:Long) : DownloadResultState() 25 | object Pause : DownloadResultState() 26 | data class Error(val errorMsg: String) : DownloadResultState() 27 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/download/FileDownloaderExt.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.download 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | /** 6 | * @author : hgj 7 | * @date : 2020/6/30 8 | * 9 | */ 10 | 11 | fun downLoadExt(downloadResultState: MutableLiveData): OnDownLoadListener { 12 | return object : OnDownLoadListener { 13 | override fun onDownLoadPrepare(key: String) { 14 | //开始下载 15 | downloadResultState.postValue(DownloadResultState.onPending()) 16 | } 17 | 18 | override fun onDownLoadError(key: String, throwable: Throwable) { 19 | //下载错误 20 | downloadResultState.postValue(DownloadResultState.onError(throwable.message ?: "下载错误")) 21 | } 22 | 23 | override fun onDownLoadSuccess(key: String, path: String, size: Long) { 24 | //下载成功 25 | downloadResultState.postValue(DownloadResultState.onSuccess(path, size)) 26 | } 27 | 28 | override fun onDownLoadPause(key: String) { 29 | //下载暂停 30 | downloadResultState.postValue(DownloadResultState.onPause()) 31 | } 32 | 33 | override fun onUpdate(key: String, progress: Int, read: Long, count: Long, done: Boolean) { 34 | //正在下载 35 | downloadResultState.postValue(DownloadResultState.onProgress(read, count, progress)) 36 | } 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/download/ShareDownLoadUtil.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.download 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import android.os.Build 6 | import me.hgj.jetpackmvvm.base.appContext 7 | 8 | /** 9 | * @author : hgj 10 | * @date : 2020/7/13 11 | */ 12 | object ShareDownLoadUtil { 13 | 14 | private var path = Build.BRAND + "_" + Build.MODEL + "_" + "download_sp" 15 | private val sp: SharedPreferences 16 | 17 | 18 | init { 19 | sp = appContext.getSharedPreferences(path, Context.MODE_PRIVATE) 20 | } 21 | 22 | 23 | fun setPath(path: String) { 24 | ShareDownLoadUtil.path = path 25 | } 26 | 27 | fun putBoolean(key: String, value: Boolean) { 28 | sp.edit().putBoolean(key, value).apply() 29 | } 30 | 31 | fun getBoolean(key: String, defValue: Boolean): Boolean { 32 | return sp.getBoolean(key, defValue) 33 | } 34 | 35 | fun putString(key: String, value: String) { 36 | sp.edit().putString(key, value).apply() 37 | } 38 | 39 | fun getString(key: String, defValue: String): String? { 40 | return sp.getString(key, defValue) 41 | } 42 | 43 | fun putInt(key: String, value: Int) { 44 | sp.edit().putInt(key, value).apply() 45 | } 46 | 47 | fun getInt(key: String, defValue: Int): Int { 48 | return sp.getInt(key, defValue) 49 | } 50 | 51 | fun putLong(key: String?, value: Long) { 52 | sp.edit().putLong(key, value).apply() 53 | } 54 | 55 | fun getLong(key: String, defValue: Long): Long { 56 | return sp.getLong(key, defValue) 57 | } 58 | 59 | fun remove(key: String) { 60 | sp.edit().remove(key).apply() 61 | } 62 | 63 | fun clear() { 64 | sp.edit().clear().apply() 65 | } 66 | 67 | 68 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/lifecycle/KtxActivityManger.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.lifecycle 2 | 3 | import android.app.Activity 4 | import java.util.* 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2021/6/8 9 | * 描述 : 10 | */ 11 | object KtxActivityManger { 12 | //activity集合 13 | private val mActivityList = LinkedList() 14 | 15 | //当前activity 16 | val currentActivity: Activity? 17 | get() = 18 | if (mActivityList.isEmpty()) null 19 | else mActivityList.last 20 | 21 | /** 22 | * activity入栈 23 | * @param activity Activity 24 | */ 25 | fun pushActivity(activity: Activity) { 26 | if (mActivityList.contains(activity)) { 27 | if (mActivityList.last != activity) { 28 | mActivityList.remove(activity) 29 | mActivityList.add(activity) 30 | } 31 | } else { 32 | mActivityList.add(activity) 33 | } 34 | } 35 | 36 | /** 37 | * activity出栈 38 | * @param activity Activity 39 | */ 40 | fun popActivity(activity: Activity) { 41 | mActivityList.remove(activity) 42 | } 43 | 44 | /** 45 | * 关闭当前activity 46 | */ 47 | fun finishCurrentActivity() { 48 | currentActivity?.finish() 49 | } 50 | 51 | /** 52 | * 关闭传入的activity 53 | * @param activity Activity 54 | */ 55 | fun finishActivity(activity: Activity) { 56 | mActivityList.remove(activity) 57 | activity.finish() 58 | } 59 | 60 | /** 61 | * 关闭传入的activity类名 62 | * @param clazz Class<*> 63 | */ 64 | fun finishActivity(clazz: Class<*>) { 65 | for (activity in mActivityList) { 66 | if (activity.javaClass == clazz) { 67 | mActivityList.remove(activity) 68 | activity.finish() 69 | return 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * 关闭所有的activity 76 | */ 77 | fun finishAllActivity() { 78 | for (activity in mActivityList) { 79 | activity.finish() 80 | } 81 | mActivityList.clear() 82 | } 83 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/lifecycle/KtxAppLifeObserver.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.lifecycle 2 | 3 | import androidx.lifecycle.Lifecycle 4 | import androidx.lifecycle.LifecycleObserver 5 | import androidx.lifecycle.OnLifecycleEvent 6 | import me.hgj.jetpackmvvm.callback.livedata.BooleanLiveData 7 | 8 | /** 9 | * 作者 : hegaojian 10 | * 时间 : 20120/1/7 11 | * 描述 : 12 | */ 13 | object KtxAppLifeObserver : LifecycleObserver { 14 | 15 | var isForeground = BooleanLiveData() 16 | 17 | //在前台 18 | @OnLifecycleEvent(Lifecycle.Event.ON_START) 19 | private fun onForeground() { 20 | isForeground.value = true 21 | } 22 | 23 | //在后台 24 | @OnLifecycleEvent(Lifecycle.Event.ON_STOP) 25 | private fun onBackground() { 26 | isForeground.value = false 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/lifecycle/KtxHandler.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.lifecycle 2 | 3 | import android.os.Handler 4 | import androidx.lifecycle.Lifecycle 5 | import androidx.lifecycle.LifecycleObserver 6 | import androidx.lifecycle.LifecycleOwner 7 | import androidx.lifecycle.OnLifecycleEvent 8 | 9 | /** 10 | * 作者 : hegaojian 11 | * 时间 : 20120/1/7 12 | * 描述 : 13 | */ 14 | class KtxHandler(lifecycleOwner: LifecycleOwner, callback: Callback) : Handler(callback), LifecycleObserver { 15 | 16 | private val mLifecycleOwner: LifecycleOwner = lifecycleOwner 17 | 18 | init { 19 | lifecycleOwner.lifecycle.addObserver(this) 20 | } 21 | 22 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 23 | private fun onDestroy() { 24 | removeCallbacksAndMessages(null) 25 | mLifecycleOwner.lifecycle.removeObserver(this) 26 | } 27 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/lifecycle/KtxLifeCycleCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.lifecycle 2 | 3 | import android.app.Activity 4 | import android.app.Application 5 | import android.os.Bundle 6 | import me.hgj.jetpackmvvm.ext.util.logd 7 | 8 | /** 9 | * 作者 : hegaojian 10 | * 时间 : 20120/1/7 11 | * 描述 : 12 | */ 13 | class KtxLifeCycleCallBack : Application.ActivityLifecycleCallbacks { 14 | 15 | override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { 16 | KtxActivityManger.pushActivity(activity) 17 | "onActivityCreated : ${activity.localClassName}".logd() 18 | } 19 | override fun onActivityStarted(activity: Activity) { 20 | "onActivityStarted : ${activity.localClassName}".logd() 21 | } 22 | 23 | override fun onActivityResumed(activity: Activity) { 24 | "onActivityResumed : ${activity.localClassName}".logd() 25 | } 26 | 27 | override fun onActivityPaused(activity: Activity) { 28 | "onActivityPaused : ${activity.localClassName}".logd() 29 | } 30 | 31 | 32 | override fun onActivityDestroyed(activity: Activity) { 33 | "onActivityDestroyed : ${activity.localClassName}".logd() 34 | KtxActivityManger.popActivity(activity) 35 | } 36 | 37 | override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { 38 | 39 | } 40 | 41 | override fun onActivityStopped(activity: Activity) { 42 | "onActivityStopped : ${activity.localClassName}".logd() 43 | } 44 | 45 | 46 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/util/LogExt.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.util 2 | 3 | import android.util.Log 4 | 5 | const val TAG = "JetpackMvvm" 6 | 7 | /** 8 | * 9 | * 是否需要开启打印日志,默认打开,1.1.7-1.1.8版本是默认关闭的(1.0.0-1.1.6没有这个字段,框架在远程依赖下,直接不打印log),但是默认关闭后很多人反馈都没有日志,好吧,我的我的 10 | * 根据true|false 控制网络请求日志和该框架产生的打印 11 | */ 12 | var jetpackMvvmLog = true 13 | 14 | private enum class LEVEL { 15 | V, D, I, W, E 16 | } 17 | 18 | fun String.logv(tag: String = TAG) = 19 | log(LEVEL.V, tag, this) 20 | fun String.logd(tag: String = TAG) = 21 | log(LEVEL.D, tag, this) 22 | fun String.logi(tag: String = TAG) = 23 | log(LEVEL.I, tag, this) 24 | fun String.logw(tag: String = TAG) = 25 | log(LEVEL.W, tag, this) 26 | fun String.loge(tag: String = TAG) = 27 | log(LEVEL.E, tag, this) 28 | 29 | private fun log(level: LEVEL, tag: String, message: String) { 30 | if (!jetpackMvvmLog) return 31 | when (level) { 32 | LEVEL.V -> Log.v(tag, message) 33 | LEVEL.D -> Log.d(tag, message) 34 | LEVEL.I -> Log.i(tag, message) 35 | LEVEL.W -> Log.w(tag, message) 36 | LEVEL.E -> Log.e(tag, message) 37 | } 38 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/util/StringExt.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.util 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.google.gson.Gson 5 | import java.util.regex.Pattern 6 | 7 | /** 8 | * 是否为手机号 0开头 12开头的不支持 9 | */ 10 | fun String?.isPhone(): Boolean { 11 | return this?.let { 12 | Pattern.matches(it, "0?(13|14|15|16|17|18|19)[0-9]{9}") 13 | }?:let { 14 | false 15 | } 16 | } 17 | 18 | /** 19 | * 是否为座机号 20 | */ 21 | fun String?.isTel(): Boolean { 22 | return this?.let { 23 | val matcher1 = Pattern.matches("^0(10|2[0-5|789]|[3-9]\\d{2})\\d{7,8}\$", this) 24 | val matcher2 = Pattern.matches("^0(10|2[0-5|789]|[3-9]\\d{2})-\\d{7,8}$", this) 25 | val matcher3 = Pattern.matches("^400\\d{7,8}$", this) 26 | val matcher4 = Pattern.matches("^400-\\d{7,8}$", this) 27 | val matcher5 = Pattern.matches("^800\\d{7,8}$", this) 28 | val matcher6 = Pattern.matches("^800-\\d{7,8}$", this) 29 | return matcher1 || matcher2 || matcher3 || matcher4 || matcher5 || matcher6 30 | }?:let { 31 | false 32 | } 33 | } 34 | 35 | /** 36 | * 是否为邮箱号 37 | */ 38 | fun String?.isEmail(): Boolean { 39 | return this?.let { 40 | Pattern.matches(this, "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$") 41 | }?:let { 42 | false 43 | } 44 | } 45 | 46 | /** 47 | * 将对象转为JSON字符串 48 | */ 49 | fun Any?.toJson():String{ 50 | return Gson().toJson(this) 51 | } 52 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/ext/view/EditTextViewExt.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.ext.view 2 | 3 | import android.text.Editable 4 | import android.text.TextWatcher 5 | import android.widget.EditText 6 | import android.widget.TextView 7 | 8 | /** 9 | * 优化输入框 10 | */ 11 | fun EditText.afterTextChange(afterTextChanged: (String) -> Unit) { 12 | 13 | this.addTextChangedListener(object : TextWatcher { 14 | override fun afterTextChanged(s: Editable?) { 15 | afterTextChanged.invoke(s.toString()) 16 | } 17 | override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { 18 | } 19 | override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { 20 | 21 | } 22 | }) 23 | } 24 | 25 | 26 | /** 27 | * 获取文本 28 | */ 29 | fun EditText.textString(): String { 30 | return this.text.toString() 31 | } 32 | /** 33 | * 获取去除空字符串的文本 34 | */ 35 | fun EditText.textStringTrim(): String { 36 | return this.textString().trim() 37 | } 38 | /** 39 | * 文本是否为空 40 | */ 41 | fun EditText.isEmpty(): Boolean { 42 | return this.textString().isEmpty() 43 | } 44 | /** 45 | * 去空字符串后文本是否为空 46 | */ 47 | fun EditText.isTrimEmpty(): Boolean { 48 | return this.textStringTrim().isEmpty() 49 | } 50 | /** 51 | * 获取文本 52 | */ 53 | fun TextView.textString(): String { 54 | return this.text.toString() 55 | } 56 | /** 57 | * 获取去除空字符串的文本 58 | */ 59 | fun TextView.textStringTrim(): String { 60 | return this.textString().trim() 61 | } 62 | /** 63 | * 文本是否为空 64 | */ 65 | fun TextView.isEmpty(): Boolean { 66 | return this.textString().isEmpty() 67 | } 68 | /** 69 | * 去空字符串后文本是否为空 70 | */ 71 | fun TextView.isTrimEmpty(): Boolean { 72 | return this.textStringTrim().isEmpty() 73 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/navigation/NavHostFragmentHideShow.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.navigation 2 | 3 | import android.view.View 4 | import androidx.navigation.Navigator 5 | import androidx.navigation.fragment.FragmentNavigator 6 | import androidx.navigation.fragment.NavHostFragment 7 | import me.hgj.jetpackmvvm.R 8 | 9 | 10 | /** 11 | * 作者 : hegaojian 12 | * 时间 : 2021/6/29 13 | * 描述 : Hide - Show NavHostFragment 14 | */ 15 | class NavHostFragmentHideShow : NavHostFragment() { 16 | 17 | 18 | /** 19 | * @return 使用自己的FragmentNavigator 20 | */ 21 | override fun createFragmentNavigator(): Navigator { 22 | return FragmentNavigatorHideShow(requireContext(), childFragmentManager, containerId) 23 | } 24 | 25 | 26 | private val containerId: Int 27 | get() { 28 | val id = id 29 | return if (id != 0 && id != View.NO_ID) { 30 | id 31 | // Fallback to using our own ID if this Fragment wasn't added via 32 | // add(containerViewId, Fragment) 33 | } else R.id.nav_host_fragment_container 34 | } 35 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/AppException.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2019/12/17 6 | * 描述 :自定义错误信息异常 7 | */ 8 | class AppException : Exception { 9 | 10 | var errorMsg: String //错误消息 11 | var errCode: Int = 0 //错误码 12 | var errorLog: String? //错误日志 13 | var throwable: Throwable? = null 14 | 15 | constructor(errCode: Int, error: String?, errorLog: String? = "", throwable: Throwable? = null) : super(error) { 16 | this.errorMsg = error ?: "请求失败,请稍后再试" 17 | this.errCode = errCode 18 | this.errorLog = errorLog ?: this.errorMsg 19 | this.throwable = throwable 20 | } 21 | 22 | constructor(error: Error, e: Throwable?) { 23 | errCode = error.getKey() 24 | errorMsg = error.getValue() 25 | errorLog = e?.message 26 | throwable = e 27 | } 28 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/BaseNetworkApi.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network 2 | 3 | import me.jessyan.retrofiturlmanager.RetrofitUrlManager 4 | import okhttp3.OkHttpClient 5 | import retrofit2.Retrofit 6 | 7 | /** 8 | * 作者 : hegaojian 9 | * 时间 : 2019/12/23 10 | * 描述 : 网络请求构建器基类 11 | */ 12 | abstract class BaseNetworkApi { 13 | 14 | fun getApi(serviceClass: Class, baseUrl: String): T { 15 | val retrofitBuilder = Retrofit.Builder() 16 | .baseUrl(baseUrl) 17 | .client(okHttpClient) 18 | return setRetrofitBuilder(retrofitBuilder).build().create(serviceClass) 19 | } 20 | 21 | /** 22 | * 实现重写父类的setHttpClientBuilder方法, 23 | * 在这里可以添加拦截器,可以对 OkHttpClient.Builder 做任意操作 24 | */ 25 | abstract fun setHttpClientBuilder(builder: OkHttpClient.Builder): OkHttpClient.Builder 26 | 27 | /** 28 | * 实现重写父类的setRetrofitBuilder方法, 29 | * 在这里可以对Retrofit.Builder做任意操作,比如添加GSON解析器,Protocol 30 | */ 31 | abstract fun setRetrofitBuilder(builder: Retrofit.Builder): Retrofit.Builder 32 | 33 | /** 34 | * 配置http 35 | */ 36 | private val okHttpClient: OkHttpClient 37 | get() { 38 | var builder = RetrofitUrlManager.getInstance().with(OkHttpClient.Builder()) 39 | builder = setHttpClientBuilder(builder) 40 | return builder.build() 41 | } 42 | } 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/BaseResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2019/12/17 6 | * 描述 : 服务器返回数据的基类 7 | * 如果需要框架帮你做脱壳处理请继承它!!请注意: 8 | * 2.必须实现抽象方法,根据自己的业务判断返回请求结果是否成功 9 | */ 10 | abstract class BaseResponse { 11 | 12 | //抽象方法,用户的基类继承该类时,需要重写该方法 13 | abstract fun isSucces(): Boolean 14 | 15 | abstract fun getResponseData(): T 16 | 17 | abstract fun getResponseCode(): Int 18 | 19 | abstract fun getResponseMsg(): String 20 | 21 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/Error.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2019/12/17 6 | * 描述 : 错误枚举类 7 | */ 8 | enum class Error(private val code: Int, private val err: String) { 9 | 10 | /** 11 | * 未知错误 12 | */ 13 | UNKNOWN(1000, "请求失败,请稍后再试"), 14 | /** 15 | * 解析错误 16 | */ 17 | PARSE_ERROR(1001, "解析错误,请稍后再试"), 18 | /** 19 | * 网络错误 20 | */ 21 | NETWORK_ERROR(1002, "网络连接错误,请稍后重试"), 22 | 23 | /** 24 | * 证书出错 25 | */ 26 | SSL_ERROR(1004, "证书出错,请稍后再试"), 27 | 28 | /** 29 | * 连接超时 30 | */ 31 | TIMEOUT_ERROR(1006, "网络连接超时,请稍后重试"); 32 | 33 | fun getValue(): String { 34 | return err 35 | } 36 | 37 | fun getKey(): Int { 38 | return code 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/interceptor/CacheInterceptor.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network.interceptor 2 | 3 | import me.hgj.jetpackmvvm.base.appContext 4 | import me.hgj.jetpackmvvm.network.NetworkUtil 5 | import okhttp3.CacheControl 6 | import okhttp3.Interceptor 7 | import okhttp3.Response 8 | 9 | /** 10 | * 作者 : hegaojian 11 | * 时间 : 2019/12/23 12 | * 描述 : 缓存拦截器 13 | * @param day 缓存天数 默认7天 14 | */ 15 | class CacheInterceptor(var day: Int = 7) : Interceptor { 16 | override fun intercept(chain: Interceptor.Chain): Response { 17 | var request = chain.request() 18 | if (!NetworkUtil.isNetworkAvailable(appContext)) { 19 | request = request.newBuilder() 20 | .cacheControl(CacheControl.FORCE_CACHE) 21 | .build() 22 | } 23 | val response = chain.proceed(request) 24 | if (!NetworkUtil.isNetworkAvailable(appContext)) { 25 | val maxAge = 60 * 60 26 | response.newBuilder() 27 | .removeHeader("Pragma") 28 | .header("Cache-Control", "public, max-age=$maxAge") 29 | .build() 30 | } else { 31 | val maxStale = 60 * 60 * 24 * day // tolerate 4-weeks stale 32 | response.newBuilder() 33 | .removeHeader("Pragma") 34 | .header("Cache-Control", "public, only-if-cached, max-stale=$maxStale") 35 | .build() 36 | } 37 | return response 38 | } 39 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/interceptor/logging/FormatPrinter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network.interceptor.logging 2 | 3 | import okhttp3.MediaType 4 | import okhttp3.Request 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2020/3/26 9 | * 描述 : 10 | */ 11 | interface FormatPrinter { 12 | /** 13 | * 打印网络请求信息, 当网络请求时 {[okhttp3.RequestBody]} 可以解析的情况 14 | * 15 | * @param request 16 | * @param bodyString 发送给服务器的请求体中的数据(已解析) 17 | */ 18 | fun printJsonRequest(request: Request, bodyString: String) 19 | 20 | /** 21 | * 打印网络请求信息, 当网络请求时 {[okhttp3.RequestBody]} 为 `null` 或不可解析的情况 22 | * 23 | * @param request 24 | */ 25 | fun printFileRequest(request: Request) 26 | 27 | /** 28 | * 打印网络响应信息, 当网络响应时 {[okhttp3.ResponseBody]} 可以解析的情况 29 | * 30 | * @param chainMs 服务器响应耗时(单位毫秒) 31 | * @param isSuccessful 请求是否成功 32 | * @param code 响应码 33 | * @param headers 请求头 34 | * @param contentType 服务器返回数据的数据类型 35 | * @param bodyString 服务器返回的数据(已解析) 36 | * @param segments 域名后面的资源地址 37 | * @param message 响应信息 38 | * @param responseUrl 请求地址 39 | */ 40 | fun printJsonResponse( 41 | chainMs: Long, 42 | isSuccessful: Boolean, 43 | code: Int, 44 | headers: String, 45 | contentType: MediaType?, 46 | bodyString: String?, 47 | segments: List, 48 | message: String, 49 | responseUrl: String 50 | ) 51 | 52 | /** 53 | * 打印网络响应信息, 当网络响应时 {[okhttp3.ResponseBody]} 为 `null` 或不可解析的情况 54 | * 55 | * @param chainMs 服务器响应耗时(单位毫秒) 56 | * @param isSuccessful 请求是否成功 57 | * @param code 响应码 58 | * @param headers 请求头 59 | * @param segments 域名后面的资源地址 60 | * @param message 响应信息 61 | * @param responseUrl 请求地址 62 | */ 63 | fun printFileResponse( 64 | chainMs: Long, 65 | isSuccessful: Boolean, 66 | code: Int, 67 | headers: String, 68 | segments: List, 69 | message: String, 70 | responseUrl: String 71 | ) 72 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/manager/NetState.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network.manager 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/5/2 6 | * 描述 : 网络变化实体类 7 | */ 8 | class NetState( 9 | var isSuccess: Boolean = true 10 | ) -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/manager/NetworkStateManager.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network.manager 2 | 3 | import me.hgj.jetpackmvvm.callback.livedata.event.EventLiveData 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2020/5/2 8 | * 描述 : 网络变化管理者 9 | */ 10 | class NetworkStateManager private constructor() { 11 | 12 | val mNetworkStateCallback = EventLiveData() 13 | 14 | companion object { 15 | val instance: NetworkStateManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { 16 | NetworkStateManager() 17 | } 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/network/manager/NetworkStateReceive.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.network.manager 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.net.ConnectivityManager 7 | import me.hgj.jetpackmvvm.network.NetworkUtil 8 | 9 | /** 10 | * 作者 : hegaojian 11 | * 时间 : 2020/5/2 12 | * 描述 : 网络变化接收器 13 | */ 14 | class NetworkStateReceive : BroadcastReceiver() { 15 | var isInit = true 16 | override fun onReceive(context: Context, intent: Intent) { 17 | if (intent.action == ConnectivityManager.CONNECTIVITY_ACTION) { 18 | if(!isInit){ 19 | if (!NetworkUtil.isNetworkAvailable(context)) { 20 | //收到没有网络时判断之前的值是不是有网络,如果有网络才提示通知 ,防止重复通知 21 | NetworkStateManager.instance.mNetworkStateCallback.value?.let { 22 | if(it.isSuccess){ 23 | //没网 24 | NetworkStateManager.instance.mNetworkStateCallback.value = NetState(isSuccess = false) 25 | } 26 | return 27 | } 28 | NetworkStateManager.instance.mNetworkStateCallback.value = NetState(isSuccess = false) 29 | }else{ 30 | //收到有网络时判断之前的值是不是没有网络,如果没有网络才提示通知 ,防止重复通知 31 | NetworkStateManager.instance.mNetworkStateCallback.value?.let { 32 | if(!it.isSuccess){ 33 | //有网络了 34 | NetworkStateManager.instance.mNetworkStateCallback.value = NetState(isSuccess = true) 35 | } 36 | return 37 | } 38 | NetworkStateManager.instance.mNetworkStateCallback.value = NetState(isSuccess = true) 39 | } 40 | } 41 | isInit = false 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/state/ResultState.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.state 2 | import androidx.lifecycle.MutableLiveData 3 | import me.hgj.jetpackmvvm.network.AppException 4 | import me.hgj.jetpackmvvm.network.BaseResponse 5 | import me.hgj.jetpackmvvm.network.ExceptionHandle 6 | 7 | /** 8 | * 作者 : hegaojian 9 | * 时间 : 2020/4/9 10 | * 描述 : 自定义结果集封装类 11 | */ 12 | sealed class ResultState { 13 | companion object { 14 | fun onAppSuccess(data: T): ResultState = Success(data) 15 | fun onAppLoading(loadingMessage: String): ResultState = Loading(loadingMessage) 16 | fun onAppError(error: AppException): ResultState = Error(error) 17 | } 18 | 19 | data class Loading(val loadingMessage: String) : ResultState() 20 | data class Success(val data: T) : ResultState() 21 | data class Error(val error: AppException) : ResultState() 22 | } 23 | 24 | /** 25 | * 处理返回值 26 | * @param result 请求结果 27 | */ 28 | fun MutableLiveData>.paresResult(result: BaseResponse) { 29 | value = when { 30 | result.isSucces() -> { 31 | ResultState.onAppSuccess(result.getResponseData()) 32 | } 33 | else -> { 34 | ResultState.onAppError(AppException(result.getResponseCode(), result.getResponseMsg())) 35 | } 36 | } 37 | } 38 | 39 | /** 40 | * 不处理返回值 直接返回请求结果 41 | * @param result 请求结果 42 | */ 43 | fun MutableLiveData>.paresResult(result: T) { 44 | value = ResultState.onAppSuccess(result) 45 | } 46 | 47 | /** 48 | * 异常转换异常处理 49 | */ 50 | fun MutableLiveData>.paresException(e: Throwable) { 51 | this.value = ResultState.onAppError(ExceptionHandle.handleException(e)) 52 | } 53 | 54 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/util/LogUtils.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.util 2 | 3 | import android.text.TextUtils 4 | import android.util.Log 5 | import me.hgj.jetpackmvvm.ext.util.jetpackMvvmLog 6 | 7 | /** 8 | * 作者 : hegaojian 9 | * 时间 : 2020/3/26 10 | * 描述 : 11 | */ 12 | object LogUtils { 13 | private const val DEFAULT_TAG = "JetpackMvvm" 14 | fun debugInfo(tag: String?, msg: String?) { 15 | if (!jetpackMvvmLog || TextUtils.isEmpty(msg)) { 16 | return 17 | } 18 | Log.d(tag, msg!!) 19 | } 20 | 21 | fun debugInfo(msg: String?) { 22 | debugInfo( 23 | DEFAULT_TAG, 24 | msg 25 | ) 26 | } 27 | 28 | fun warnInfo(tag: String?, msg: String?) { 29 | if (!jetpackMvvmLog || TextUtils.isEmpty(msg)) { 30 | return 31 | } 32 | Log.w(tag, msg!!) 33 | } 34 | 35 | fun warnInfo(msg: String?) { 36 | warnInfo( 37 | DEFAULT_TAG, 38 | msg 39 | ) 40 | } 41 | 42 | /** 43 | * 这里使用自己分节的方式来输出足够长度的 message 44 | * 45 | * @param tag 标签 46 | * @param msg 日志内容 47 | */ 48 | fun debugLongInfo(tag: String?, msg: String) { 49 | var msg = msg 50 | if (!jetpackMvvmLog || TextUtils.isEmpty(msg)) { 51 | return 52 | } 53 | msg = msg.trim { it <= ' ' } 54 | var index = 0 55 | val maxLength = 3500 56 | var sub: String 57 | while (index < msg.length) { 58 | sub = if (msg.length <= index + maxLength) { 59 | msg.substring(index) 60 | } else { 61 | msg.substring(index, index + maxLength) 62 | } 63 | index += maxLength 64 | Log.d(tag, sub.trim { it <= ' ' }) 65 | } 66 | } 67 | 68 | fun debugLongInfo(msg: String) { 69 | debugLongInfo( 70 | DEFAULT_TAG, 71 | msg 72 | ) 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/util/ProxyDrawable.java: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.util; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.graphics.drawable.StateListDrawable; 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2020/4/10 9 | * 描述 :使用DataBinding时使用该库 https://github.com/whataa/noDrawable 10 | * 只需要复制核心类 ProxyDrawable,Drawables至项目中即可 11 | * 可以减少大量的drawable.xml文件 12 | */ 13 | public class ProxyDrawable extends StateListDrawable { 14 | 15 | private Drawable originDrawable; 16 | 17 | @Override 18 | public void addState(int[] stateSet, Drawable drawable) { 19 | if (stateSet != null && stateSet.length == 1 && stateSet[0] == 0) { 20 | originDrawable = drawable; 21 | } 22 | super.addState(stateSet, drawable); 23 | } 24 | 25 | Drawable getOriginDrawable() { 26 | return originDrawable; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/util/UrlEncoderUtils.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.util 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/3/26 6 | * 描述 : 7 | */ 8 | class UrlEncoderUtils private constructor() { 9 | companion object { 10 | /** 11 | * 判断 str 是否已经 URLEncoder.encode() 过 12 | * 经常遇到这样的情况, 拿到一个 URL, 但是搞不清楚到底要不要 URLEncoder.encode() 13 | * 不做 URLEncoder.encode() 吧, 担心出错, 做 URLEncoder.encode() 吧, 又怕重复了 14 | * 15 | * @param str 需要判断的内容 16 | * @return 返回 `true` 为被 URLEncoder.encode() 过 17 | */ 18 | @JvmStatic 19 | fun hasUrlEncoded(str: String): Boolean { 20 | var encode = false 21 | for (i in str.indices) { 22 | val c = str[i] 23 | if (c == '%' && i + 2 < str.length) { 24 | // 判断是否符合urlEncode规范 25 | val c1 = str[i + 1] 26 | val c2 = str[i + 2] 27 | if (isValidHexChar(c1) && isValidHexChar(c2)) { 28 | encode = true 29 | break 30 | } else { 31 | break 32 | } 33 | } 34 | } 35 | return encode 36 | } 37 | 38 | /** 39 | * 判断 c 是否是 16 进制的字符 40 | * 41 | * @param c 需要判断的字符 42 | * @return 返回 `true` 为 16 进制的字符 43 | */ 44 | private fun isValidHexChar(c: Char): Boolean { 45 | return c in '0'..'9' || c in 'a'..'f' || c in 'A'..'F' 46 | } 47 | } 48 | 49 | init { 50 | throw IllegalStateException("you can't instantiate me!") 51 | } 52 | } -------------------------------------------------------------------------------- /JetpackMvvm/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | JetpackMvvm 3 | 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/cxk.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/cxk.jks -------------------------------------------------------------------------------- /app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/release/app-release.apk -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":19,"versionName":"1.1.9","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}] -------------------------------------------------------------------------------- /app/src/androidTest/java/me/hgj/jetpackmvvm/demo/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("me.hgj.jetpackmvvm.demo", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/base/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.base 2 | 3 | import android.os.Bundle 4 | import androidx.databinding.ViewDataBinding 5 | import me.hgj.jetpackmvvm.base.activity.BaseVmDbActivity 6 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 7 | import me.hgj.jetpackmvvm.demo.app.ext.dismissLoadingExt 8 | import me.hgj.jetpackmvvm.demo.app.ext.showLoadingExt 9 | 10 | /** 11 | * 时间 : 2019/12/21 12 | * 作者 : hegaojian 13 | * 描述 : 你项目中的Activity基类,在这里实现显示弹窗,吐司,还有加入自己的需求操作 ,如果不想用Databind,请继承 14 | * BaseVmActivity例如 15 | * abstract class BaseActivity : BaseVmActivity() { 16 | */ 17 | abstract class BaseActivity : BaseVmDbActivity() { 18 | 19 | abstract override fun initView(savedInstanceState: Bundle?) 20 | 21 | /** 22 | * 创建liveData观察者 23 | */ 24 | override fun createObserver() {} 25 | 26 | /** 27 | * 打开等待框 28 | */ 29 | override fun showLoading(message: String) { 30 | showLoadingExt(message) 31 | } 32 | 33 | /** 34 | * 关闭等待框 35 | */ 36 | override fun dismissLoading() { 37 | dismissLoadingExt() 38 | } 39 | 40 | /* *//** 41 | * 在任何情况下本来适配正常的布局突然出现适配失效,适配异常等问题,只要重写 Activity 的 getResources() 方法 42 | *//* 43 | override fun getResources(): Resources { 44 | AutoSizeCompat.autoConvertDensityOfGlobal(super.getResources()) 45 | return super.getResources() 46 | }*/ 47 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/base/BaseActivity1.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.base 2 | 3 | import android.os.Bundle 4 | import androidx.databinding.ViewDataBinding 5 | import androidx.viewbinding.ViewBinding 6 | import me.hgj.jetpackmvvm.base.activity.BaseVmDbActivity 7 | import me.hgj.jetpackmvvm.base.activity.BaseVmVbActivity 8 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 9 | import me.hgj.jetpackmvvm.demo.app.ext.dismissLoadingExt 10 | import me.hgj.jetpackmvvm.demo.app.ext.showLoadingExt 11 | 12 | /** 13 | * 时间 : 2019/12/21 14 | * 作者 : hegaojian 15 | * 描述 : 你项目中的Activity基类,在这里实现显示弹窗,吐司,还有加入自己的需求操作 ,如果不想用 Databind,请继承 16 | * BaseVmActivity例如 17 | * abstract class BaseActivity : BaseVmActivity() { 18 | */ 19 | abstract class BaseActivity1 : BaseVmVbActivity() { 20 | 21 | abstract override fun initView(savedInstanceState: Bundle?) 22 | 23 | /** 24 | * 创建liveData观察者 25 | */ 26 | override fun createObserver() {} 27 | 28 | /** 29 | * 打开等待框 30 | */ 31 | override fun showLoading(message: String) { 32 | showLoadingExt(message) 33 | } 34 | 35 | /** 36 | * 关闭等待框 37 | */ 38 | override fun dismissLoading() { 39 | dismissLoadingExt() 40 | } 41 | 42 | /* *//** 43 | * 在任何情况下本来适配正常的布局突然出现适配失效,适配异常等问题,只要重写 Activity 的 getResources() 方法 44 | *//* 45 | override fun getResources(): Resources { 46 | AutoSizeCompat.autoConvertDensityOfGlobal(super.getResources()) 47 | return super.getResources() 48 | }*/ 49 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/base/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.base 2 | 3 | import android.os.Bundle 4 | import androidx.databinding.ViewDataBinding 5 | import me.hgj.jetpackmvvm.base.fragment.BaseVmDbFragment 6 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 7 | import me.hgj.jetpackmvvm.demo.app.ext.dismissLoadingExt 8 | import me.hgj.jetpackmvvm.demo.app.ext.hideSoftKeyboard 9 | import me.hgj.jetpackmvvm.demo.app.ext.showLoadingExt 10 | 11 | /** 12 | * 作者 : hegaojian 13 | * 时间 : 2019/12/21 14 | * 描述 : 你项目中的Fragment基类,在这里实现显示弹窗,吐司,还有自己的需求操作 ,如果不想用Databind,请继承 15 | * BaseVmFragment例如 16 | * abstract class BaseFragment : BaseVmFragment() { 17 | */ 18 | abstract class BaseFragment : BaseVmDbFragment() { 19 | 20 | 21 | abstract override fun initView(savedInstanceState: Bundle?) 22 | 23 | /** 24 | * 懒加载 只有当前fragment视图显示时才会触发该方法 25 | */ 26 | override fun lazyLoadData() {} 27 | 28 | /** 29 | * 创建LiveData观察者 Fragment执行onViewCreated后触发 30 | */ 31 | override fun createObserver() {} 32 | 33 | /** 34 | * Fragment执行onViewCreated后触发 35 | */ 36 | override fun initData() { 37 | 38 | } 39 | 40 | /** 41 | * 打开等待框 42 | */ 43 | override fun showLoading(message: String) { 44 | showLoadingExt(message) 45 | } 46 | 47 | /** 48 | * 关闭等待框 49 | */ 50 | override fun dismissLoading() { 51 | dismissLoadingExt() 52 | } 53 | 54 | override fun onPause() { 55 | super.onPause() 56 | hideSoftKeyboard(activity) 57 | } 58 | 59 | /** 60 | * 延迟加载 防止 切换动画还没执行完毕时数据就已经加载好了,这时页面会有渲染卡顿 bug 61 | * 这里传入你想要延迟的时间,延迟时间可以设置比转场动画时间长一点 单位: 毫秒 62 | * 不传默认 300毫秒 63 | * @return Long 64 | */ 65 | override fun lazyLoadTime(): Long { 66 | return 300 67 | } 68 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/base/BaseFragment1.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.base 2 | 3 | import android.os.Bundle 4 | import androidx.databinding.ViewDataBinding 5 | import androidx.viewbinding.ViewBinding 6 | import me.hgj.jetpackmvvm.base.fragment.BaseVmDbFragment 7 | import me.hgj.jetpackmvvm.base.fragment.BaseVmVbFragment 8 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 9 | import me.hgj.jetpackmvvm.demo.app.ext.dismissLoadingExt 10 | import me.hgj.jetpackmvvm.demo.app.ext.hideSoftKeyboard 11 | import me.hgj.jetpackmvvm.demo.app.ext.showLoadingExt 12 | 13 | /** 14 | * 作者 : hegaojian 15 | * 时间 : 2019/12/21 16 | * 描述 : 你项目中的Fragment基类,在这里实现显示弹窗,吐司,还有自己的需求操作 ,如果不想用Databind,请继承 17 | * BaseVmFragment例如 18 | * abstract class BaseFragment : BaseVmFragment() { 19 | */ 20 | abstract class BaseFragment1 : BaseVmVbFragment() { 21 | 22 | abstract override fun initView(savedInstanceState: Bundle?) 23 | 24 | /** 25 | * 懒加载 只有当前fragment视图显示时才会触发该方法 26 | */ 27 | override fun lazyLoadData() {} 28 | 29 | /** 30 | * 创建LiveData观察者 Fragment执行onViewCreated后触发 31 | */ 32 | override fun createObserver() {} 33 | 34 | /** 35 | * Fragment执行onViewCreated后触发 36 | */ 37 | override fun initData() { 38 | 39 | } 40 | 41 | /** 42 | * 打开等待框 43 | */ 44 | override fun showLoading(message: String) { 45 | showLoadingExt(message) 46 | } 47 | 48 | /** 49 | * 关闭等待框 50 | */ 51 | override fun dismissLoading() { 52 | dismissLoadingExt() 53 | } 54 | 55 | override fun onPause() { 56 | super.onPause() 57 | hideSoftKeyboard(activity) 58 | } 59 | 60 | /** 61 | * 延迟加载 防止 切换动画还没执行完毕时数据就已经加载好了,这时页面会有渲染卡顿 bug 62 | * 这里传入你想要延迟的时间,延迟时间可以设置比转场动画时间长一点 单位: 毫秒 63 | * 不传默认 300毫秒 64 | * @return Long 65 | */ 66 | override fun lazyLoadTime(): Long { 67 | return 300 68 | } 69 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/event/AppViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.event 2 | 3 | import com.kunminx.architecture.ui.callback.UnPeekLiveData 4 | import me.hgj.jetpackmvvm.base.appContext 5 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 6 | import me.hgj.jetpackmvvm.callback.livedata.event.EventLiveData 7 | import me.hgj.jetpackmvvm.demo.app.util.CacheUtil 8 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 9 | import me.hgj.jetpackmvvm.demo.data.model.bean.UserInfo 10 | 11 | /** 12 | * 作者 : hegaojian 13 | * 时间 : 2019/12/23 14 | * 描述 :APP全局的ViewModel,可以存放公共数据,当他数据改变时,所有监听他的地方都会收到回调,也可以做发送消息 15 | * 比如 全局可使用的 地理位置信息,账户信息,App的基本配置等等, 16 | */ 17 | class AppViewModel : BaseViewModel() { 18 | 19 | //App的账户信息 20 | var userInfo = UnPeekLiveData.Builder().setAllowNullValue(true).create() 21 | 22 | //App主题颜色 中大型项目不推荐以这种方式改变主题颜色,比较繁琐耦合,且容易有遗漏某些控件没有设置主题色 23 | var appColor = EventLiveData() 24 | 25 | //App 列表动画 26 | var appAnimation = EventLiveData() 27 | 28 | init { 29 | //默认值保存的账户信息,没有登陆过则为null 30 | userInfo.value = CacheUtil.getUser() 31 | //默认值颜色 32 | appColor.value = SettingUtil.getColor(appContext) 33 | //初始化列表动画 34 | appAnimation.value = SettingUtil.getListMode() 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/event/EventViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.event 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | import me.hgj.jetpackmvvm.callback.livedata.event.EventLiveData 5 | import me.hgj.jetpackmvvm.demo.data.model.bean.CollectBus 6 | 7 | /** 8 | * 作者 : hegaojian 9 | * 时间 : 2019/5/2 10 | * 描述 :APP全局的ViewModel,可以在这里发送全局通知替代EventBus,LiveDataBus等 11 | */ 12 | class EventViewModel : BaseViewModel() { 13 | 14 | //全局收藏,在任意一个地方收藏或取消收藏,监听该值的界面都会收到消息 15 | val collectEvent = EventLiveData() 16 | 17 | //分享文章通知 18 | val shareArticleEvent = EventLiveData() 19 | 20 | //添加TODO通知 21 | val todoEvent = EventLiveData() 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/ext/AdapterExt.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.ext 2 | 3 | import android.view.View 4 | import com.chad.library.adapter.base.BaseQuickAdapter 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2020/4/16 9 | * 描述 : 10 | */ 11 | 12 | /** 13 | * 给adapter拓展的,防止重复点击item 14 | */ 15 | var adapterLastClickTime = 0L 16 | 17 | fun BaseQuickAdapter<*, *>.setNbOnItemClickListener(interval: Long = 1000,action: (adapter: BaseQuickAdapter<*, *>, view: View, position: Int) -> Unit) { 18 | setOnItemClickListener { adapter, view, position -> 19 | val currentTime = System.currentTimeMillis() 20 | if (adapterLastClickTime != 0L && (currentTime - adapterLastClickTime < interval)) { 21 | return@setOnItemClickListener 22 | } 23 | adapterLastClickTime = currentTime 24 | action(adapter,view,position) 25 | } 26 | } 27 | 28 | /** 29 | * 给adapter拓展的,防止重复点击item 30 | */ 31 | var adapterChildLastClickTime = 0L 32 | fun BaseQuickAdapter<*, *>.setNbOnItemChildClickListener(interval: Long = 1000,action: (adapter: BaseQuickAdapter<*, *>, view: View, position: Int) -> Unit) { 33 | setOnItemChildClickListener { adapter, view, position -> 34 | val currentTime = System.currentTimeMillis() 35 | if (adapterChildLastClickTime != 0L && (currentTime - adapterChildLastClickTime < interval)) { 36 | return@setOnItemChildClickListener 37 | } 38 | adapterChildLastClickTime = currentTime 39 | action(adapter,view,position) 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/network/MyHeadInterceptor.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.network 2 | 3 | import me.hgj.jetpackmvvm.demo.app.util.CacheUtil 4 | import okhttp3.Interceptor 5 | import okhttp3.Response 6 | import java.io.IOException 7 | 8 | /** 9 | * 自定义头部参数拦截器,传入heads 10 | */ 11 | class MyHeadInterceptor : Interceptor { 12 | 13 | @Throws(IOException::class) 14 | override fun intercept(chain: Interceptor.Chain): Response { 15 | val builder = chain.request().newBuilder() 16 | builder.addHeader("token", "token123456").build() 17 | builder.addHeader("device", "Android").build() 18 | builder.addHeader("isLogin", CacheUtil.isLogin().toString()).build() 19 | return chain.proceed(builder.build()) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/network/TokenOutInterceptor.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.network 2 | 3 | import android.content.Intent 4 | import com.google.gson.Gson 5 | import me.hgj.jetpackmvvm.base.appContext 6 | import me.hgj.jetpackmvvm.demo.data.model.bean.ApiResponse 7 | import me.hgj.jetpackmvvm.demo.ui.activity.TestActivity 8 | import okhttp3.Interceptor 9 | import okhttp3.Response 10 | import okhttp3.ResponseBody 11 | import java.io.IOException 12 | 13 | /** 14 | * 作者 : hegaojian 15 | * 时间 : 2022/1/13 16 | * 描述 : token过期拦截器 17 | */ 18 | class TokenOutInterceptor : Interceptor { 19 | 20 | val gson: Gson by lazy { Gson() } 21 | 22 | @kotlin.jvm.Throws(IOException::class) 23 | override fun intercept(chain: Interceptor.Chain): Response { 24 | val response = chain.proceed(chain.request()) 25 | return if (response.body() != null && response.body()!!.contentType() != null) { 26 | val mediaType = response.body()!!.contentType() 27 | val string = response.body()!!.string() 28 | val responseBody = ResponseBody.create(mediaType, string) 29 | val apiResponse = gson.fromJson(string, ApiResponse::class.java) 30 | //判断逻辑 模拟一下 31 | if (apiResponse.errorCode == 99999) { 32 | //如果是普通的activity话 可以直接跳转,如果是navigation中的fragment,可以发送通知跳转 33 | appContext.startActivity(Intent(appContext, TestActivity::class.java).apply { 34 | flags = Intent.FLAG_ACTIVITY_NEW_TASK 35 | }) 36 | } 37 | response.newBuilder().body(responseBody).build() 38 | } else { 39 | response 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/network/stateCallback/CollectUiState.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.network.stateCallback 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/3/11 6 | * 描述 :收藏数据状态类 7 | */ 8 | data class CollectUiState( 9 | //请求是否成功 10 | var isSuccess: Boolean = true, 11 | //收藏 12 | var collect: Boolean = false, 13 | //收藏Id 14 | var id: Int = -1, 15 | //请求失败的错误信息 16 | var errorMsg: String = "" 17 | ) -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/network/stateCallback/ListDataUiState.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.network.stateCallback 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/3/3 6 | * 描述 : 列表数据状态类 7 | */ 8 | data class ListDataUiState( 9 | //是否请求成功 10 | val isSuccess: Boolean, 11 | //错误消息 isSuccess为false才会有 12 | val errMessage: String = "", 13 | //是否为刷新 14 | val isRefresh: Boolean = false, 15 | //是否为空 16 | val isEmpty: Boolean = false, 17 | //是否还有更多 18 | val hasMore: Boolean = false, 19 | //是第一页且没有数据 20 | val isFirstEmpty:Boolean = false, 21 | //列表数据 22 | val listData: ArrayList = arrayListOf() 23 | ) -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/network/stateCallback/UpdateUiState.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.network.stateCallback 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/3/11 6 | * 描述 :操作数据的状态类 7 | */ 8 | data class UpdateUiState( 9 | //请求是否成功 10 | var isSuccess: Boolean = true, 11 | //操作的对象 12 | var data: T? = null, 13 | //请求失败的错误信息 14 | var errorMsg: String = "" 15 | ) -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/banner/HomeBannerAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.banner 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/2/20 6 | * 描述 : 7 | */ 8 | 9 | import android.view.View 10 | import com.zhpan.bannerview.BaseBannerAdapter 11 | import me.hgj.jetpackmvvm.demo.R 12 | import me.hgj.jetpackmvvm.demo.data.model.bean.BannerResponse 13 | 14 | class HomeBannerAdapter : BaseBannerAdapter() { 15 | override fun getLayoutId(viewType: Int): Int { 16 | return R.layout.banner_itemhome 17 | } 18 | 19 | override fun createViewHolder(itemView: View, viewType: Int): HomeBannerViewHolder { 20 | return HomeBannerViewHolder(itemView); 21 | } 22 | 23 | override fun onBind( 24 | holder: HomeBannerViewHolder?, 25 | data: BannerResponse?, 26 | position: Int, 27 | pageSize: Int 28 | ) { 29 | holder?.bindData(data, position, pageSize); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/banner/HomeBannerViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.banner 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/2/20 6 | * 描述 : 7 | */ 8 | 9 | import android.view.View 10 | import android.widget.ImageView 11 | import com.bumptech.glide.Glide 12 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions 13 | import com.zhpan.bannerview.BaseViewHolder 14 | import me.hgj.jetpackmvvm.base.appContext 15 | import me.hgj.jetpackmvvm.demo.R 16 | import me.hgj.jetpackmvvm.demo.data.model.bean.BannerResponse 17 | 18 | class HomeBannerViewHolder(view: View) : BaseViewHolder(view) { 19 | override fun bindData(data: BannerResponse?, position: Int, pageSize: Int) { 20 | val img = itemView.findViewById(R.id.bannerhome_img) 21 | data?.let { 22 | Glide.with(appContext) 23 | .load(it.imagePath) 24 | .transition(DrawableTransitionOptions.withCrossFade(500)) 25 | .into(img) 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/banner/WelcomeBannerAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.banner 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/2/20 6 | * 描述 : 7 | */ 8 | 9 | import android.view.View 10 | import com.zhpan.bannerview.BaseBannerAdapter 11 | import me.hgj.jetpackmvvm.demo.R 12 | 13 | class WelcomeBannerAdapter : BaseBannerAdapter() { 14 | 15 | override fun getLayoutId(viewType: Int): Int { 16 | return R.layout.banner_itemwelcome 17 | } 18 | 19 | override fun createViewHolder(itemView: View, viewType: Int): WelcomeBannerViewHolder { 20 | return WelcomeBannerViewHolder(itemView); 21 | } 22 | 23 | override fun onBind( 24 | holder: WelcomeBannerViewHolder?, 25 | data: String?, 26 | position: Int, 27 | pageSize: Int 28 | ) { 29 | holder?.bindData(data, position, pageSize); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/banner/WelcomeBannerViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.banner 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/2/20 6 | * 描述 : 7 | */ 8 | 9 | import android.view.View 10 | import android.widget.TextView 11 | import com.zhpan.bannerview.BaseViewHolder 12 | import me.hgj.jetpackmvvm.demo.R 13 | 14 | class WelcomeBannerViewHolder(view: View) : BaseViewHolder(view) { 15 | override fun bindData(data: String?, position: Int, pageSize: Int) { 16 | val textView = findView(R.id.banner_text) 17 | textView.text = data 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/customview/CollectView.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.customview 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.MotionEvent 6 | import android.view.View 7 | import com.blankj.utilcode.util.VibrateUtils 8 | import me.hgj.jetpackmvvm.demo.R 9 | import me.hgj.jetpackmvvm.demo.app.util.CacheUtil 10 | import me.hgj.jetpackmvvm.ext.nav 11 | import me.hgj.jetpackmvvm.ext.navigateAction 12 | 13 | 14 | import per.goweii.reveallayout.RevealLayout 15 | 16 | /** 17 | * @author CuiZhen 18 | */ 19 | class CollectView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : RevealLayout(context, attrs, defStyleAttr), View.OnTouchListener { 20 | 21 | private var onCollectViewClickListener: OnCollectViewClickListener? = null 22 | 23 | override fun initAttr(attrs: AttributeSet) { 24 | super.initAttr(attrs) 25 | setCheckWithExpand(true) 26 | setUncheckWithExpand(false) 27 | setCheckedLayoutId(R.layout.layout_collect_view_checked) 28 | setUncheckedLayoutId(R.layout.layout_collect_view_unchecked) 29 | setAnimDuration(300) 30 | setAllowRevert(true) 31 | setOnTouchListener(this) 32 | } 33 | 34 | override fun onTouch(v: View, event: MotionEvent): Boolean { 35 | when (event.action) { 36 | MotionEvent.ACTION_UP ->{ 37 | //震动一下 38 | VibrateUtils.vibrate(40) 39 | if(CacheUtil.isLogin()){ 40 | onCollectViewClickListener?.onClick(this) 41 | }else{ 42 | isChecked = true 43 | nav(v).navigateAction(R.id.action_to_loginFragment) 44 | } 45 | 46 | } 47 | } 48 | return false 49 | } 50 | 51 | fun setOnCollectViewClickListener(onCollectViewClickListener: OnCollectViewClickListener) { 52 | this.onCollectViewClickListener = onCollectViewClickListener 53 | } 54 | 55 | interface OnCollectViewClickListener { 56 | fun onClick(v: CollectView) 57 | } 58 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/customview/MyView.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.customview 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | 7 | 8 | /** 9 | * 作者 : hegaojian 10 | * 时间 : 2020/4/24 11 | * 描述 : 12 | */ 13 | class MyView(context: Context) : View(context) { 14 | 15 | constructor(context: Context, attr: AttributeSet) : this(context) { 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/loadCallBack/EmptyCallback.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.loadCallBack 2 | 3 | 4 | import com.kingja.loadsir.callback.Callback 5 | import me.hgj.jetpackmvvm.demo.R 6 | 7 | 8 | class EmptyCallback : Callback() { 9 | 10 | override fun onCreateView(): Int { 11 | return R.layout.layout_empty 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/loadCallBack/ErrorCallback.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.loadCallBack 2 | 3 | import com.kingja.loadsir.callback.Callback 4 | import me.hgj.jetpackmvvm.demo.R 5 | 6 | 7 | class ErrorCallback : Callback() { 8 | 9 | override fun onCreateView(): Int { 10 | return R.layout.layout_error 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/loadCallBack/LoadingCallback.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.loadCallBack 2 | 3 | import android.content.Context 4 | import android.view.View 5 | import com.kingja.loadsir.callback.Callback 6 | import me.hgj.jetpackmvvm.demo.R 7 | 8 | 9 | class LoadingCallback : Callback() { 10 | 11 | override fun onCreateView(): Int { 12 | return R.layout.layout_loading 13 | } 14 | 15 | override fun onReloadEvent(context: Context?, view: View?): Boolean { 16 | return true 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/preference/IconPreference.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.preference 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.preference.Preference 6 | import androidx.preference.PreferenceViewHolder 7 | import me.hgj.jetpackmvvm.demo.R 8 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 9 | 10 | 11 | /** 12 | * @Author: hegaojian 13 | * @CreateDate: 2019/8/12 14:23 14 | */ 15 | 16 | class IconPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) { 17 | 18 | var circleImageView: MyColorCircleView? = null 19 | 20 | init { 21 | widgetLayoutResource = R.layout.item_icon_preference_preview 22 | } 23 | 24 | override fun onBindViewHolder(holder: PreferenceViewHolder?) { 25 | super.onBindViewHolder(holder) 26 | val color = SettingUtil.getColor(context) 27 | circleImageView = holder?.itemView?.findViewById(R.id.iv_preview) 28 | circleImageView?.color = color 29 | circleImageView?.border = color 30 | } 31 | 32 | fun setView() { 33 | val color = SettingUtil.getColor(context) 34 | circleImageView?.color = color 35 | circleImageView?.border = color 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/recyclerview/FatScrollAwareFABBehavior.java: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.recyclerview; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | 8 | import androidx.coordinatorlayout.widget.CoordinatorLayout; 9 | import androidx.core.view.ViewCompat; 10 | 11 | import com.google.android.material.floatingactionbutton.FloatingActionButton; 12 | 13 | /** 14 | * 自定义Behavior FAB 上滑显示 下滑隐藏 15 | */ 16 | 17 | public class FatScrollAwareFABBehavior extends FloatingActionButton.Behavior { 18 | 19 | public FatScrollAwareFABBehavior(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | } 22 | 23 | @Override 24 | public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, 25 | FloatingActionButton child, 26 | View directTargetChild, 27 | View target, 28 | int nestedScrollAxes) { 29 | return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || 30 | super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); 31 | } 32 | 33 | @SuppressLint("RestrictedApi") 34 | @Override 35 | public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, 36 | View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 37 | super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, 38 | dyUnconsumed); 39 | 40 | if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) { 41 | child.setVisibility(View.INVISIBLE); 42 | } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { 43 | child.show(); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/recyclerview/SpaceItemDecoration.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.recyclerview 2 | 3 | import android.annotation.SuppressLint 4 | import android.graphics.Canvas 5 | import android.graphics.Rect 6 | import android.view.View 7 | 8 | import androidx.recyclerview.widget.LinearLayoutManager 9 | import androidx.recyclerview.widget.RecyclerView 10 | 11 | 12 | class SpaceItemDecoration(private val leftRight: Int, private val topBottom: Int,private val firstNeedTop:Boolean = true) : RecyclerView.ItemDecoration() { 13 | //leftRight为横向间的距离 topBottom为纵向间距离 14 | override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { 15 | super.onDraw(c, parent, state) 16 | } 17 | 18 | @SuppressLint("WrongConstant") 19 | override fun getItemOffsets( 20 | outRect: Rect, 21 | view: View, 22 | parent: RecyclerView, 23 | state: RecyclerView.State 24 | ) { 25 | val layoutManager = parent.layoutManager as LinearLayoutManager? 26 | //竖直方向的 27 | if (layoutManager!!.orientation == LinearLayoutManager.VERTICAL) { 28 | //最后一项需要 bottom 29 | if (parent.getChildAdapterPosition(view) == layoutManager.itemCount - 1) { 30 | outRect.bottom = topBottom 31 | } 32 | if(!firstNeedTop&&parent.getChildAdapterPosition(view)==0){ 33 | outRect.top = 0 34 | }else{ 35 | outRect.top = topBottom 36 | } 37 | outRect.left = leftRight 38 | outRect.right = leftRight 39 | } else { 40 | //最后一项需要right 41 | if (parent.getChildAdapterPosition(view) != layoutManager.itemCount - 1) { 42 | outRect.right = leftRight 43 | } 44 | outRect.top = topBottom 45 | outRect.left = 0 46 | outRect.bottom = topBottom 47 | } 48 | } 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/app/weight/viewpager/ScaleTransitionPagerTitleView.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.app.weight.viewpager 2 | 3 | import android.content.Context 4 | 5 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.ColorTransitionPagerTitleView 6 | 7 | /** 8 | * 带颜色渐变和缩放的指示器标题 9 | * 博客: http://hackware.lucode.net 10 | * Created by hackware on 2016/6/26. 11 | */ 12 | class ScaleTransitionPagerTitleView(context: Context) : ColorTransitionPagerTitleView(context) { 13 | 14 | var minScale = 0.7f 15 | 16 | override fun onEnter(index: Int, totalCount: Int, enterPercent: Float, leftToRight: Boolean) { 17 | super.onEnter(index, totalCount, enterPercent, leftToRight) // 实现颜色渐变 18 | scaleX = minScale + (1.0f - minScale) * enterPercent 19 | scaleY = minScale + (1.0f - minScale) * enterPercent 20 | } 21 | 22 | override fun onLeave(index: Int, totalCount: Int, leavePercent: Float, leftToRight: Boolean) { 23 | super.onLeave(index, totalCount, leavePercent, leftToRight) // 实现颜色渐变 24 | scaleX = 1.0f + (minScale - 1.0f) * leavePercent 25 | scaleY = 1.0f + (minScale - 1.0f) * leavePercent 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/ApiPagerResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * 分页数据的基类 7 | */ 8 | data class ApiPagerResponse( 9 | var datas: T, 10 | var curPage: Int, 11 | var offset: Int, 12 | var over: Boolean, 13 | var pageCount: Int, 14 | var size: Int, 15 | var total: Int 16 | ) : Serializable { 17 | /** 18 | * 数据是否为空 19 | */ 20 | fun isEmpty() = (datas as List<*>).size == 0 21 | 22 | /** 23 | * 是否为刷新 24 | */ 25 | fun isRefresh() = offset == 0 26 | 27 | /** 28 | * 是否还有更多数据 29 | */ 30 | fun hasMore() = !over 31 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/ApiResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import me.hgj.jetpackmvvm.network.BaseResponse 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/23 8 | * 描述 :服务器返回数据的基类 9 | * 如果你的项目中有基类,那美滋滋,可以继承BaseResponse,请求时框架可以帮你自动脱壳,自动判断是否请求成功,怎么做: 10 | * 1.继承 BaseResponse 11 | * 2.重写isSucces 方法,编写你的业务需求,根据自己的条件判断数据是否请求成功 12 | * 3.重写 getResponseCode、getResponseData、getResponseMsg方法,传入你的 code data msg 13 | */ 14 | data class ApiResponse(val errorCode: Int, val errorMsg: String, val data: T) : BaseResponse() { 15 | 16 | // 这里是示例,wanandroid 网站返回的 错误码为 0 就代表请求成功,请你根据自己的业务需求来改变 17 | override fun isSucces() = errorCode == 0 18 | 19 | override fun getResponseCode() = errorCode 20 | 21 | override fun getResponseData() = data 22 | 23 | override fun getResponseMsg() = errorMsg 24 | 25 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/AriticleResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 文章 9 | */ 10 | @SuppressLint("ParcelCreator") 11 | @Parcelize 12 | data class AriticleResponse( 13 | var apkLink: String, 14 | var author: String,//作者 15 | var chapterId: Int, 16 | var chapterName: String, 17 | var collect: Boolean,//是否收藏 18 | var courseId: Int, 19 | var desc: String, 20 | var envelopePic: String, 21 | var fresh: Boolean, 22 | var id: Int, 23 | var link: String, 24 | var niceDate: String, 25 | var origin: String, 26 | var prefix: String, 27 | var projectLink: String, 28 | var publishTime: Long, 29 | var superChapterId: Int, 30 | var superChapterName: String, 31 | var shareUser: String, 32 | var tags: List, 33 | var title: String, 34 | var type: Int, 35 | var userId: Int, 36 | var visible: Int, 37 | var zan: Int) : Parcelable 38 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/BannerResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 轮播图 9 | */ 10 | @SuppressLint("ParcelCreator") 11 | @Parcelize 12 | data class BannerResponse( 13 | var desc: String = "", 14 | var id: Int = 0, 15 | var imagePath: String = "", 16 | var isVisible: Int = 0, 17 | var order: Int = 0, 18 | var title: String = "", 19 | var type: Int = 0, 20 | var url: String = "" 21 | ) : Parcelable 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/ClassifyResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 项目分类 9 | */ 10 | @SuppressLint("ParcelCreator") 11 | @Parcelize 12 | data class ClassifyResponse(var children: List = listOf(), 13 | var courseId: Int = 0, 14 | var id: Int = 0, 15 | var name: String = "", 16 | var order: Int = 0, 17 | var parentChapterId: Int = 0, 18 | var userControlSetTop: Boolean = false, 19 | var visible: Int = 0) : Parcelable 20 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/CoinInfoResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 分享人信息 9 | */ 10 | @SuppressLint("ParcelCreator") 11 | @Parcelize 12 | data class CoinInfoResponse( 13 | var coinCount: Int, 14 | var rank: String, 15 | var userId: Int, 16 | var username: String 17 | ) : Parcelable 18 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/CollectBus.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/3/4 6 | * 描述 : 7 | */ 8 | class CollectBus(var id: Int, var collect: Boolean) -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/CollectResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | @SuppressLint("ParcelCreator") 8 | @Parcelize 9 | data class CollectResponse(var chapterId: Int, 10 | var author: String, 11 | var chapterName: String, 12 | var courseId: Int, 13 | var desc: String, 14 | var envelopePic: String, 15 | var id: Int, 16 | var link: String, 17 | var niceDate: String, 18 | var origin: String, 19 | var originId: Int, 20 | var publishTime: Long, 21 | var title: String, 22 | var userId: Int, 23 | var visible: Int, 24 | var zan: Int):Parcelable -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/CollectUrlResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 收藏的网址类 9 | * @Author: hegaojian 10 | * @CreateDate: 2019/8/31 10:36 11 | */ 12 | @SuppressLint("ParcelCreator") 13 | @Parcelize 14 | data class CollectUrlResponse(var icon: String, 15 | var id: Int, 16 | var link: String, 17 | var name: String, 18 | var order: Int, 19 | var userId: Int, 20 | var visible: Int) : Parcelable 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/IntegralHistoryResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 积分记录 9 | */ 10 | @SuppressLint("ParcelCreator") 11 | @Parcelize 12 | data class IntegralHistoryResponse( 13 | var coinCount: Int, 14 | var date: Long, 15 | var desc: String, 16 | var id: Int, 17 | var type: Int, 18 | var reason: String, 19 | var userId: Int, 20 | var userName: String) : Parcelable 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/IntegralResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 积分 9 | */ 10 | @SuppressLint("ParcelCreator") 11 | @Parcelize 12 | data class IntegralResponse( 13 | var coinCount: Int,//当前积分 14 | var rank: Int, 15 | var userId: Int, 16 | var username: String) : Parcelable 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/MeItemEntity.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import me.hgj.jetpackmvvm.demo.data.model.enums.MeItemType 4 | 5 | /** 6 | * @author : hgj 7 | * @date : 2020/6/11 8 | * 9 | */ 10 | data class MeItemEntity( 11 | var itemType: MeItemType, 12 | var itemPosition: Int, 13 | var data: Any 14 | ) -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/NavigationResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 导航数据 9 | * @Author: hegaojian 10 | * @CreateDate: 2019/8/26 17:40 11 | */ 12 | @SuppressLint("ParcelCreator") 13 | @Parcelize 14 | data class NavigationResponse(var articles: ArrayList, 15 | var cid: Int, 16 | var name: String) : Parcelable 17 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/SearchResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 搜索热词 9 | */ 10 | @SuppressLint("ParcelCreator") 11 | @Parcelize 12 | data class SearchResponse(var id: Int, 13 | var link: String, 14 | var name: String, 15 | var order: Int, 16 | var visible: Int) : Parcelable 17 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/ShareResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | @SuppressLint("ParcelCreator") 8 | @Parcelize 9 | data class ShareResponse( 10 | var coinInfo: CoinInfoResponse, 11 | var shareArticles: ApiPagerResponse> 12 | ) : Parcelable -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/SystemResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | 7 | /** 8 | * 体系数据 9 | * @Author: hegaojian 10 | * @CreateDate: 2019/8/21 15:46 11 | */ 12 | @SuppressLint("ParcelCreator") 13 | @Parcelize 14 | data class SystemResponse(var children: ArrayList, 15 | var courseId: Int, 16 | var id: Int, 17 | var name: String, 18 | var order: Int, 19 | var parentChapterId: Int, 20 | var userControlSetTop: Boolean, 21 | var visible: Int) : Parcelable 22 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/TagsResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | /** 7 | * 文章的标签 8 | */ 9 | @SuppressLint("ParcelCreator") 10 | @Parcelize 11 | data class TagsResponse(var name:String, var url:String): Parcelable 12 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/TodoResponse.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Parcelable 5 | import kotlinx.android.parcel.Parcelize 6 | import me.hgj.jetpackmvvm.demo.app.util.DatetimeUtil 7 | 8 | /** 9 | * 项目分类 10 | */ 11 | @SuppressLint("ParcelCreator") 12 | @Parcelize 13 | data class TodoResponse( 14 | var completeDate: Long, 15 | var completeDateStr: String, 16 | var content: String, 17 | var date: Long, 18 | var dateStr: String, 19 | var id: Int, 20 | var priority: Int, 21 | var status: Int, 22 | var title: String, 23 | var type: Int, 24 | var userId: Int 25 | ) : Parcelable { 26 | fun isDone(): Boolean { 27 | //判断是否已完成或者已过期 28 | return if (status == 1) { 29 | true 30 | } else { 31 | DatetimeUtil.nows.time > DatetimeUtil.formatDate( 32 | DatetimeUtil.DATE_PATTERN, 33 | dateStr 34 | ).time 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/bean/UserInfo.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.bean 2 | import android.annotation.SuppressLint 3 | import android.os.Parcelable 4 | import kotlinx.android.parcel.Parcelize 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2019/12/23 9 | * 描述 : 账户信息 10 | */ 11 | @SuppressLint("ParcelCreator") 12 | @Parcelize 13 | data class UserInfo(var admin: Boolean = false, 14 | var chapterTops: List = listOf(), 15 | var collectIds: MutableList = mutableListOf(), 16 | var email: String="", 17 | var icon: String="", 18 | var id: String="", 19 | var nickname: String="", 20 | var password: String="", 21 | var token: String="", 22 | var type: Int =0, 23 | var username: String="") : Parcelable 24 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/enums/CollectType.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.enums 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/3/4 6 | * 描述 : 收藏的类型 7 | */ 8 | enum class CollectType(val type: Int) { 9 | // 0.文章 10 | Ariticle(0), 11 | //1.网址 12 | Url(1) 13 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/enums/MeItemType.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.enums 2 | 3 | /** 4 | * 作者 : hegaojian 5 | * 时间 : 2020/3/4 6 | * 描述 : 个人中心类型 7 | */ 8 | enum class MeItemType(val type: Int) { 9 | //头部布局 10 | TopItem(1), 11 | //圆角Item 12 | RoundItem(2), 13 | //分割线 14 | BackGroundItem(3), 15 | //普通的列表 16 | ListItem(4), 17 | //右边有数据的列表 18 | ListRightItem(4) 19 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/model/enums/TodoType.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.model.enums 2 | 3 | import android.graphics.Color 4 | 5 | enum class TodoType(val type: Int, val color: Int, val content: String) { 6 | TodoType1(0, Color.parseColor("#fe7b7b"), "重要且紧急"), 7 | TodoType2(1, Color.parseColor("#dda239"), "重要不紧急"), 8 | TodoType3(2, Color.parseColor("#69adef"), "紧急但不重要"), 9 | TodoType4(3, Color.parseColor("#6cc959"), "不重要不紧急"); 10 | 11 | companion object { 12 | /** 13 | * 根据传入的type得到相关的枚举类型 没有的话默认 重要且紧急 14 | */ 15 | fun byType(type: Int): TodoType { 16 | values().forEach { 17 | if (type == it.type) { 18 | return it 19 | } 20 | } 21 | return TodoType1 22 | } 23 | /** 24 | * 根据传入的content得到相关的枚举类型 没有的话默认 重要且紧急 25 | */ 26 | fun byValue(content: String): TodoType { 27 | values().forEach { 28 | if (content == it.content) { 29 | return it 30 | } 31 | } 32 | return TodoType1 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/data/repository/local/LocalDataManger.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.data.repository.local 2 | 3 | 4 | class LocalDataManger { 5 | 6 | companion object { 7 | val instance: LocalDataManger by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { 8 | LocalDataManger() 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/activity/TestActivity.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.activity 2 | 3 | import android.os.Bundle 4 | import androidx.activity.viewModels 5 | import androidx.lifecycle.Observer 6 | import kotlinx.android.synthetic.main.activity_test.* 7 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 8 | import me.hgj.jetpackmvvm.demo.R 9 | import me.hgj.jetpackmvvm.demo.app.base.BaseActivity 10 | import me.hgj.jetpackmvvm.demo.app.ext.showMessage 11 | import me.hgj.jetpackmvvm.demo.databinding.ActivityTestBinding 12 | import me.hgj.jetpackmvvm.demo.ui.adapter.TestAdapter 13 | import me.hgj.jetpackmvvm.demo.viewmodel.request.RequestLoginRegisterViewModel 14 | import me.hgj.jetpackmvvm.ext.parseState 15 | import me.hgj.jetpackmvvm.ext.util.logd 16 | 17 | /** 18 | * @author : hgj 19 | * @date : 2020/8/26 20 | */ 21 | 22 | class TestActivity : BaseActivity() { 23 | 24 | val viewModel: RequestLoginRegisterViewModel by viewModels() 25 | 26 | val adapter: TestAdapter by lazy { TestAdapter(arrayListOf()) } 27 | 28 | 29 | override fun initView(savedInstanceState: Bundle?) { 30 | 31 | //强烈注意:使用addLoadingObserve 将非绑定当前activity的viewmodel绑定loading回调 防止出现请求时不显示 loading 弹窗bug 32 | addLoadingObserve(viewModel) 33 | 34 | adapter.run { 35 | clickAction = { position, item, state -> 36 | "海王收到了点击事件,并准备发一个红包".logd() 37 | } 38 | } 39 | 40 | } 41 | 42 | override fun createObserver() { 43 | 44 | 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/CollectUrlAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import me.hgj.jetpackmvvm.demo.R 6 | import me.hgj.jetpackmvvm.demo.app.ext.setAdapterAnimation 7 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 8 | import me.hgj.jetpackmvvm.demo.app.weight.customview.CollectView 9 | import me.hgj.jetpackmvvm.demo.data.model.bean.CollectUrlResponse 10 | import me.hgj.jetpackmvvm.ext.util.toHtml 11 | 12 | 13 | class CollectUrlAdapter(data: ArrayList) : 14 | BaseQuickAdapter( 15 | R.layout.item_collecturl, data 16 | ) { 17 | 18 | private var collectAction: (item: CollectUrlResponse, v: CollectView, position: Int) -> Unit = 19 | { _: CollectUrlResponse, _: CollectView, _: Int -> } 20 | 21 | init { 22 | setAdapterAnimation(SettingUtil.getListMode()) 23 | } 24 | 25 | override fun convert(holder: BaseViewHolder, item: CollectUrlResponse) { 26 | //赋值 27 | item.run { 28 | holder.setText(R.id.item_collecturl_name, name.toHtml()) 29 | holder.setText(R.id.item_collecturl_link, link) 30 | holder.getView(R.id.item_collecturl_collect).isChecked = true 31 | } 32 | holder.getView(R.id.item_collecturl_collect) 33 | .setOnCollectViewClickListener(object : CollectView.OnCollectViewClickListener { 34 | override fun onClick(v: CollectView) { 35 | collectAction.invoke(item, v, holder.adapterPosition) 36 | } 37 | }) 38 | } 39 | 40 | fun setCollectClick(inputCollectAction: (item: CollectUrlResponse, v: CollectView, position: Int) -> Unit) { 41 | this.collectAction = inputCollectAction 42 | } 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/IntegralAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import androidx.core.content.ContextCompat 4 | import com.chad.library.adapter.base.BaseQuickAdapter 5 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 6 | import me.hgj.jetpackmvvm.demo.R 7 | import me.hgj.jetpackmvvm.demo.app.ext.setAdapterAnimation 8 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 9 | import me.hgj.jetpackmvvm.demo.data.model.bean.IntegralResponse 10 | 11 | /** 12 | * 积分排行 adapter 13 | * @Author: hegaojian 14 | * @CreateDate: 2019/9/1 9:52 15 | */ 16 | class IntegralAdapter(data: ArrayList) : BaseQuickAdapter(R.layout.item_integral, data) { 17 | private var rankNum: Int = -1 18 | 19 | constructor(data: ArrayList, rank: Int) : this(data) { 20 | this.rankNum = rank 21 | } 22 | init { 23 | setAdapterAnimation(SettingUtil.getListMode()) 24 | } 25 | override fun convert(holder: BaseViewHolder, item: IntegralResponse) { 26 | //赋值 27 | item.run { 28 | if(rankNum==holder.adapterPosition+1){ 29 | holder.setTextColor(R.id.item_integral_rank, SettingUtil.getColor(context)) 30 | holder.setTextColor(R.id.item_integral_name,SettingUtil.getColor(context)) 31 | holder.setTextColor(R.id.item_integral_count,SettingUtil.getColor(context)) 32 | }else{ 33 | holder.setTextColor(R.id.item_integral_rank,ContextCompat.getColor(context,R.color.colorBlack333)) 34 | holder.setTextColor(R.id.item_integral_name,ContextCompat.getColor(context,R.color.colorBlack666)) 35 | holder.setTextColor(R.id.item_integral_count,ContextCompat.getColor(context,R.color.textHint)) 36 | } 37 | holder.setText(R.id.item_integral_rank, "${holder.adapterPosition + 1}") 38 | holder.setText(R.id.item_integral_name, username) 39 | holder.setText(R.id.item_integral_count, coinCount.toString()) 40 | } 41 | } 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/IntegralHistoryAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import me.hgj.jetpackmvvm.demo.R 6 | import me.hgj.jetpackmvvm.demo.app.ext.setAdapterAnimation 7 | import me.hgj.jetpackmvvm.demo.app.util.DatetimeUtil 8 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 9 | import me.hgj.jetpackmvvm.demo.data.model.bean.IntegralHistoryResponse 10 | 11 | /** 12 | * 积分获取历史 adapter 13 | * @Author: hegaojian 14 | * @CreateDate: 2019/9/1 12:21 15 | */ 16 | class IntegralHistoryAdapter(data: ArrayList) : 17 | BaseQuickAdapter( 18 | R.layout.item_integral_history, data 19 | ) { 20 | init { 21 | setAdapterAnimation(SettingUtil.getListMode()) 22 | } 23 | 24 | override fun convert(holder: BaseViewHolder, item: IntegralHistoryResponse) { 25 | //赋值 26 | item.run { 27 | val descStr = 28 | if (desc.contains("积分")) desc.subSequence(desc.indexOf("积分"), desc.length) else "" 29 | holder.setText(R.id.item_integralhistory_title, reason + descStr) 30 | holder.setText( 31 | R.id.item_integralhistory_date, 32 | DatetimeUtil.formatDate(date, DatetimeUtil.DATE_PATTERN_SS) 33 | ) 34 | holder.setText(R.id.item_integralhistory_count, "+$coinCount") 35 | holder.setTextColor(R.id.item_integralhistory_count, SettingUtil.getColor(context)) 36 | } 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/NavigationChildAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import me.hgj.jetpackmvvm.demo.R 6 | import me.hgj.jetpackmvvm.demo.app.ext.setAdapterAnimation 7 | import me.hgj.jetpackmvvm.demo.app.util.ColorUtil 8 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 9 | import me.hgj.jetpackmvvm.demo.data.model.bean.AriticleResponse 10 | import me.hgj.jetpackmvvm.ext.util.toHtml 11 | 12 | class NavigationChildAdapter(data: ArrayList) : 13 | BaseQuickAdapter(R.layout.flow_layout, data) { 14 | 15 | init { 16 | setAdapterAnimation(SettingUtil.getListMode()) 17 | } 18 | 19 | override fun convert(holder: BaseViewHolder, item: AriticleResponse) { 20 | holder.setText(R.id.flow_tag,item.title.toHtml()) 21 | holder.setTextColor(R.id.flow_tag, ColorUtil.randomColor()) 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/PriorityAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import me.hgj.jetpackmvvm.demo.R 6 | import me.hgj.jetpackmvvm.demo.app.weight.preference.MyColorCircleView 7 | import me.hgj.jetpackmvvm.demo.data.model.enums.TodoType 8 | 9 | /** 10 | * 重要程度 adapter 11 | * @Author: hegaojian 12 | * @CreateDate: 2019/9/1 9:52 13 | */ 14 | class PriorityAdapter(data: ArrayList) : BaseQuickAdapter(R.layout.item_todo_dialog, data) { 15 | var checkType = TodoType.TodoType1.type 16 | 17 | constructor(data: ArrayList, checkType: Int) : this(data) { 18 | this.checkType = checkType 19 | } 20 | 21 | override fun convert(holder: BaseViewHolder, item: TodoType) { 22 | //赋值 23 | item.run { 24 | holder.setText(R.id.item_todo_dialog_name, item.content) 25 | if (checkType == item.type) { 26 | holder.getView(R.id.item_todo_dialog_icon).setViewSelect(item.color) 27 | } else { 28 | holder.getView(R.id.item_todo_dialog_icon).setView(item.color) 29 | } 30 | } 31 | } 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/SearcHistoryAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import me.hgj.jetpackmvvm.demo.R 6 | import me.hgj.jetpackmvvm.demo.app.ext.setAdapterAnimation 7 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 8 | 9 | class SearcHistoryAdapter(data: MutableList) : 10 | BaseQuickAdapter(R.layout.item_history, data) { 11 | 12 | init { 13 | setAdapterAnimation(SettingUtil.getListMode()) 14 | } 15 | 16 | override fun convert(holder: BaseViewHolder, item: String) { 17 | holder.setText(R.id.item_history_text, item) 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/SearcHotAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import me.hgj.jetpackmvvm.demo.R 6 | import me.hgj.jetpackmvvm.demo.app.ext.setAdapterAnimation 7 | import me.hgj.jetpackmvvm.demo.app.util.ColorUtil 8 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 9 | import me.hgj.jetpackmvvm.demo.data.model.bean.SearchResponse 10 | 11 | class SearcHotAdapter(data: ArrayList) : 12 | BaseQuickAdapter(R.layout.flow_layout, data) { 13 | 14 | init { 15 | setAdapterAnimation(SettingUtil.getListMode()) 16 | } 17 | 18 | override fun convert(holder: BaseViewHolder, item: SearchResponse) { 19 | holder.setText(R.id.flow_tag, item.name) 20 | holder.setTextColor(R.id.flow_tag, ColorUtil.randomColor()) 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/ShareAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import me.hgj.jetpackmvvm.demo.R 6 | import me.hgj.jetpackmvvm.demo.app.ext.setAdapterAnimation 7 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 8 | import me.hgj.jetpackmvvm.demo.data.model.bean.AriticleResponse 9 | 10 | 11 | /** 12 | * 分享的文章 adapter 13 | * @Author: hegaojian 14 | * @CreateDate: 2019/9/1 9:52 15 | */ 16 | class ShareAdapter(data: ArrayList) : 17 | BaseQuickAdapter( 18 | R.layout.item_share_ariticle, data 19 | ) { 20 | init { 21 | setAdapterAnimation(SettingUtil.getListMode()) 22 | } 23 | 24 | override fun convert(helper: BaseViewHolder, item: AriticleResponse) { 25 | //赋值 26 | item.run { 27 | helper.setText(R.id.item_share_title, title) 28 | helper.setText(R.id.item_share_date, niceDate) 29 | } 30 | } 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/SystemChildAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import me.hgj.jetpackmvvm.demo.R 6 | import me.hgj.jetpackmvvm.demo.app.ext.setAdapterAnimation 7 | import me.hgj.jetpackmvvm.demo.app.util.ColorUtil 8 | import me.hgj.jetpackmvvm.demo.app.util.SettingUtil 9 | import me.hgj.jetpackmvvm.demo.data.model.bean.ClassifyResponse 10 | import me.hgj.jetpackmvvm.ext.util.toHtml 11 | 12 | class SystemChildAdapter(data: ArrayList) : 13 | BaseQuickAdapter(R.layout.flow_layout, data) { 14 | 15 | init { 16 | setAdapterAnimation(SettingUtil.getListMode()) 17 | } 18 | 19 | override fun convert(holder: BaseViewHolder, item: ClassifyResponse) { 20 | holder.setText(R.id.flow_tag, item.name.toHtml()) 21 | holder.setTextColor(R.id.flow_tag, ColorUtil.randomColor()) 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/adapter/TestAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.adapter 2 | 3 | import android.widget.Switch 4 | import com.chad.library.adapter.base.BaseQuickAdapter 5 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 6 | import me.hgj.jetpackmvvm.demo.R 7 | 8 | /** 9 | * @author : hgj 10 | * @date : 2020/9/7 11 | * 海王测试Adapter,以后海王再问 问题 发红包 12 | */ 13 | 14 | class TestAdapter(data: ArrayList) :BaseQuickAdapter(R.layout.item_integral, data) { 15 | 16 | var clickAction: (position: Int, item: String, state: Boolean) -> Unit = { _, _, _ -> } 17 | 18 | override fun convert(holder: BaseViewHolder, item: String) { 19 | holder.getView(R.id.item_integral_rank).setOnCheckedChangeListener { _, isChecked -> 20 | clickAction.invoke(holder.adapterPosition, item, isChecked) 21 | } 22 | } 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/fragment/MainFragment.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.fragment 2 | 3 | import android.os.Bundle 4 | import androidx.lifecycle.Observer 5 | import kotlinx.android.synthetic.main.fragment_main.* 6 | import me.hgj.jetpackmvvm.demo.R 7 | import me.hgj.jetpackmvvm.demo.app.appViewModel 8 | import me.hgj.jetpackmvvm.demo.app.base.BaseFragment 9 | import me.hgj.jetpackmvvm.demo.app.ext.init 10 | import me.hgj.jetpackmvvm.demo.app.ext.initMain 11 | import me.hgj.jetpackmvvm.demo.app.ext.interceptLongClick 12 | import me.hgj.jetpackmvvm.demo.app.ext.setUiTheme 13 | import me.hgj.jetpackmvvm.demo.databinding.FragmentMainBinding 14 | import me.hgj.jetpackmvvm.demo.viewmodel.state.MainViewModel 15 | import me.hgj.jetpackmvvm.ext.nav 16 | import me.hgj.jetpackmvvm.ext.util.loge 17 | 18 | /** 19 | * 时间 : 2019/12/27 20 | * 作者 : hegaojian 21 | * 描述 :项目主页Fragment 22 | */ 23 | class MainFragment : BaseFragment() { 24 | 25 | override fun initView(savedInstanceState: Bundle?) { 26 | //初始化viewpager2 27 | mainViewpager.initMain(this) 28 | //初始化 bottomBar 29 | mainBottom.init{ 30 | when (it) { 31 | R.id.menu_main -> mainViewpager.setCurrentItem(0, false) 32 | R.id.menu_project -> mainViewpager.setCurrentItem(1, false) 33 | R.id.menu_system -> mainViewpager.setCurrentItem(2, false) 34 | R.id.menu_public -> mainViewpager.setCurrentItem(3, false) 35 | R.id.menu_me -> mainViewpager.setCurrentItem(4, false) 36 | } 37 | } 38 | mainBottom.interceptLongClick(R.id.menu_main,R.id.menu_project,R.id.menu_system,R.id.menu_public,R.id.menu_me) 39 | } 40 | 41 | override fun createObserver() { 42 | appViewModel.appColor.observeInFragment(this, Observer { 43 | setUiTheme(it, mainBottom) 44 | }) 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/ui/fragment/collect/CollectFragment.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.ui.fragment.collect 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.Fragment 5 | import kotlinx.android.synthetic.main.fragment_collect.* 6 | import kotlinx.android.synthetic.main.include_toolbar.* 7 | import me.hgj.jetpackmvvm.demo.R 8 | import me.hgj.jetpackmvvm.demo.app.appViewModel 9 | import me.hgj.jetpackmvvm.demo.viewmodel.request.RequestCollectViewModel 10 | import me.hgj.jetpackmvvm.demo.app.base.BaseFragment 11 | import me.hgj.jetpackmvvm.demo.app.ext.bindViewPager2 12 | import me.hgj.jetpackmvvm.demo.app.ext.init 13 | import me.hgj.jetpackmvvm.demo.app.ext.initClose 14 | import me.hgj.jetpackmvvm.demo.databinding.FragmentCollectBinding 15 | import me.hgj.jetpackmvvm.ext.nav 16 | 17 | /** 18 | * 作者 : hegaojian 19 | * 时间 : 2020/3/10 20 | * 描述 : 收藏 21 | */ 22 | class CollectFragment:BaseFragment() { 23 | 24 | var titleData = arrayListOf("文章","网址") 25 | 26 | private var fragments : ArrayList = arrayListOf() 27 | 28 | init { 29 | fragments.add(CollectAriticleFragment()) 30 | fragments.add(CollectUrlFragment()) 31 | } 32 | override fun initView(savedInstanceState: Bundle?) { 33 | //初始化时设置顶部主题颜色 34 | appViewModel.appColor.value?.let { collect_viewpager_linear.setBackgroundColor(it) } 35 | //初始化viewpager2 36 | collect_view_pager.init(this,fragments) 37 | //初始化 magic_indicator 38 | collect_magic_indicator.bindViewPager2(collect_view_pager,mStringList = titleData) 39 | toolbar.initClose(){ 40 | nav().navigateUp() 41 | } 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/request/RequestLookInfoViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.request 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 5 | import me.hgj.jetpackmvvm.demo.app.network.apiService 6 | import me.hgj.jetpackmvvm.demo.app.network.stateCallback.ListDataUiState 7 | import me.hgj.jetpackmvvm.demo.data.model.bean.AriticleResponse 8 | import me.hgj.jetpackmvvm.demo.data.model.bean.ShareResponse 9 | import me.hgj.jetpackmvvm.ext.request 10 | 11 | /** 12 | * 作者 : hegaojian 13 | * 时间 : 2020/3/4 14 | * 描述 : 15 | */ 16 | class RequestLookInfoViewModel : BaseViewModel() { 17 | 18 | var pageNo = 1 19 | 20 | var shareListDataUistate = MutableLiveData>() 21 | 22 | var shareResponse = MutableLiveData() 23 | 24 | fun getLookinfo(id: Int, isRefresh: Boolean) { 25 | if (isRefresh) { 26 | pageNo = 1 27 | } 28 | request({ apiService.getShareByidData(id, pageNo) }, { 29 | //请求成功 30 | pageNo++ 31 | shareResponse.value = it 32 | val listDataUiState = 33 | ListDataUiState( 34 | isSuccess = true, 35 | isRefresh = it.shareArticles.isRefresh(), 36 | isEmpty = it.shareArticles.isEmpty(), 37 | hasMore = it.shareArticles.hasMore(), 38 | isFirstEmpty = isRefresh && it.shareArticles.isEmpty(), 39 | listData = it.shareArticles.datas 40 | ) 41 | shareListDataUistate.value = listDataUiState 42 | }, { 43 | //请求失败 44 | val listDataUiState = 45 | ListDataUiState( 46 | isSuccess = false, 47 | errMessage = it.errorMsg, 48 | isRefresh = isRefresh, 49 | listData = arrayListOf() 50 | ) 51 | shareListDataUistate.value = listDataUiState 52 | }) 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/request/RequestMeViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.request 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 5 | import me.hgj.jetpackmvvm.demo.app.network.apiService 6 | import me.hgj.jetpackmvvm.demo.data.model.bean.IntegralResponse 7 | import me.hgj.jetpackmvvm.ext.request 8 | import me.hgj.jetpackmvvm.state.ResultState 9 | 10 | /** 11 | * 作者 : hegaojian 12 | * 时间 : 2019/12/27 13 | * 描述 : 14 | */ 15 | class RequestMeViewModel : BaseViewModel() { 16 | 17 | var meData = MutableLiveData>() 18 | 19 | fun getIntegral() { 20 | request({ apiService.getIntegral() }, meData) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/request/RequestSearchViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.request 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 5 | import me.hgj.jetpackmvvm.demo.app.network.apiService 6 | import me.hgj.jetpackmvvm.demo.app.util.CacheUtil 7 | import me.hgj.jetpackmvvm.demo.data.model.bean.ApiPagerResponse 8 | import me.hgj.jetpackmvvm.demo.data.model.bean.AriticleResponse 9 | import me.hgj.jetpackmvvm.demo.data.model.bean.SearchResponse 10 | import me.hgj.jetpackmvvm.ext.launch 11 | import me.hgj.jetpackmvvm.ext.request 12 | import me.hgj.jetpackmvvm.state.ResultState 13 | 14 | /** 15 | * 作者 : hegaojian 16 | * 时间 : 2020/2/29 17 | * 描述 : 18 | */ 19 | class RequestSearchViewModel : BaseViewModel() { 20 | 21 | var pageNo = 0 22 | 23 | //搜索热词数据 24 | var hotData: MutableLiveData>> = MutableLiveData() 25 | 26 | //搜索结果数据 27 | var seachResultData: MutableLiveData>>> = 28 | MutableLiveData() 29 | 30 | //搜索历史词数据 31 | var historyData: MutableLiveData> = MutableLiveData() 32 | 33 | /** 34 | * 获取热门数据 35 | */ 36 | fun getHotData() { 37 | request({ apiService.getSearchData() }, hotData) 38 | } 39 | 40 | /** 41 | * 获取历史数据 42 | */ 43 | fun getHistoryData() { 44 | launch({ 45 | CacheUtil.getSearchHistoryData() 46 | }, { 47 | historyData.value = it 48 | }, { 49 | //获取本地历史数据出异常了 50 | }) 51 | } 52 | 53 | /** 54 | * 根据字符串搜索结果 55 | */ 56 | fun getSearchResultData(searchKey: String, isRefresh: Boolean) { 57 | if (isRefresh) { 58 | pageNo = 0 59 | } 60 | request( 61 | { apiService.getSearchDataByKey(pageNo, searchKey) }, 62 | seachResultData 63 | ) 64 | } 65 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/AriticleViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | import me.hgj.jetpackmvvm.callback.databind.StringObservableField 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2020/3/11 9 | * 描述 : 10 | */ 11 | class AriticleViewModel : BaseViewModel() { 12 | 13 | //分享文章标题 14 | var shareTitle = StringObservableField() 15 | 16 | //分享文章网址 17 | var shareUrl = StringObservableField() 18 | 19 | //分享文章的人 20 | var shareName = StringObservableField() 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/DemoViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * @author : hgj 7 | * @date : 2020/7/13 8 | * 9 | */ 10 | class DemoViewModel : BaseViewModel() { 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/HomeViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2019/12/27 8 | */ 9 | class HomeViewModel : BaseViewModel(){ 10 | 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/IntegralViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import androidx.databinding.ObservableField 4 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 5 | import me.hgj.jetpackmvvm.demo.data.model.bean.IntegralResponse 6 | 7 | /** 8 | * 作者 : hegaojian 9 | * 时间 : 2020/3/10 10 | * 描述 : 11 | */ 12 | class IntegralViewModel : BaseViewModel() { 13 | 14 | var rank = ObservableField() 15 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/LoginRegisterViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import android.view.View 4 | import androidx.databinding.ObservableField 5 | import androidx.databinding.ObservableInt 6 | import androidx.lifecycle.map 7 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 8 | import me.hgj.jetpackmvvm.callback.databind.BooleanObservableField 9 | import me.hgj.jetpackmvvm.callback.databind.StringObservableField 10 | import me.hgj.jetpackmvvm.callback.livedata.StringLiveData 11 | import me.hgj.jetpackmvvm.ext.util.logd 12 | 13 | /** 14 | * 作者 : hegaojian 15 | * 时间 : 2019/12/23 16 | * 描述 :登录注册的ViewModel 17 | */ 18 | class LoginRegisterViewModel : BaseViewModel() { 19 | 20 | //用户名 21 | var username = StringObservableField() 22 | 23 | //密码(登录注册界面) 24 | var password = StringObservableField() 25 | 26 | var password2 = StringObservableField() 27 | 28 | //是否显示明文密码(登录注册界面) 29 | var isShowPwd = BooleanObservableField() 30 | 31 | var isShowPwd2 = BooleanObservableField() 32 | 33 | 34 | //用户名清除按钮是否显示 不要在 xml 中写逻辑 所以逻辑判断放在这里 35 | var clearVisible = object :ObservableInt(username){ 36 | override fun get(): Int { 37 | return if(username.get().isEmpty()){ 38 | View.GONE 39 | }else{ 40 | View.VISIBLE 41 | } 42 | } 43 | } 44 | 45 | //密码显示按钮是否显示 不要在 xml 中写逻辑 所以逻辑判断放在这里 46 | var passwordVisible = object :ObservableInt(password){ 47 | override fun get(): Int { 48 | return if(password.get().isEmpty()){ 49 | View.GONE 50 | }else{ 51 | View.VISIBLE 52 | } 53 | } 54 | } 55 | 56 | //密码显示按钮是否显示 不要在 xml 中写逻辑 所以逻辑判断放在这里 57 | var passwordVisible2 = object :ObservableInt(password2){ 58 | override fun get(): Int { 59 | return if(password2.get().isEmpty()){ 60 | View.GONE 61 | }else{ 62 | View.VISIBLE 63 | } 64 | } 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/LookInfoViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | import me.hgj.jetpackmvvm.callback.databind.StringObservableField 5 | 6 | /** 7 | * 作者 : hegaojian 8 | * 时间 : 2020/3/4 9 | * 描述 : 10 | */ 11 | class LookInfoViewModel : BaseViewModel() { 12 | 13 | var name = StringObservableField("--") 14 | 15 | var imageUrl = 16 | StringObservableField("https://upload.jianshu.io/users/upload_avatars/9305757/93322613-ff1a-445c-80f9-57f088f7c1b1.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/300/format/webp") 17 | 18 | var info = StringObservableField() 19 | 20 | 21 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | 5 | class MainViewModel : BaseViewModel() { 6 | 7 | 8 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/MeViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | import me.hgj.jetpackmvvm.callback.databind.IntObservableField 5 | import me.hgj.jetpackmvvm.callback.databind.StringObservableField 6 | import me.hgj.jetpackmvvm.demo.app.util.ColorUtil 7 | 8 | /** 9 | * 作者 : hegaojian 10 | * 时间 : 2019/12/27 11 | * 描述 : 专门存放 MeFragment 界面数据的ViewModel 12 | */ 13 | class MeViewModel : BaseViewModel() { 14 | 15 | var name = StringObservableField("请先登录~") 16 | 17 | var integral = IntObservableField(0) 18 | 19 | var info = StringObservableField("id:-- 排名:-") 20 | 21 | var imageUrl = StringObservableField(ColorUtil.randomImage()) 22 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/ProjectViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2020/2/28 8 | * 描述 : 9 | */ 10 | class ProjectViewModel : BaseViewModel() { 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/PublicNumberViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2020/2/29 8 | * 描述 : 9 | */ 10 | class PublicNumberViewModel : BaseViewModel() { 11 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/SearchViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2020/2/29 8 | * 描述 : 9 | */ 10 | class SearchViewModel : BaseViewModel() { 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/TodoViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | import me.hgj.jetpackmvvm.callback.databind.IntObservableField 5 | import me.hgj.jetpackmvvm.callback.databind.StringObservableField 6 | import me.hgj.jetpackmvvm.demo.data.model.enums.TodoType 7 | import me.hgj.jetpackmvvm.ext.launch 8 | 9 | /** 10 | * 作者 : hegaojian 11 | * 时间 : 2020/3/11 12 | * 描述 : 13 | */ 14 | class TodoViewModel : BaseViewModel() { 15 | 16 | //标题 17 | var todoTitle = StringObservableField() 18 | 19 | //内容 20 | var todoContent = 21 | StringObservableField() 22 | 23 | //时间 24 | var todoTime = StringObservableField() 25 | 26 | //优先级 27 | var todoLeve = 28 | StringObservableField(TodoType.TodoType1.content) 29 | 30 | //优先级颜色 31 | var todoColor = 32 | IntObservableField(TodoType.TodoType1.color) 33 | 34 | fun xx(): Unit { 35 | launch({ 36 | 37 | },{ 38 | 39 | }) 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/TreeViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2020/3/2 8 | * 描述 : 9 | */ 10 | class TreeViewModel : BaseViewModel() { 11 | 12 | 13 | } -------------------------------------------------------------------------------- /app/src/main/java/me/hgj/jetpackmvvm/demo/viewmodel/state/WebViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.hgj.jetpackmvvm.demo.viewmodel.state 2 | 3 | import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * 作者 : hegaojian 7 | * 时间 : 2020/3/3 8 | * 描述 : 9 | */ 10 | class WebViewModel : BaseViewModel() { 11 | 12 | //是否收藏 13 | var collect = false 14 | 15 | //收藏的Id 16 | var ariticleId = 0 17 | 18 | //标题 19 | var showTitle: String = "" 20 | 21 | //文章的网络访问路径 22 | var url: String = "" 23 | 24 | //需要收藏的类型 具体参数说明请看 CollectType 枚举类 25 | var collectType = 0 26 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/push_bottom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/anim/push_bottom_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/color/bottom_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/flow_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/item_imgselector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/item_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/collect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/cxk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/cxk.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/default_project_img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/default_project_img.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/fab_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/fab_up.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_account.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_clear.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_close.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_collect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_collected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_collected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_custom_drawable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_custom_drawable.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_demo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_done.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_favorite.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_guize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_guize.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_history.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_more.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_password_see.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_password_see.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_password_see_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_password_see_on.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_right.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_tag.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_yiguoqi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/ic_yiguoqi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/jairu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/jairu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/jifen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/jifen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/load_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/load_empty.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/load_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/load_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/menu_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/menu_main.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/menu_me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/menu_me.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/menu_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/menu_project.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/menu_public.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/menu_public.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/menu_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/menu_tree.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/renwu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/renwu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/shezhi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/shezhi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/web.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/wenzhang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hegaojian/JetpackMvvm/355946850374837e0fc69413123fc5615eb47803/app/src/main/res/drawable-xxxhdpi/wenzhang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bottom_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_shap.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cardview_shap.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/flow_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/forground_shap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_imgselector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyvisibily_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/title_lable_shap.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/title_lable_shap1.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 |