├── .gitignore ├── GIF.gif ├── LICENSE ├── QR_WanAndroid.png ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── release │ ├── app-release.apk │ └── output.json ├── src │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── king │ │ │ └── wanandroid │ │ │ └── ExampleInstrumentedTest.java │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── ic_launcher-web.png │ │ ├── java │ │ │ └── com │ │ │ │ └── king │ │ │ │ └── wanandroid │ │ │ │ ├── App.java │ │ │ │ ├── api │ │ │ │ ├── Api.java │ │ │ │ ├── ApiCallback.java │ │ │ │ ├── ApiService.java │ │ │ │ └── LogInterceptor.java │ │ │ │ ├── app │ │ │ │ ├── about │ │ │ │ │ └── AboutActivity.java │ │ │ │ ├── account │ │ │ │ │ ├── LoginActivity.java │ │ │ │ │ ├── LoginViewModel.java │ │ │ │ │ └── RegisterActivity.java │ │ │ │ ├── adapter │ │ │ │ │ ├── ArticleAdapter.java │ │ │ │ │ ├── BindingAdapter.java │ │ │ │ │ ├── BindingHolder.java │ │ │ │ │ ├── CollectAdapter.java │ │ │ │ │ ├── EmptyAdapter.java │ │ │ │ │ ├── HistoryTagAdapter.java │ │ │ │ │ ├── HotKeyTagAdapter.java │ │ │ │ │ ├── SimpleBindingAdapter.java │ │ │ │ │ ├── TreeAdapter.java │ │ │ │ │ └── TreeTagAdapter.java │ │ │ │ ├── base │ │ │ │ │ ├── BaseActivity.java │ │ │ │ │ ├── BaseRepository.java │ │ │ │ │ ├── BaseViewModel.java │ │ │ │ │ ├── BindingActivity.java │ │ │ │ │ ├── DataRepository.java │ │ │ │ │ ├── DataViewModel.java │ │ │ │ │ ├── MVVMActivity.java │ │ │ │ │ └── ViewModelFactory.java │ │ │ │ ├── collect │ │ │ │ │ ├── CollectActivity.java │ │ │ │ │ └── CollectViewModel.java │ │ │ │ ├── comm │ │ │ │ │ ├── Constants.java │ │ │ │ │ ├── Status.java │ │ │ │ │ └── Tree.java │ │ │ │ ├── home │ │ │ │ │ ├── HomeActivity.java │ │ │ │ │ └── HomeViewModel.java │ │ │ │ ├── navi │ │ │ │ │ ├── NaviActivity.java │ │ │ │ │ └── NaviViewModel.java │ │ │ │ ├── search │ │ │ │ │ ├── SearchActivity.java │ │ │ │ │ └── SearchViewModel.java │ │ │ │ ├── splash │ │ │ │ │ └── SplashActivity.java │ │ │ │ ├── tree │ │ │ │ │ ├── TreeActivity.java │ │ │ │ │ ├── TreeChildrenActivity.java │ │ │ │ │ └── TreeViewModel.java │ │ │ │ └── web │ │ │ │ │ └── WebActivity.java │ │ │ │ ├── bean │ │ │ │ ├── ArticleBean.java │ │ │ │ ├── BannerBean.java │ │ │ │ ├── BaseResult.java │ │ │ │ ├── CollectBean.java │ │ │ │ ├── DataBean.java │ │ │ │ ├── HotKeyBean.java │ │ │ │ ├── NaviBean.java │ │ │ │ ├── Resource.java │ │ │ │ ├── Result.java │ │ │ │ ├── SearchHistory.java │ │ │ │ ├── TreeBean.java │ │ │ │ ├── User.java │ │ │ │ └── VersionBean.java │ │ │ │ ├── dao │ │ │ │ ├── AppDatabase.java │ │ │ │ ├── DataSource.java │ │ │ │ └── SearchHistoryDao.java │ │ │ │ ├── di │ │ │ │ ├── component │ │ │ │ │ ├── AppComponent.java │ │ │ │ │ └── BaseActivitySubComponent.java │ │ │ │ ├── module │ │ │ │ │ ├── ActivityModule.java │ │ │ │ │ ├── AppModule.java │ │ │ │ │ ├── HomeModule.java │ │ │ │ │ ├── HttpModule.java │ │ │ │ │ ├── ViewModelFactoryModule.java │ │ │ │ │ └── ViewModelModule.java │ │ │ │ └── scope │ │ │ │ │ ├── ActivityScope.java │ │ │ │ │ ├── FragmentScope.java │ │ │ │ │ └── ViewModelKey.java │ │ │ │ ├── glide │ │ │ │ └── WanGlideModule.java │ │ │ │ └── util │ │ │ │ ├── AES.java │ │ │ │ ├── Base64.java │ │ │ │ ├── RandomUtils.java │ │ │ │ └── TimeUtils.java │ │ └── res │ │ │ ├── anim │ │ │ ├── cycle_3.xml │ │ │ ├── in.xml │ │ │ ├── out.xml │ │ │ ├── shake.xml │ │ │ └── splash.xml │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable-xxhdpi │ │ │ ├── btn_back_normal.png │ │ │ ├── btn_back_pressed.png │ │ │ ├── btn_bg_normal.9.png │ │ │ ├── btn_bg_pressed.9.png │ │ │ ├── btn_black_back_normal.png │ │ │ ├── btn_black_back_pressed.png │ │ │ ├── btn_clear.png │ │ │ ├── btn_close_normal.png │ │ │ ├── btn_close_pressed.png │ │ │ ├── btn_delete_normal.png │ │ │ ├── btn_delete_pressed.png │ │ │ ├── btn_menu_normal.png │ │ │ ├── btn_menu_pressed.png │ │ │ ├── btn_more_normal.png │ │ │ ├── btn_more_pressed.png │ │ │ ├── btn_navi_normal.png │ │ │ ├── btn_navi_pressed.png │ │ │ ├── btn_none.png │ │ │ ├── btn_search_normal.png │ │ │ ├── btn_search_pressed.png │ │ │ ├── collect.png │ │ │ ├── collected.png │ │ │ ├── github.png │ │ │ ├── home_bg.9.png │ │ │ ├── ic_about_image.png │ │ │ ├── ic_collect.png │ │ │ ├── ic_empty.png │ │ │ ├── ic_explorer.png │ │ │ ├── ic_github.png │ │ │ ├── ic_menu_about.png │ │ │ ├── ic_menu_collect.png │ │ │ ├── ic_menu_logout.png │ │ │ ├── ic_menu_navi.png │ │ │ ├── ic_menu_project.png │ │ │ ├── ic_menu_system.png │ │ │ ├── ic_refresh.png │ │ │ ├── ic_right_arrow.png │ │ │ ├── ic_share.png │ │ │ └── ic_top.png │ │ │ ├── drawable │ │ │ ├── btn_back_selector.xml │ │ │ ├── btn_bg_selector.xml │ │ │ ├── btn_black_back_selector.xml │ │ │ ├── btn_clear_selector.xml │ │ │ ├── btn_close_selector.xml │ │ │ ├── btn_delete_selector.xml │ │ │ ├── btn_menu_selector.xml │ │ │ ├── btn_more_selector.xml │ │ │ ├── btn_navi_selector.xml │ │ │ ├── btn_search_selector.xml │ │ │ ├── collect_select_selector.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── line_drawable.xml │ │ │ ├── line_drawable_8.xml │ │ │ ├── search_bg.xml │ │ │ ├── tag_bg_normal.xml │ │ │ ├── tag_bg_pressed.xml │ │ │ └── tag_bg_selector.xml │ │ │ ├── layout │ │ │ ├── about_activity.xml │ │ │ ├── collect_activity.xml │ │ │ ├── empty_layout.xml │ │ │ ├── home_activity.xml │ │ │ ├── line_xh.xml │ │ │ ├── login_activity.xml │ │ │ ├── menu_layout.xml │ │ │ ├── navi_activity.xml │ │ │ ├── popup_menu.xml │ │ │ ├── register_activity.xml │ │ │ ├── rv_article_item.xml │ │ │ ├── rv_collect_item.xml │ │ │ ├── rv_navi_menu_item.xml │ │ │ ├── rv_tree_item.xml │ │ │ ├── rv_tree_project_item.xml │ │ │ ├── search_activity.xml │ │ │ ├── splash_activity.xml │ │ │ ├── toolbar.xml │ │ │ ├── top_title_back_bar.xml │ │ │ ├── top_title_bar.xml │ │ │ ├── tree_activity.xml │ │ │ ├── tree_children_activity.xml │ │ │ ├── tree_tag_item.xml │ │ │ └── web_activity.xml │ │ │ ├── menu │ │ │ ├── about_menu.xml │ │ │ └── toolbar_menu.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values-v21 │ │ │ └── dimens.xml │ │ │ ├── values │ │ │ ├── about.xml │ │ │ ├── arrays.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── integers.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ └── provider_paths.xml │ └── test │ │ └── java │ │ └── com │ │ └── king │ │ └── wanandroid │ │ └── ExampleUnitTest.java └── tinker-support.gradle ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── versions.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | ### Android template 10 | # Built application files 11 | #*.apk 12 | *.ap_ 13 | 14 | # Files for the ART/Dalvik VM 15 | *.dex 16 | 17 | # Java class files 18 | *.class 19 | 20 | # Generated files 21 | bin/ 22 | gen/ 23 | out/ 24 | 25 | # Gradle files 26 | .gradle/ 27 | build/ 28 | 29 | # Local configuration file (sdk path, etc) 30 | local.properties 31 | 32 | # Proguard folder generated by Eclipse 33 | proguard/ 34 | 35 | # Log Files 36 | *.log 37 | 38 | # Android Studio Navigation editor temp files 39 | .navigation/ 40 | 41 | # Android Studio captures folder 42 | captures/ 43 | 44 | # IntelliJ 45 | *.iml 46 | .idea/workspace.xml 47 | .idea/tasks.xml 48 | .idea/gradle.xml 49 | .idea/assetWizardSettings.xml 50 | .idea/dictionaries 51 | .idea/libraries 52 | .idea/caches 53 | 54 | # Keystore files 55 | # Uncomment the following line if you do not want to check your keystore files in. 56 | #*.jks 57 | 58 | # External native build folder generated in Android Studio 2.2 and later 59 | .externalNativeBuild 60 | 61 | # Google Services (e.g. APIs or Firebase) 62 | google-services.json 63 | 64 | # Freeline 65 | freeline.py 66 | freeline/ 67 | freeline_project_description.json 68 | 69 | # fastlane 70 | fastlane/report.xml 71 | fastlane/Preview.html 72 | fastlane/screenshots 73 | fastlane/test_output 74 | fastlane/readme.md 75 | 76 | ### Android template 77 | # Built application files 78 | #*.apk 79 | *.ap_ 80 | 81 | # Files for the ART/Dalvik VM 82 | *.dex 83 | 84 | # Java class files 85 | *.class 86 | 87 | # Generated files 88 | bin/ 89 | gen/ 90 | out/ 91 | 92 | # Gradle files 93 | .gradle/ 94 | build/ 95 | 96 | # Local configuration file (sdk path, etc) 97 | local.properties 98 | 99 | # Proguard folder generated by Eclipse 100 | proguard/ 101 | 102 | # Log Files 103 | *.log 104 | 105 | # Android Studio Navigation editor temp files 106 | .navigation/ 107 | 108 | # Android Studio captures folder 109 | captures/ 110 | 111 | # IntelliJ 112 | *.iml 113 | .idea/workspace.xml 114 | .idea/tasks.xml 115 | .idea/gradle.xml 116 | .idea/assetWizardSettings.xml 117 | .idea/dictionaries 118 | .idea/libraries 119 | .idea/caches 120 | 121 | # Keystore files 122 | # Uncomment the following line if you do not want to check your keystore files in. 123 | #*.jks 124 | 125 | # External native build folder generated in Android Studio 2.2 and later 126 | .externalNativeBuild 127 | 128 | # Google Services (e.g. APIs or Firebase) 129 | google-services.json 130 | 131 | # Freeline 132 | freeline.py 133 | freeline/ 134 | freeline_project_description.json 135 | 136 | # fastlane 137 | fastlane/report.xml 138 | fastlane/Preview.html 139 | fastlane/screenshots 140 | fastlane/test_output 141 | fastlane/readme.md 142 | 143 | -------------------------------------------------------------------------------- /GIF.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/GIF.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jenly Yu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QR_WanAndroid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/QR_WanAndroid.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WanAndroid 2 | 3 | ![Image](app/src/main/ic_launcher-web.png) 4 | 5 | [![Download](https://img.shields.io/badge/download-APK-brightgreen?logo=github)](https://raw.githubusercontent.com/jenly1314/WanAndroid/master/app/release/app-release.apk) 6 | [![API](https://img.shields.io/badge/API-16%2B-brightgreen?logo=android)](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels) 7 | [![License](https://img.shields.io/github/license/jenly1314/WanAndroid?logo=open-source-initiative)](https://opensource.org/licenses/mit) 8 | 9 | WanAndroid App 是基于 [WanAndroid](http://www.wanandroid.com) 网站提供API打造的一款开源客户端。界面精美,优质体验。 10 | 11 | * App 采用MVVM模式设计,基于Architecture Components dependencies(Lifecycles,LiveData,ViewModel,Room) + Dagger + ARouter + DataBinding + Glide + Retrofit 构建。 12 | 13 | > 里面可能包含了你想要学习的各种技术要点,欢迎star。 14 | 15 | 16 | ## 效果展示 17 | ![Image](GIF.gif) 18 | 19 | > 录制的gif效果有点不清晰,你可以直接[下载App](https://raw.githubusercontent.com/jenly1314/WanAndroid/master/app/release/app-release.apk)体验效果。 20 | 21 | > 如果github下载App比较慢,可以尝试使用[备用地址](https://gitee.com/jenly1314/WanAndroid/raw/master/app/release/app-release.apk)进行下载。 22 | 23 | ## 相关推荐 24 | - [MVVMFrame](https://github.com/jenly1314/MVVMFrame) 一个基于Google官方推出的JetPack构建的MVVM快速开发框架。 25 | - [AppTemplate](https://github.com/jenly1314/AppTemplate) 一款基于**MVVMFrame**构建的App模板。 26 | - [KingWeather](https://github.com/jenly1314/KingWeather) 一款天气预报APP。 27 | - [EasyChat](https://github.com/yetel/EasyChatAndroidClient) 一款即时通讯APP。 28 | - [MVVMFrameComponent](https://github.com/jenly1314/MVVMFrameComponent) 一款基于**MVVMFrame**构建的组件化方案。 29 | - [AppUpdater](http://github.com/jenly1314/AppUpdater) 一个专注于App更新,一键傻瓜式集成App版本升级的轻量开源库。 30 | - [RetrofitHelper](http://github.com/jenly1314/RetrofitHelper) 一个支持动态改变BaseUrl,动态配置超时时长的Retrofit帮助类。 31 | - [BaseUrlManager](http://github.com/jenly1314/BaseUrlManager) 一个BaseUrl管理器,主要用于打测试包时,一个App可动态切换到不同的开发环境或测试环境。 32 | - [SuperTextView](http://github.com/jenly1314/SuperTextView) 一个在TextView的基础上扩展了几种动画效果的控件。 33 | - [ImageViewer](http://github.com/AndroidKTX/ImageViewer) 一个图片查看器,一般用来查看图片详情或查看大图时使用。 34 | - [GuidePage](http://github.com/AndroidKTX/GuidePage) 一个App欢迎引导页。一般用于首次打开App时场景,通过引导页指南,概述App特色等相关信息。 35 | - [LogX](http://github.com/jenly1314/LogX) 一个轻量而强大的日志框架;好用不解释。 36 | - [KVCache](http://github.com/jenly1314/KVCache) 一个便于统一管理的键值缓存库;支持无缝切换缓存实现。 37 | - [AndroidKTX](http://github.com/AndroidKTX/AndroidKTX) 一个简化 Android 开发的 Kotlin 工具类集合。 38 | - [AndroidUtil](http://github.com/AndroidUtil/AndroidUtil) 一个整理了Android常用工具类集合,平时在开发的过程中可能会经常用到。 39 | 40 | ## 版本记录 41 | 42 | #### 2018-7-16 v1.0 初始版本 43 | * 登录注册 44 | * 我的收藏 45 | * 知识体系 46 | * 项目分类 47 | * 网址导航 48 | * 搜索功能 49 | * 分享功能 50 | * 关于我们 51 | 52 | ## 感谢 53 | 54 | 感谢[鸿洋](https://github.com/hongyangAndroid)提供的[WanAndroid API](http://www.wanandroid.com/blog/show/2) 55 | 56 | 感谢所有开源开发者的贡献与开源精神。 57 | 58 | --- 59 | 60 | ![footer](https://jenly1314.github.io/page/footer.svg) 61 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/release/app-release.apk -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] -------------------------------------------------------------------------------- /app/src/androidTest/java/com/king/wanandroid/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | import android.util.Log; 7 | 8 | import com.king.wanandroid.bean.SearchHistory; 9 | 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | 13 | import java.util.List; 14 | 15 | import static org.junit.Assert.*; 16 | 17 | /** 18 | * Instrumented test, which will execute on an Android device. 19 | * 20 | * @see Testing documentation 21 | */ 22 | @RunWith(AndroidJUnit4.class) 23 | public class ExampleInstrumentedTest { 24 | @Test 25 | public void useAppContext() { 26 | // Context of the app under test. 27 | Context appContext = InstrumentationRegistry.getTargetContext(); 28 | 29 | assertEquals("com.king.wanandroid", appContext.getPackageName()); 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 36 | 37 | 40 | 41 | 44 | 45 | 47 | 48 | 50 | 51 | 53 | 54 | 57 | 58 | 60 | 61 | 63 | 64 | 65 | 66 | 69 | 70 | 73 | 74 | 79 | 82 | 83 | 84 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/api/Api.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.api; 2 | 3 | import com.king.wanandroid.bean.ArticleBean; 4 | import com.king.wanandroid.bean.BaseResult; 5 | import com.king.wanandroid.bean.DataBean; 6 | 7 | import java.util.List; 8 | 9 | import javax.inject.Inject; 10 | 11 | import retrofit2.Callback; 12 | 13 | /** 14 | * @author Jenly Jenly 15 | */ 16 | public class Api { 17 | 18 | private ApiService apiService; 19 | 20 | @Inject 21 | public Api(ApiService apiService){ 22 | this.apiService = apiService; 23 | } 24 | 25 | public void getArticlesList(int curPage, Callback>>> callback){ 26 | apiService.getArticlesList(curPage).enqueue(callback); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/api/ApiCallback.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.api; 2 | 3 | import com.king.wanandroid.bean.BaseResult; 4 | 5 | import retrofit2.Call; 6 | import retrofit2.Callback; 7 | import retrofit2.Response; 8 | import timber.log.Timber; 9 | 10 | /** 11 | * @author Jenly Jenly 12 | */ 13 | public abstract class ApiCallback implements Callback { 14 | 15 | @Override 16 | public void onResponse(Call call, Response response) { 17 | T data = response.body(); 18 | onResponse(call,data); 19 | } 20 | 21 | @Override 22 | public void onFailure(Call call, Throwable t) { 23 | Timber.w(t); 24 | onError(call,t); 25 | } 26 | 27 | 28 | public abstract void onResponse(Call call,T result); 29 | 30 | public abstract void onError(Call call,Throwable t); 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/api/ApiService.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.api; 2 | 3 | import com.king.wanandroid.bean.ArticleBean; 4 | import com.king.wanandroid.bean.BannerBean; 5 | import com.king.wanandroid.bean.BaseResult; 6 | import com.king.wanandroid.bean.CollectBean; 7 | import com.king.wanandroid.bean.HotKeyBean; 8 | import com.king.wanandroid.bean.DataBean; 9 | import com.king.wanandroid.bean.NaviBean; 10 | import com.king.wanandroid.bean.Result; 11 | import com.king.wanandroid.bean.TreeBean; 12 | import com.king.wanandroid.bean.User; 13 | import com.king.wanandroid.bean.VersionBean; 14 | 15 | import java.util.List; 16 | 17 | import retrofit2.Call; 18 | import retrofit2.http.Field; 19 | import retrofit2.http.FormUrlEncoded; 20 | import retrofit2.http.GET; 21 | import retrofit2.http.POST; 22 | import retrofit2.http.Path; 23 | import retrofit2.http.Query; 24 | 25 | /** 26 | * @author Jenly Jenly 27 | */ 28 | public interface ApiService { 29 | 30 | /** 31 | * 获取文章列表 32 | * @param curPage 页码从0开始 33 | * @return 34 | */ 35 | @GET("article/list/{curPage}/json") 36 | Call>>> getArticlesList(@Path("curPage") int curPage); 37 | 38 | /** 39 | * 首页Banner 40 | * @return 41 | */ 42 | @GET("banner/json") 43 | Call>> getBanner(); 44 | 45 | /** 46 | * 搜索热词 47 | * @return 48 | */ 49 | @GET("hotkey/json") 50 | Call>> getHotKey(); 51 | 52 | /** 53 | * 知识体系 54 | * @return 55 | */ 56 | @GET("tree/json") 57 | Call>> getSystem(); 58 | 59 | /** 60 | * 项目分类 从第1页开始 61 | * @return 62 | */ 63 | @GET("project/tree/json") 64 | Call>> getProject(); 65 | 66 | /** 67 | * 项目列表 68 | * @param curPage 从第0页开始 69 | * @param id 70 | * @return 71 | */ 72 | @GET("project/list/{curPage}/json") 73 | Call>>> getProjectList(@Path("curPage")int curPage, @Query("cid")int id); 74 | 75 | 76 | /** 77 | * 获取文章列表 78 | * @param curPage 79 | * @param id 文章分类id 80 | * @return 81 | */ 82 | @GET("article/list/{curPage}/json") 83 | Call>>> getArticlesList(@Path("curPage")int curPage, @Query("cid")int id); 84 | 85 | /** 86 | * 登录 87 | * @param username 88 | * @param password 89 | * @return 90 | */ 91 | @FormUrlEncoded 92 | @POST("user/login") 93 | Call> login(@Field("username") String username,@Field("password")String password); 94 | 95 | /** 96 | * 注册 97 | * @param username 98 | * @param password 99 | * @param repassword 100 | * @return 101 | */ 102 | @FormUrlEncoded 103 | @POST("user/register") 104 | Call> register(@Field("username")String username,@Field("password")String password,@Field("repassword")String repassword); 105 | 106 | /** 107 | * 收藏站内文章 108 | * @param id 109 | * @return 110 | */ 111 | @POST("lg/collect/{id}/json") 112 | Call> collect(@Path("id") int id); 113 | 114 | /** 115 | * 收藏站外文章 116 | * @param title 117 | * @param author 118 | * @param link 119 | * @return 120 | */ 121 | @FormUrlEncoded 122 | @POST("lg/collect/add/json") 123 | Call> collect(@Field("title")String title,@Field("author")String author,@Field("link")String link); 124 | 125 | /** 126 | * 获取收藏列表 127 | * @param curPage 从第0页开始 128 | * @return 129 | */ 130 | @GET("lg/collect/list/{curPage}/json") 131 | Call>>> getCollectList(@Path("curPage") int curPage); 132 | 133 | /** 134 | * 取消文章列表中的收藏 135 | * @param id 136 | * @return 137 | */ 138 | @POST("lg/uncollect_originId/{id}/json") 139 | Call unCollect(@Path("id") int id); 140 | 141 | /** 142 | * 取消我的收藏中的收藏 143 | * @param id 144 | * @return 145 | */ 146 | @FormUrlEncoded 147 | @POST("lg/uncollect/{id}/json") 148 | Call unMyCollect(@Path("id") int id,@Field("originId")int originId); 149 | 150 | /** 151 | * 搜索热词 152 | * @return 153 | */ 154 | @GET("hotkey/json") 155 | Call>> getHotkey(); 156 | 157 | /** 158 | * 搜索 159 | * @param curPage 160 | * @param key 161 | * @return 162 | */ 163 | @FormUrlEncoded 164 | @POST("article/query/{curPage}/json") 165 | Call>>> getArticlesList(@Path("curPage")int curPage, @Field("k")String key); 166 | 167 | /** 168 | * 导航 169 | * @return 170 | */ 171 | @GET("navi/json") 172 | Call>> getNavi(); 173 | 174 | /** 175 | * 版本检测 176 | * @return 177 | */ 178 | @GET("tools/mockapi/3273/WanAndroid") 179 | Call> checkVersion(); 180 | 181 | } 182 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/api/LogInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.api; 2 | 3 | import java.io.IOException; 4 | import java.util.logging.Logger; 5 | 6 | import okhttp3.Interceptor; 7 | import okhttp3.MediaType; 8 | import okhttp3.Request; 9 | import okhttp3.RequestBody; 10 | import okhttp3.Response; 11 | import okhttp3.ResponseBody; 12 | import okio.Buffer; 13 | import timber.log.Timber; 14 | 15 | /** 16 | * @author Jenly Jenly 17 | */ 18 | public class LogInterceptor implements Interceptor { 19 | @Override 20 | public Response intercept(Chain chain) throws IOException { 21 | Request request = chain.request(); 22 | Timber.i(String.format("%1$s->%2$s",request.method(),request.url())); 23 | if(request.headers()!=null){ 24 | Timber.i("Headers:" + request.headers()); 25 | } 26 | if(request.body()!=null){ 27 | Timber.i("RequestBody:" + bodyToString(request.body())); 28 | } 29 | 30 | Response response = chain.proceed(chain.request()); 31 | MediaType mediaType = response.body().contentType(); 32 | String responseBody = response.body().string(); 33 | Timber.d("ResponseBody:" + responseBody); 34 | 35 | return response.newBuilder() 36 | .body(ResponseBody.create(mediaType, responseBody)) 37 | .build(); 38 | } 39 | 40 | private String bodyToString(final RequestBody request) { 41 | if(request!=null){ 42 | try { 43 | final RequestBody copy = request; 44 | final Buffer buffer = new Buffer(); 45 | copy.writeTo(buffer); 46 | return buffer.readUtf8(); 47 | } catch (final IOException e) { 48 | Timber.e(e,"Did not work."); 49 | } 50 | } 51 | return null; 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/about/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.about; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.support.v4.content.ContextCompat; 6 | import android.text.Html; 7 | import android.text.method.LinkMovementMethod; 8 | import android.view.Gravity; 9 | import android.view.Menu; 10 | import android.view.MenuItem; 11 | 12 | import com.alibaba.android.arouter.facade.annotation.Route; 13 | import com.flyco.systembar.SystemBarHelper; 14 | import com.king.wanandroid.R; 15 | import com.king.wanandroid.app.base.BindingActivity; 16 | import com.king.wanandroid.app.comm.Constants; 17 | import com.king.wanandroid.databinding.AboutActivityBinding; 18 | import com.king.wanandroid.glide.GlideApp; 19 | 20 | /** 21 | * @author Jenly Jenly 22 | */ 23 | @Route(path = Constants.ROUTE_ABOUT) 24 | public class AboutActivity extends BindingActivity { 25 | 26 | 27 | @Override 28 | protected int getLayoutId() { 29 | return R.layout.about_activity; 30 | } 31 | 32 | @Override 33 | public void initData() { 34 | SystemBarHelper.immersiveStatusBar(this, 0); 35 | SystemBarHelper.setHeightAndPadding(this, mBinding.toolbar); 36 | 37 | setSupportActionBar(mBinding.toolbar); 38 | getSupportActionBar().setHomeButtonEnabled(true); 39 | mBinding.toolbar.setNavigationOnClickListener(v -> onBackPressed()); 40 | 41 | GlideApp.with(this).load(R.drawable.ic_about_image).into(mBinding.ivAbout); 42 | mBinding.collapsingToolbar.setExpandedTitleColor(ContextCompat.getColor(getContext(),R.color.white)); 43 | mBinding.collapsingToolbar.setCollapsedTitleTextColor(ContextCompat.getColor(getContext(),R.color.white)); 44 | mBinding.collapsingToolbar.setCollapsedTitleGravity(Gravity.CENTER); 45 | mBinding.tv.setText(Html.fromHtml(getString(R.string.about_desc))); 46 | mBinding.tv.setMovementMethod(LinkMovementMethod.getInstance()); 47 | mBinding.fab.setOnClickListener(v -> startWeb(Constants.AUTHOR,"https://github.com/jenly1314")); 48 | } 49 | 50 | private void clickEmail(String email){ 51 | Uri uri = Uri.parse(String.format("mailto:%s",email)); 52 | Intent intent = new Intent(Intent.ACTION_SENDTO, uri); 53 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 54 | startActivity(Intent.createChooser(intent, null)); 55 | } 56 | 57 | 58 | @Override 59 | public boolean onCreateOptionsMenu(Menu menu) { 60 | getMenuInflater().inflate(R.menu.about_menu,menu); 61 | return super.onCreateOptionsMenu(menu); 62 | } 63 | 64 | public boolean joinQQGroup(String key) { 65 | Intent intent = new Intent(); 66 | intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D" + key)); 67 | try { 68 | startActivity(intent); 69 | return true; 70 | } catch (Exception e) { 71 | // 未安装手Q或安装的版本不支持 72 | showToast(R.string.tips_join_qq_group_exception); 73 | return false; 74 | } 75 | } 76 | 77 | 78 | @Override 79 | public boolean onOptionsItemSelected(MenuItem item) { 80 | switch (item.getItemId()){ 81 | case R.id.menuGithub: 82 | startWeb(Constants.AUTHOR,"https://github.com/jenly1314"); 83 | break; 84 | case R.id.menuSource: 85 | startWeb(getString(R.string.menu_source),"https://github.com/jenly1314/WanAndroid"); 86 | break; 87 | case R.id.menuIssue: 88 | startWeb(getString(R.string.menu_issue),"https://github.com/jenly1314/WanAndroid/issues"); 89 | break; 90 | case R.id.menuEmail: 91 | clickEmail(Constants.GMAIL); 92 | break; 93 | case R.id.menuQQGroup: 94 | joinQQGroup(Constants.QQ_GROUP_KEY); 95 | break; 96 | } 97 | return super.onOptionsItemSelected(item); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/account/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.account; 2 | 3 | 4 | import android.content.Intent; 5 | import android.text.Editable; 6 | import android.text.TextUtils; 7 | import android.text.TextWatcher; 8 | 9 | import com.alibaba.android.arouter.facade.annotation.Route; 10 | import com.alibaba.android.arouter.launcher.ARouter; 11 | import com.king.wanandroid.R; 12 | import com.king.wanandroid.app.comm.Constants; 13 | import com.king.wanandroid.app.base.MVVMActivity; 14 | import com.king.wanandroid.bean.User; 15 | import com.king.wanandroid.databinding.LoginActivityBinding; 16 | 17 | /** 18 | * @author Jenly Jenly 19 | */ 20 | @Route(path = Constants.ROUTE_LOGIN) 21 | public class LoginActivity extends MVVMActivity { 22 | @Override 23 | protected LoginViewModel createViewModel() { 24 | return getViewModel(LoginViewModel.class); 25 | } 26 | 27 | @Override 28 | protected int getLayoutId() { 29 | return R.layout.login_activity; 30 | } 31 | 32 | @Override 33 | public void initData() { 34 | 35 | setToolbarTitle(R.string.login); 36 | 37 | mBinding.setViewModel(mViewModel); 38 | 39 | mBinding.etUsername.addTextChangedListener(new TextWatcher() { 40 | @Override 41 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 42 | 43 | } 44 | 45 | @Override 46 | public void onTextChanged(CharSequence s, int start, int before, int count) { 47 | mBinding.etUsername.setSelected(!TextUtils.isEmpty(s)); 48 | } 49 | 50 | @Override 51 | public void afterTextChanged(Editable s) { 52 | 53 | } 54 | }); 55 | clickRightClear(mBinding.etUsername); 56 | 57 | mBinding.btnLogin.setOnClickListener(v -> 58 | clickLogin() 59 | ); 60 | mBinding.tvRegister.setOnClickListener(v ->{ 61 | String username = mBinding.etUsername.getText().toString(); 62 | ARouter.getInstance() 63 | .build(Constants.ROUTE_REGISTER) 64 | .withString(Constants.KEY_USERNAME,username) 65 | .navigation(); 66 | }); 67 | 68 | } 69 | 70 | private void clickLogin(){ 71 | if(checkInput(mBinding.etUsername,R.string.tips_username_is_empty) && checkInput(mBinding.etPassword,R.string.tips_password_is_empty)){ 72 | String username = mBinding.etUsername.getText().toString(); 73 | String password = mBinding.etPassword.getText().toString(); 74 | mViewModel.login(username,password).observe(this, resource -> { 75 | resource.handle(new OnCallback() { 76 | @Override 77 | public void onSuccess(User data) { 78 | showToast(R.string.success_login); 79 | getApp().login(data); 80 | ARouter.getInstance() 81 | .build(Constants.ROUTE_HOME) 82 | .withBoolean(Constants.KEY_IS_LOGIN,true) 83 | .withFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_CLEAR_TASK) 84 | .navigation(getContext()); 85 | } 86 | }); 87 | }); 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/account/LoginViewModel.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.account; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.LiveData; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.king.wanandroid.app.base.DataRepository; 8 | import com.king.wanandroid.app.base.DataViewModel; 9 | import com.king.wanandroid.bean.Resource; 10 | import com.king.wanandroid.bean.User; 11 | 12 | import javax.inject.Inject; 13 | 14 | /** 15 | * @author Jenly Jenly 16 | */ 17 | public class LoginViewModel extends DataViewModel { 18 | 19 | @Inject 20 | public LoginViewModel(@NonNull Application application, DataRepository repository) { 21 | super(application, repository); 22 | } 23 | 24 | public LiveData> login(String username,String password){ 25 | return getRepository().login(username,password); 26 | } 27 | 28 | public LiveData> register(String username,String password){ 29 | return getRepository().register(username,password); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/account/RegisterActivity.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.account; 2 | 3 | 4 | import android.content.Intent; 5 | import android.text.Editable; 6 | import android.text.TextUtils; 7 | import android.text.TextWatcher; 8 | 9 | import com.alibaba.android.arouter.facade.annotation.Route; 10 | import com.alibaba.android.arouter.launcher.ARouter; 11 | import com.king.base.util.StringUtils; 12 | import com.king.wanandroid.R; 13 | import com.king.wanandroid.app.comm.Constants; 14 | import com.king.wanandroid.app.base.MVVMActivity; 15 | import com.king.wanandroid.bean.User; 16 | import com.king.wanandroid.databinding.RegisterActivityBinding; 17 | 18 | /** 19 | * @author Jenly Jenly 20 | */ 21 | @Route(path = Constants.ROUTE_REGISTER) 22 | public class RegisterActivity extends MVVMActivity { 23 | @Override 24 | protected LoginViewModel createViewModel() { 25 | return getViewModel(LoginViewModel.class); 26 | } 27 | 28 | @Override 29 | protected int getLayoutId() { 30 | return R.layout.register_activity; 31 | } 32 | 33 | @Override 34 | public void initData() { 35 | 36 | setToolbarTitle(R.string.register); 37 | 38 | String username = getIntent().getStringExtra(Constants.KEY_USERNAME); 39 | if(StringUtils.isNotBlank(username)){ 40 | mBinding.etUsername.setText(username); 41 | mBinding.etPassword.requestFocus(); 42 | } 43 | 44 | mBinding.setViewModel(mViewModel); 45 | 46 | mBinding.etUsername.addTextChangedListener(new TextWatcher() { 47 | @Override 48 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 49 | 50 | } 51 | 52 | @Override 53 | public void onTextChanged(CharSequence s, int start, int before, int count) { 54 | mBinding.etUsername.setSelected(!TextUtils.isEmpty(s)); 55 | } 56 | 57 | @Override 58 | public void afterTextChanged(Editable s) { 59 | 60 | } 61 | }); 62 | clickRightClear(mBinding.etUsername); 63 | 64 | mBinding.btnRegister.setOnClickListener(v -> 65 | clickRegister() 66 | ); 67 | 68 | } 69 | 70 | private void clickRegister(){ 71 | if(checkInput(mBinding.etUsername,R.string.tips_username_is_empty) && checkInput(mBinding.etPassword,R.string.tips_password_is_empty) && checkInput(mBinding.etRePassword,R.string.tips_re_password_is_empty)){ 72 | String password = mBinding.etPassword.getText().toString(); 73 | String rePassword = mBinding.etRePassword.getText().toString(); 74 | if(!password.equals(rePassword)){ 75 | showToast(R.string.tips_password_is_different); 76 | return; 77 | } 78 | 79 | String username = mBinding.etUsername.getText().toString(); 80 | 81 | mViewModel.register(username,password).observe(this, resource -> { 82 | resource.handle(new OnCallback() { 83 | @Override 84 | public void onSuccess(User data) { 85 | showToast(R.string.success_register); 86 | getApp().login(data); 87 | ARouter.getInstance() 88 | .build(Constants.ROUTE_HOME) 89 | .withBoolean(Constants.KEY_IS_LOGIN,true) 90 | .withFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_CLEAR_TASK) 91 | .navigation(getContext()); 92 | } 93 | }); 94 | }); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/ArticleAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | import android.databinding.DataBindingUtil; 5 | import android.databinding.ViewDataBinding; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.king.base.adapter.ViewHolderRecyclerAdapter; 11 | import com.king.base.adapter.holder.ViewHolder; 12 | import com.king.wanandroid.BR; 13 | import com.king.wanandroid.R; 14 | import com.king.wanandroid.bean.ArticleBean; 15 | import com.king.wanandroid.util.TimeUtils; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * @author Jenly Jenly 21 | */ 22 | public class ArticleAdapter extends EmptyAdapter { 23 | public ArticleAdapter(Context context, List listData) { 24 | super(context, listData); 25 | } 26 | 27 | @Override 28 | public void bindViewData(BindingHolder holder, ArticleBean data, int position) { 29 | ViewDataBinding binding = holder.getBinding(); 30 | binding.setVariable(BR.data,data); 31 | holder.setText(R.id.tvTime, TimeUtils.getUpdatedRelativeTime(getContext(),data.getPublishTime())); 32 | holder.setSelecteded(R.id.ivCollect,data.isCollect()); 33 | holder.setOnClickListener(R.id.ivCollect, v -> onItemClick(v,position)); 34 | 35 | binding.executePendingBindings(); 36 | } 37 | 38 | @Override 39 | public int getItemViewId() { 40 | return R.layout.rv_article_item; 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/BindingAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | import android.databinding.DataBindingUtil; 5 | import android.databinding.ViewDataBinding; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.king.base.adapter.HolderRecyclerAdapter; 11 | import com.king.wanandroid.R; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * @author Jenly Jenly 17 | */ 18 | public abstract class BindingAdapter extends HolderRecyclerAdapter { 19 | 20 | protected final int DEFAULT_VARIABLE_ID = 0x01; 21 | 22 | public BindingAdapter(Context context, List listData) { 23 | super(context, listData); 24 | } 25 | 26 | @Override 27 | public View buildConvertView(LayoutInflater layoutInflater, ViewGroup parent, int viewType) { 28 | ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, getConvertViewId(), parent, false); 29 | if(binding == null){ 30 | return inflate(getConvertViewId(),parent,false); 31 | } 32 | 33 | View itemView = binding.getRoot(); 34 | itemView.setTag(R.id.dataBinding,binding); 35 | return itemView; 36 | } 37 | 38 | 39 | @Override 40 | public BindingHolder buildHolder(View convertView, int viewType) { 41 | return new BindingHolder(convertView); 42 | } 43 | 44 | public abstract int getConvertViewId(); 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/BindingHolder.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.databinding.ViewDataBinding; 4 | import android.view.View; 5 | 6 | import com.king.base.adapter.holder.ViewHolder; 7 | import com.king.wanandroid.R; 8 | 9 | /** 10 | * @author Jenly Jenly 11 | */ 12 | public class BindingHolder extends ViewHolder { 13 | public BindingHolder(View convertView) { 14 | super(convertView); 15 | } 16 | 17 | 18 | public ViewDataBinding getBinding() { 19 | return (ViewDataBinding) itemView.getTag(R.id.dataBinding); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/CollectAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | import android.databinding.ViewDataBinding; 5 | 6 | import com.king.wanandroid.BR; 7 | import com.king.wanandroid.R; 8 | import com.king.wanandroid.bean.CollectBean; 9 | import com.king.wanandroid.util.TimeUtils; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author Jenly Jenly 15 | */ 16 | public class CollectAdapter extends EmptyAdapter { 17 | public CollectAdapter(Context context, List listData) { 18 | super(context, listData); 19 | } 20 | 21 | @Override 22 | public int getItemViewId() { 23 | return R.layout.rv_collect_item; 24 | } 25 | 26 | @Override 27 | public void bindViewData(BindingHolder holder, CollectBean data, int position) { 28 | ViewDataBinding binding = holder.getBinding(); 29 | binding.setVariable(BR.data,data); 30 | holder.setText(R.id.tvTime, TimeUtils.getUpdatedRelativeTime(getContext(),data.getPublishTime())); 31 | holder.setSelecteded(R.id.ivCollect,true); 32 | holder.setOnClickListener(R.id.ivCollect, v -> onItemClick(v,position)); 33 | 34 | binding.executePendingBindings(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/EmptyAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | 5 | import com.king.wanandroid.R; 6 | import com.king.wanandroid.util.RandomUtils; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * @author Jenly Jenly 13 | */ 14 | public abstract class EmptyAdapter extends BindingAdapter { 15 | 16 | private boolean isHideEmpty = true; 17 | 18 | protected static final int EMPTY_VIEW = 1; 19 | private int viewType; 20 | 21 | private String[] tips; 22 | 23 | /** 24 | * 是否随机提示 25 | */ 26 | private boolean isRandomTips = true; 27 | 28 | public EmptyAdapter(Context context, List listData) { 29 | super(context, listData); 30 | tips = context.getResources().getStringArray(R.array.tips_empty_random); 31 | } 32 | 33 | public boolean isHideEmpty(){ 34 | return isHideEmpty; 35 | } 36 | 37 | public void setHideEmpty(boolean isHideEmpty){ 38 | this.isHideEmpty = isHideEmpty; 39 | } 40 | 41 | public boolean isRandomTips(){ 42 | return isRandomTips; 43 | } 44 | 45 | public void setRandomTips(boolean isRandomTips){ 46 | this.isRandomTips = isRandomTips; 47 | } 48 | 49 | @Override 50 | public int getItemCount() { 51 | return (super.getItemCount()== 0 && !isHideEmpty) ? 1 : super.getItemCount(); 52 | } 53 | 54 | public int getCount(){ 55 | return super.getItemCount(); 56 | } 57 | 58 | @Override 59 | public int getItemViewType(int position) { 60 | if(!isHideEmpty){ 61 | if(getListData()==null || getListData().size() ==0){ 62 | viewType = EMPTY_VIEW; 63 | return EMPTY_VIEW; 64 | } 65 | } 66 | viewType = 0; 67 | return super.getItemViewType( position ); 68 | } 69 | 70 | @Override 71 | public void bindViewDatas(BindingHolder holder, T t, int position) { 72 | if(viewType == EMPTY_VIEW ){ 73 | if(isRandomTips){ 74 | holder.setText(R.id.tvEmpty,tips[RandomUtils.INSTANCE.random(0,tips.length-1)]); 75 | } 76 | return; 77 | } 78 | bindViewData(holder,t,position); 79 | } 80 | 81 | @Override 82 | public int getConvertViewId() { 83 | return viewType != EMPTY_VIEW ? getItemViewId() : R.layout.empty_layout; 84 | } 85 | 86 | public abstract int getItemViewId(); 87 | public abstract void bindViewData(BindingHolder holder, T t, int position); 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/HistoryTagAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.king.wanandroid.R; 9 | import com.king.wanandroid.app.comm.Constants; 10 | import com.king.wanandroid.bean.SearchHistory; 11 | import com.king.wanandroid.util.RandomUtils; 12 | import com.zhy.view.flowlayout.FlowLayout; 13 | import com.zhy.view.flowlayout.TagAdapter; 14 | 15 | import java.util.List; 16 | 17 | 18 | /** 19 | * @author Jenly Jenly 20 | */ 21 | public class HistoryTagAdapter extends TagAdapter { 22 | private Context mContext; 23 | private LayoutInflater mInflater; 24 | 25 | public HistoryTagAdapter(Context context, List datas) { 26 | super(datas); 27 | this.mContext = context; 28 | mInflater = LayoutInflater.from(context); 29 | } 30 | 31 | @Override 32 | public View getView(FlowLayout parent, int position, SearchHistory data) { 33 | TextView tv = (TextView) mInflater.inflate(R.layout.tree_tag_item,parent,false); 34 | tv.setText(data.getName()); 35 | tv.setTextColor(RandomUtils.INSTANCE.randomColor(Constants.COLOR_RGB_MIN,Constants.COLOR_RGB_MAX)); 36 | return tv; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/HotKeyTagAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.king.wanandroid.R; 9 | import com.king.wanandroid.app.comm.Constants; 10 | import com.king.wanandroid.bean.HotKeyBean; 11 | import com.king.wanandroid.util.RandomUtils; 12 | import com.zhy.view.flowlayout.FlowLayout; 13 | import com.zhy.view.flowlayout.TagAdapter; 14 | 15 | import java.util.List; 16 | 17 | 18 | /** 19 | * @author Jenly Jenly 20 | */ 21 | public class HotKeyTagAdapter extends TagAdapter { 22 | private Context mContext; 23 | private LayoutInflater mInflater; 24 | 25 | public HotKeyTagAdapter(Context context, List datas) { 26 | super(datas); 27 | this.mContext = context; 28 | mInflater = LayoutInflater.from(context); 29 | } 30 | 31 | @Override 32 | public View getView(FlowLayout parent, int position, HotKeyBean data) { 33 | TextView tv = (TextView) mInflater.inflate(R.layout.tree_tag_item,parent,false); 34 | tv.setText(data.getName()); 35 | tv.setTextColor(RandomUtils.INSTANCE.randomColor(Constants.COLOR_RGB_MIN,Constants.COLOR_RGB_MAX)); 36 | return tv; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/SimpleBindingAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | import android.databinding.ViewDataBinding; 5 | import android.support.annotation.LayoutRes; 6 | 7 | import com.king.wanandroid.BR; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author Jenly Jenly 13 | */ 14 | public class SimpleBindingAdapter extends EmptyAdapter { 15 | 16 | private int mLayoutId; 17 | 18 | public SimpleBindingAdapter(Context context, List listData, @LayoutRes int layoutId) { 19 | super(context, listData); 20 | this.mLayoutId = layoutId; 21 | } 22 | 23 | @Override 24 | public int getItemViewId() { 25 | return mLayoutId; 26 | } 27 | 28 | @Override 29 | public void bindViewData(BindingHolder holder, T data, int position) { 30 | ViewDataBinding binding = holder.getBinding(); 31 | binding.setVariable(BR.data,data); 32 | binding.executePendingBindings(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/TreeAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | import android.databinding.DataBindingUtil; 5 | import android.databinding.ViewDataBinding; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.king.wanandroid.R; 11 | import com.king.wanandroid.app.comm.Tree; 12 | import com.king.wanandroid.bean.TreeBean; 13 | import com.zhy.view.flowlayout.TagFlowLayout; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * @author Jenly Jenly 19 | */ 20 | public class TreeAdapter extends SimpleBindingAdapter { 21 | 22 | private OnTagClickListener mOnTagClick; 23 | 24 | private @Tree int mTree; 25 | 26 | public TreeAdapter(Context context, List listData,@Tree int tree) { 27 | super(context, listData, tree == Tree.SYSTEM ? R.layout.rv_tree_item : R.layout.rv_tree_project_item); 28 | this.mTree = tree; 29 | } 30 | 31 | @Override 32 | public void bindViewData(BindingHolder holder, TreeBean data, int position) { 33 | super.bindViewData(holder, data, position); 34 | if(mTree == Tree.SYSTEM){ 35 | TagFlowLayout flowLayout = holder.getView(R.id.flowLayout); 36 | flowLayout.setAdapter(new TreeTagAdapter(getContext(),data.getChildren())); 37 | flowLayout.setOnTagClickListener((view, pos, parent) -> { 38 | if(mOnTagClick!=null){ 39 | mOnTagClick.onTagClick(view,data, pos); 40 | } 41 | return true; 42 | }); 43 | } 44 | } 45 | 46 | public void setOnTagClickListener(OnTagClickListener onTagClick){ 47 | this.mOnTagClick = onTagClick; 48 | } 49 | 50 | public interface OnTagClickListener{ 51 | void onTagClick(View view,T t,int position); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/adapter/TreeTagAdapter.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.king.wanandroid.R; 9 | import com.king.wanandroid.app.comm.Constants; 10 | import com.king.wanandroid.bean.TreeBean; 11 | import com.king.wanandroid.util.RandomUtils; 12 | import com.zhy.view.flowlayout.FlowLayout; 13 | import com.zhy.view.flowlayout.TagAdapter; 14 | 15 | import java.util.List; 16 | 17 | 18 | /** 19 | * @author Jenly Jenly 20 | */ 21 | public class TreeTagAdapter extends TagAdapter { 22 | 23 | private Context mContext; 24 | private LayoutInflater mInflater; 25 | 26 | public TreeTagAdapter(Context context,List datas) { 27 | super(datas); 28 | this.mContext = context; 29 | mInflater = LayoutInflater.from(context); 30 | } 31 | 32 | @Override 33 | public View getView(FlowLayout parent, int position, TreeBean.ChildrenBean data) { 34 | TextView tv = (TextView) mInflater.inflate(R.layout.tree_tag_item,parent,false); 35 | tv.setText(data.getName()); 36 | tv.setTextColor(RandomUtils.INSTANCE.randomColor(Constants.COLOR_RGB_MIN,Constants.COLOR_RGB_MAX)); 37 | return tv; 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/base/BaseRepository.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.base; 2 | 3 | import com.king.wanandroid.api.ApiService; 4 | import com.king.wanandroid.bean.BaseResult; 5 | 6 | 7 | /** 8 | * @author Jenly Jenly 9 | */ 10 | public class BaseRepository { 11 | 12 | private ApiService apiService; 13 | 14 | public BaseRepository(ApiService apiService){ 15 | this.apiService = apiService; 16 | } 17 | 18 | public ApiService getApiService() { 19 | return apiService; 20 | } 21 | 22 | public boolean isSuccess(BaseResult result){ 23 | return result!=null && result.isSuccess(); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/base/BaseViewModel.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.base; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.AndroidViewModel; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.king.wanandroid.App; 8 | 9 | /** 10 | * @author Jenly Jenly 11 | */ 12 | public class BaseViewModel extends AndroidViewModel{ 13 | 14 | 15 | private T repository; 16 | 17 | public BaseViewModel(@NonNull Application application,T repository) { 18 | super(application); 19 | this.repository = repository; 20 | } 21 | 22 | public App getApp(){ 23 | return getApplication(); 24 | } 25 | 26 | public T getRepository(){ 27 | return repository; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/base/BindingActivity.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.base; 2 | 3 | import android.databinding.DataBindingUtil; 4 | import android.databinding.ViewDataBinding; 5 | import android.support.annotation.DrawableRes; 6 | import android.support.annotation.LayoutRes; 7 | import android.support.annotation.StringRes; 8 | 9 | import com.king.base.adapter.holder.ViewHolder; 10 | import com.king.wanandroid.R; 11 | 12 | /** 13 | * @author Jenly Jenly 14 | */ 15 | public abstract class BindingActivity extends BaseActivity { 16 | 17 | protected VDB mBinding; 18 | 19 | protected ViewHolder mHolder; 20 | 21 | @Override 22 | public void initView() { 23 | mBinding = DataBindingUtil.setContentView(this,getLayoutId()); 24 | mHolder = new ViewHolder(mBinding.getRoot()); 25 | } 26 | 27 | public void setToolbarTitle(@StringRes int title){ 28 | mHolder.setText(R.id.tvTitle,title); 29 | } 30 | 31 | public void setToolbarTitle(CharSequence title){ 32 | mHolder.setText(R.id.tvTitle,title); 33 | } 34 | 35 | public void setLeftImage(@DrawableRes int drawable){ 36 | mHolder.setImageResource(R.id.ivLeft,drawable); 37 | } 38 | 39 | public void setRightImage(@DrawableRes int drawable){ 40 | mHolder.setImageResource(R.id.ivRight,drawable); 41 | } 42 | 43 | protected abstract @LayoutRes int getLayoutId(); 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/base/DataViewModel.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.base; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.LiveData; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.king.wanandroid.bean.ArticleBean; 8 | import com.king.wanandroid.bean.CollectBean; 9 | import com.king.wanandroid.bean.Resource; 10 | 11 | import javax.inject.Inject; 12 | 13 | /** 14 | * @author Jenly Jenly 15 | */ 16 | public class DataViewModel extends BaseViewModel { 17 | 18 | @Inject 19 | public DataViewModel(@NonNull Application application, DataRepository repository) { 20 | super(application, repository); 21 | } 22 | 23 | public LiveData> collect(ArticleBean data){ 24 | int id = data.getId(); 25 | //收藏站内文章 26 | if(id>0){ 27 | return collect(id); 28 | } 29 | //收藏站外文章 30 | return getRepository().collect(data.getTitle(),data.getAuthor(),data.getLink()); 31 | } 32 | 33 | public LiveData> collect(int id){ 34 | return getRepository().collect(id); 35 | } 36 | 37 | public LiveData unCollect(int id){ 38 | return getRepository().unCollect(id); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/base/MVVMActivity.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.base; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.arch.lifecycle.ViewModelProviders; 6 | import android.databinding.ViewDataBinding; 7 | import android.support.annotation.NonNull; 8 | import android.support.annotation.Nullable; 9 | 10 | import javax.inject.Inject; 11 | 12 | /** 13 | * @author Jenly Jenly 14 | */ 15 | public abstract class MVVMActivity extends BindingActivity{ 16 | 17 | @Inject 18 | protected ViewModelProvider.Factory mViewModelFactory; 19 | 20 | protected VM mViewModel; 21 | 22 | @Override 23 | public void initView() { 24 | mViewModel = createViewModel(); 25 | super.initView(); 26 | } 27 | 28 | public T getViewModel(@NonNull Class modelClass){ 29 | return ViewModelProviders.of(this,mViewModelFactory).get(modelClass); 30 | } 31 | 32 | public T getViewModel(@NonNull Class modelClass,@Nullable ViewModelProvider.Factory factory){ 33 | return ViewModelProviders.of(this,factory).get(modelClass); 34 | } 35 | 36 | public ViewModelProvider.Factory getViewModelFactory(){ 37 | return mViewModelFactory; 38 | } 39 | 40 | protected abstract VM createViewModel(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/base/ViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.base; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.support.annotation.NonNull; 6 | 7 | import java.util.Map; 8 | 9 | import javax.inject.Inject; 10 | import javax.inject.Provider; 11 | import javax.inject.Singleton; 12 | 13 | 14 | /** 15 | * @author Jenly Jenly 16 | */ 17 | @Singleton 18 | public class ViewModelFactory implements ViewModelProvider.Factory { 19 | 20 | private final Map, Provider> creators; 21 | 22 | @Inject 23 | public ViewModelFactory(Map, Provider> creators){ 24 | this.creators = creators; 25 | } 26 | 27 | @NonNull 28 | @Override 29 | public T create(@NonNull Class modelClass) { 30 | Provider creator = creators.get(modelClass); 31 | if(creator == null){ 32 | for(Map.Entry, Provider> entry : creators.entrySet()){ 33 | if(modelClass.isAssignableFrom(entry.getKey())){ 34 | creator = entry.getValue(); 35 | } 36 | } 37 | } 38 | 39 | if (creator == null) { 40 | throw new IllegalArgumentException("Unknown model class " + modelClass); 41 | } 42 | 43 | try { 44 | return (T) creator.get(); 45 | } catch (Exception e) { 46 | throw new RuntimeException(e); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/collect/CollectViewModel.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.collect; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.LiveData; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.king.wanandroid.app.base.BaseViewModel; 8 | import com.king.wanandroid.app.base.DataRepository; 9 | import com.king.wanandroid.app.base.DataViewModel; 10 | import com.king.wanandroid.bean.CollectBean; 11 | import com.king.wanandroid.bean.DataBean; 12 | import com.king.wanandroid.bean.Resource; 13 | 14 | import java.util.List; 15 | 16 | import javax.inject.Inject; 17 | 18 | /** 19 | * @author Jenly Jenly 20 | */ 21 | public class CollectViewModel extends DataViewModel { 22 | 23 | @Inject 24 | public CollectViewModel(@NonNull Application application, DataRepository repository) { 25 | super(application, repository); 26 | } 27 | 28 | public LiveData>>> getCollectList(int curPage){ 29 | return getRepository().getCollectList(curPage); 30 | } 31 | 32 | public LiveData unMyCollect(int id,int originId){ 33 | return getRepository().unMyCollect(id,originId); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/comm/Constants.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.comm; 2 | 3 | /** 4 | * @author Jenly Jenly 5 | */ 6 | public final class Constants { 7 | 8 | public static final String BASE_URL = "https://www.wanandroid.com/"; 9 | 10 | 11 | 12 | //---------------------------------------------- 13 | 14 | public static final String KEY_URL = "key_url"; 15 | 16 | public static final String KEY_TITLE = "key_title"; 17 | 18 | public static final String KEY_AUTHOR = "key_author"; 19 | 20 | public static final String KEY_ID = "key_id"; 21 | 22 | public static final String KEY_KEY = "key_key"; 23 | 24 | public static final String KEY_IS_COLLECT = "key_is_collect"; 25 | 26 | public static final String KEY_IS_LOGIN = "key_is_login"; 27 | 28 | public static final String KEY_TREE = "key_tree"; 29 | 30 | 31 | public static final String KEY_USER = "pref_user"; 32 | public static final String KEY_USER_ID = "key_user_id"; 33 | public static final String KEY_USERNAME = "key_username"; 34 | public static final String KEY_PASSWORD = "key_password"; 35 | public static final String KEY_EMAIL = "key_email"; 36 | public static final String KEY_ICON = "key_icon"; 37 | public static final String KEY_TYPE = "key_type"; 38 | 39 | public static final String KEY_CHECK_TIME = "key_check_time"; 40 | 41 | //---------------------------------------------- 42 | 43 | public static final String ROUTE_SPLASH = "/app/splash"; 44 | 45 | public static final String ROUTE_HOME = "/app/home"; 46 | 47 | public static final String ROUTE_LOGIN = "/app/login"; 48 | 49 | public static final String ROUTE_REGISTER = "/app/register"; 50 | 51 | public static final String ROUTE_WEB = "/app/web"; 52 | 53 | public static final String ROUTE_COLLECT = "/app/collect"; 54 | 55 | public static final String ROUTE_TREE = "/app/tree"; 56 | 57 | public static final String ROUTE_TREE_CHILDREN = "/app/treeChildren"; 58 | 59 | public static final String ROUTE_SEARCH = "/app/search"; 60 | 61 | public static final String ROUTE_NAVI = "/app/navi"; 62 | 63 | public static final String ROUTE_ABOUT = "/app/about"; 64 | 65 | //---------------------------------------------- 66 | 67 | public static final int RECODE_ARTICLE = 0x01; 68 | 69 | //---------------------------------------------- 70 | 71 | public static final String AUTHOR = "Jenly"; 72 | public static final String GMAIL = "jenly1314@gmail.com"; 73 | public static final String QQ_GROUP_KEY = "5D3GQFxzrzGft-E7FyRujPoCYBOcczbQ"; 74 | 75 | //---------------------------------------------- 76 | 77 | 78 | public static final String DATABASE_NAME = "wan_android.db"; 79 | 80 | //---------------------------------------------- 81 | 82 | public static final String BUGLY_APP_ID = "3d5fc11500"; 83 | 84 | //---------------------------------------------- 85 | 86 | public static final int COLOR_RGB_MIN = 20; 87 | public static final int COLOR_RGB_MAX = 230; 88 | 89 | //---------------------------------------------- 90 | 91 | public static final int MAX_COUNT = 30; 92 | 93 | 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/comm/Status.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.comm; 2 | 3 | import android.support.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | /** 9 | * @author Jenly Jenly 10 | */ 11 | @IntDef({Status.LOADING,Status.SUCCESS,Status.FAILURE,Status.ERROR}) 12 | @Retention(RetentionPolicy.SOURCE) 13 | public @interface Status { 14 | int LOADING = 0; 15 | int SUCCESS = 1; 16 | int FAILURE = 2; 17 | int ERROR = 3; 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/comm/Tree.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.comm; 2 | 3 | import android.support.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | 9 | /** 10 | * @author Jenly Jenly 11 | */ 12 | @IntDef({Tree.SYSTEM,Tree.PROJECT,Tree.SEARCH}) 13 | @Retention(RetentionPolicy.SOURCE) 14 | public @interface Tree { 15 | int SYSTEM = 0; 16 | int PROJECT = 1; 17 | int SEARCH = 2; 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/home/HomeViewModel.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.home; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.LiveData; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.king.wanandroid.app.base.DataRepository; 8 | import com.king.wanandroid.app.base.DataViewModel; 9 | import com.king.wanandroid.bean.ArticleBean; 10 | import com.king.wanandroid.bean.BannerBean; 11 | import com.king.wanandroid.bean.DataBean; 12 | import com.king.wanandroid.bean.Resource; 13 | import com.king.wanandroid.bean.VersionBean; 14 | 15 | import java.util.List; 16 | 17 | import javax.inject.Inject; 18 | 19 | /** 20 | * @author Jenly Jenly 21 | */ 22 | public class HomeViewModel extends DataViewModel { 23 | 24 | @Inject 25 | public HomeViewModel(@NonNull Application application,DataRepository repository) { 26 | super( application,repository); 27 | } 28 | 29 | public LiveData>>> getArticlesList(int curPage){ 30 | return getRepository().getArticlesList(curPage); 31 | } 32 | 33 | public LiveData>> getBanner(){ 34 | return getRepository().getBanner(); 35 | } 36 | 37 | public LiveData> checkVersion(){ 38 | return getRepository().checkVersion(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/navi/NaviViewModel.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.navi; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.LiveData; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.king.wanandroid.app.base.DataRepository; 8 | import com.king.wanandroid.app.base.DataViewModel; 9 | import com.king.wanandroid.bean.NaviBean; 10 | import com.king.wanandroid.bean.Resource; 11 | 12 | import java.util.List; 13 | 14 | import javax.inject.Inject; 15 | 16 | /** 17 | * @author Jenly Jenly 18 | */ 19 | public class NaviViewModel extends DataViewModel { 20 | 21 | @Inject 22 | public NaviViewModel(@NonNull Application application, DataRepository repository) { 23 | super(application, repository); 24 | } 25 | 26 | /** 27 | * 获取导航 28 | * @return 29 | */ 30 | public LiveData>> getNavi(){ 31 | return getRepository().getNavi(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/search/SearchViewModel.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.search; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.LiveData; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.king.wanandroid.app.base.DataRepository; 8 | import com.king.wanandroid.app.base.DataViewModel; 9 | import com.king.wanandroid.bean.HotKeyBean; 10 | import com.king.wanandroid.bean.Resource; 11 | import com.king.wanandroid.bean.SearchHistory; 12 | 13 | import java.util.List; 14 | 15 | import javax.inject.Inject; 16 | 17 | /** 18 | * @author Jenly Jenly 19 | */ 20 | public class SearchViewModel extends DataViewModel { 21 | @Inject 22 | public SearchViewModel(@NonNull Application application, DataRepository repository) { 23 | super(application, repository); 24 | } 25 | 26 | public LiveData>> getHotkey(){ 27 | return getRepository().getHotkey(); 28 | } 29 | 30 | public LiveData> getSearchHistory(int count){ 31 | return getRepository().getSearchHistory(count); 32 | } 33 | 34 | /** 35 | * 添加历史 36 | * @param key 37 | */ 38 | public void addHistory(String key){ 39 | getRepository().addHistory(key); 40 | } 41 | 42 | /** 43 | * 删除历史 44 | */ 45 | public void deleteAllHistory(){ 46 | getRepository().deleteAllHistory(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/splash/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.splash; 2 | 3 | import android.content.Intent; 4 | import android.support.v4.app.ActivityOptionsCompat; 5 | import android.view.View; 6 | import android.view.animation.Animation; 7 | import android.view.animation.AnimationUtils; 8 | 9 | import com.alibaba.android.arouter.facade.annotation.Route; 10 | import com.alibaba.android.arouter.launcher.ARouter; 11 | import com.king.wanandroid.R; 12 | import com.king.wanandroid.app.base.BindingActivity; 13 | import com.king.wanandroid.app.comm.Constants; 14 | import com.king.wanandroid.databinding.SplashActivityBinding; 15 | 16 | /** 17 | * @author Jenly Jenly 18 | */ 19 | @Route(path = Constants.ROUTE_SPLASH) 20 | public class SplashActivity extends BindingActivity{ 21 | @Override 22 | protected int getLayoutId() { 23 | return R.layout.splash_activity; 24 | } 25 | 26 | @Override 27 | public void initData() { 28 | startAnimation(mBinding.getRoot()); 29 | } 30 | 31 | protected void startAnimation(View view){ 32 | Animation anim = AnimationUtils.loadAnimation(getContext(),R.anim.splash); 33 | anim.setAnimationListener(new Animation.AnimationListener() { 34 | @Override 35 | public void onAnimationStart(Animation animation) { 36 | mBinding.tvName.start(); 37 | } 38 | 39 | @Override 40 | public void onAnimationEnd(Animation animation) { 41 | 42 | ActivityOptionsCompat options = ActivityOptionsCompat.makeCustomAnimation(getContext(),R.anim.in,R.anim.out); 43 | ARouter.getInstance() 44 | .build(Constants.ROUTE_HOME) 45 | .withFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_CLEAR_TASK) 46 | .withOptionsCompat(options) 47 | .navigation(getContext()); 48 | finish(); 49 | 50 | } 51 | 52 | @Override 53 | public void onAnimationRepeat(Animation animation) { 54 | 55 | } 56 | }); 57 | view.startAnimation(anim); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/tree/TreeActivity.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.tree; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.arch.lifecycle.Observer; 5 | import android.content.Intent; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.view.View; 9 | 10 | import com.alibaba.android.arouter.facade.annotation.Route; 11 | import com.alibaba.android.arouter.launcher.ARouter; 12 | import com.king.base.adapter.divider.DividerItemDecoration; 13 | import com.king.wanandroid.R; 14 | import com.king.wanandroid.app.adapter.TreeAdapter; 15 | import com.king.wanandroid.app.base.MVVMActivity; 16 | import com.king.wanandroid.app.comm.Constants; 17 | import com.king.wanandroid.app.comm.Tree; 18 | import com.king.wanandroid.bean.Resource; 19 | import com.king.wanandroid.bean.TreeBean; 20 | import com.king.wanandroid.databinding.TreeActivityBinding; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | * @author Jenly Jenly 27 | */ 28 | @Route(path = Constants.ROUTE_TREE) 29 | public class TreeActivity extends MVVMActivity { 30 | 31 | private List listData; 32 | 33 | private TreeAdapter mAdapter; 34 | 35 | private @Tree int mTree; 36 | 37 | @Override 38 | protected TreeViewModel createViewModel() { 39 | return getViewModel(TreeViewModel.class); 40 | } 41 | 42 | @Override 43 | protected int getLayoutId() { 44 | return R.layout.tree_activity; 45 | } 46 | 47 | @SuppressLint("ResourceAsColor") 48 | @Override 49 | public void initData() { 50 | 51 | Intent intent = getIntent(); 52 | mTree = intent.getIntExtra(Constants.KEY_TREE,Tree.SYSTEM); 53 | 54 | setToolbarTitle(intent.getStringExtra(Constants.KEY_TITLE)); 55 | 56 | setRightImage(R.drawable.btn_search_selector); 57 | mBinding.setViewModel(mViewModel); 58 | 59 | listData = new ArrayList<>(); 60 | mAdapter = new TreeAdapter(getContext(),listData,mTree); 61 | mAdapter.setOnItemClickListener((v, position) -> { 62 | if(mAdapter.getCount()> position){ 63 | TreeBean bean = listData.get(position); 64 | startTreeChildren(mTree,bean.getName(),bean.getId()); 65 | } 66 | }); 67 | mAdapter.setOnTagClickListener((view, data, position) -> { 68 | TreeBean.ChildrenBean bean = data.getChildren().get(position); 69 | startTreeChildren(mTree,bean.getName(),bean.getId()); 70 | }); 71 | 72 | mBinding.rv.setLayoutManager(new LinearLayoutManager(getContext())); 73 | mBinding.rv.addItemDecoration(new DividerItemDecoration(getContext(),DividerItemDecoration.VERTICAL,R.drawable.line_drawable_8)); 74 | mBinding.rv.setNestedScrollingEnabled(false); 75 | mBinding.rv.setAdapter(mAdapter); 76 | 77 | mBinding.srl.setColorSchemeResources(R.color.colorPrimary); 78 | mBinding.srl.setOnRefreshListener(() -> 79 | getTree() 80 | ); 81 | mBinding.srl.setRefreshing(true); 82 | getTree(); 83 | } 84 | 85 | 86 | private void getTree(){ 87 | mViewModel.getTree(mTree).observe(this,mListObserver); 88 | } 89 | 90 | private void refreshListView(List data){ 91 | listData.clear(); 92 | listData.addAll(data); 93 | } 94 | 95 | private Observer mListObserver = new Observer>>() { 96 | @Override 97 | public void onChanged(@Nullable Resource> resource) { 98 | resource.handle(new OnCallback>() { 99 | @Override 100 | public void onSuccess(List data) { 101 | refreshListView(data); 102 | } 103 | 104 | @Override 105 | public void onCompleted() { 106 | super.onCompleted(); 107 | mAdapter.setHideEmpty(false); 108 | mAdapter.notifyDataSetChanged(); 109 | mBinding.srl.setRefreshing(false); 110 | 111 | } 112 | }); 113 | } 114 | }; 115 | 116 | private void clickSearch(){ 117 | ARouter.getInstance() 118 | .build(Constants.ROUTE_SEARCH) 119 | .navigation(getContext()); 120 | } 121 | 122 | @Override 123 | public void OnClick(View v) { 124 | super.OnClick(v); 125 | switch (v.getId()){ 126 | case R.id.ivRight: 127 | clickSearch(); 128 | break; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/app/tree/TreeViewModel.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.app.tree; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.LiveData; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.king.wanandroid.app.base.DataRepository; 8 | import com.king.wanandroid.app.base.DataViewModel; 9 | import com.king.wanandroid.app.comm.Tree; 10 | import com.king.wanandroid.bean.ArticleBean; 11 | import com.king.wanandroid.bean.DataBean; 12 | import com.king.wanandroid.bean.Resource; 13 | import com.king.wanandroid.bean.TreeBean; 14 | 15 | import java.util.List; 16 | 17 | import javax.inject.Inject; 18 | 19 | /** 20 | * @author Jenly Jenly 21 | */ 22 | public class TreeViewModel extends DataViewModel { 23 | @Inject 24 | public TreeViewModel(@NonNull Application application, DataRepository repository) { 25 | super(application, repository); 26 | } 27 | 28 | /** 29 | * 获取一级树 30 | * @param tree 31 | * @return 32 | */ 33 | public LiveData>> getTree(@Tree int tree) { 34 | if(tree == Tree.PROJECT){ 35 | return getRepository().getProject(); 36 | } 37 | 38 | return getRepository().getSystem(); 39 | } 40 | 41 | public LiveData>>> getTreeList(@Tree int tree,int curPage,int id,String key){ 42 | if(tree == Tree.PROJECT){//项目列表 43 | return getRepository().getProjectList(curPage,id); 44 | } 45 | if(tree == Tree.SEARCH){//关键字搜索 46 | return getRepository().getArticlesList(curPage,key); 47 | } 48 | 49 | return getRepository().getArticlesList(curPage,id); 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/BannerBean.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | /** 4 | * @author Jenly Jenly 5 | */ 6 | public class BannerBean { 7 | 8 | /** 9 | * desc : 10 | * id : 6 11 | * imagePath : http://www.wanandroid.com/blogimgs/62c1bd68-b5f3-4a3c-a649-7ca8c7dfabe6.png 12 | * isVisible : 1 13 | * order : 1 14 | * title : 我们新增了一个常用导航Tab~ 15 | * type : 0 16 | * url : http://www.wanandroid.com/navi 17 | */ 18 | 19 | private String desc; 20 | private int id; 21 | private String imagePath; 22 | private int isVisible; 23 | private int order; 24 | private String title; 25 | private int type; 26 | private String url; 27 | 28 | public String getDesc() { 29 | return desc; 30 | } 31 | 32 | public void setDesc(String desc) { 33 | this.desc = desc; 34 | } 35 | 36 | public int getId() { 37 | return id; 38 | } 39 | 40 | public void setId(int id) { 41 | this.id = id; 42 | } 43 | 44 | public String getImagePath() { 45 | return imagePath; 46 | } 47 | 48 | public void setImagePath(String imagePath) { 49 | this.imagePath = imagePath; 50 | } 51 | 52 | public int getIsVisible() { 53 | return isVisible; 54 | } 55 | 56 | public void setIsVisible(int isVisible) { 57 | this.isVisible = isVisible; 58 | } 59 | 60 | public int getOrder() { 61 | return order; 62 | } 63 | 64 | public void setOrder(int order) { 65 | this.order = order; 66 | } 67 | 68 | public String getTitle() { 69 | return title; 70 | } 71 | 72 | public void setTitle(String title) { 73 | this.title = title; 74 | } 75 | 76 | public int getType() { 77 | return type; 78 | } 79 | 80 | public void setType(int type) { 81 | this.type = type; 82 | } 83 | 84 | public String getUrl() { 85 | return url; 86 | } 87 | 88 | public void setUrl(String url) { 89 | this.url = url; 90 | } 91 | 92 | @Override 93 | public String toString() { 94 | return "BannerBean{" + 95 | "desc='" + desc + '\'' + 96 | ", id=" + id + 97 | ", imagePath='" + imagePath + '\'' + 98 | ", isVisible=" + isVisible + 99 | ", order=" + order + 100 | ", title='" + title + '\'' + 101 | ", type=" + type + 102 | ", url='" + url + '\'' + 103 | '}'; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/BaseResult.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * @author Jenly Jenly 7 | */ 8 | public class BaseResult { 9 | 10 | public static final int RESULT_SUCCESS = 0; 11 | 12 | @SerializedName("errorCode") 13 | private int resultCode; 14 | 15 | private String errorMsg; 16 | 17 | private T data; 18 | 19 | public int getResultCode() { 20 | return resultCode; 21 | } 22 | 23 | public void setResultCode(int resultCode) { 24 | this.resultCode = resultCode; 25 | } 26 | 27 | public String getErrorMsg() { 28 | return errorMsg; 29 | } 30 | 31 | public void setErrorMsg(String errorMsg) { 32 | this.errorMsg = errorMsg; 33 | } 34 | 35 | public T getData() { 36 | return data; 37 | } 38 | 39 | public void setData(T data) { 40 | this.data = data; 41 | } 42 | 43 | public boolean isSuccess(){ 44 | return RESULT_SUCCESS == resultCode; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "BaseResult{" + 50 | "resultCode=" + resultCode + 51 | ", errorMsg='" + errorMsg + '\'' + 52 | ", data=" + data + 53 | '}'; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/CollectBean.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | /** 4 | * @author Jenly Jenly 5 | */ 6 | public class CollectBean { 7 | 8 | /** 9 | * author : 小编 10 | * chapterId : 352 11 | * chapterName : 资讯 12 | * courseId : 13 13 | * desc : 14 | * envelopePic : 15 | * id : 15915 16 | * link : http://www.wanandroid.com/blog/show/2 17 | * niceDate : 刚刚 18 | * origin : 19 | * originId : 2864 20 | * publishTime : 1530849681000 21 | * title : 玩Android API 22 | * userId : 3273 23 | * visible : 0 24 | * zan : 0 25 | */ 26 | 27 | private String author; 28 | private int chapterId; 29 | private String chapterName; 30 | private int courseId; 31 | private String desc; 32 | private String envelopePic; 33 | private int id; 34 | private String link; 35 | private String niceDate; 36 | private String origin; 37 | private int originId = -1; 38 | private long publishTime; 39 | private String title; 40 | private int userId; 41 | private int visible; 42 | private int zan; 43 | 44 | public String getAuthor() { 45 | return author; 46 | } 47 | 48 | public void setAuthor(String author) { 49 | this.author = author; 50 | } 51 | 52 | public int getChapterId() { 53 | return chapterId; 54 | } 55 | 56 | public void setChapterId(int chapterId) { 57 | this.chapterId = chapterId; 58 | } 59 | 60 | public String getChapterName() { 61 | return chapterName; 62 | } 63 | 64 | public void setChapterName(String chapterName) { 65 | this.chapterName = chapterName; 66 | } 67 | 68 | public int getCourseId() { 69 | return courseId; 70 | } 71 | 72 | public void setCourseId(int courseId) { 73 | this.courseId = courseId; 74 | } 75 | 76 | public String getDesc() { 77 | return desc; 78 | } 79 | 80 | public void setDesc(String desc) { 81 | this.desc = desc; 82 | } 83 | 84 | public String getEnvelopePic() { 85 | return envelopePic; 86 | } 87 | 88 | public void setEnvelopePic(String envelopePic) { 89 | this.envelopePic = envelopePic; 90 | } 91 | 92 | public int getId() { 93 | return id; 94 | } 95 | 96 | public void setId(int id) { 97 | this.id = id; 98 | } 99 | 100 | public String getLink() { 101 | return link; 102 | } 103 | 104 | public void setLink(String link) { 105 | this.link = link; 106 | } 107 | 108 | public String getNiceDate() { 109 | return niceDate; 110 | } 111 | 112 | public void setNiceDate(String niceDate) { 113 | this.niceDate = niceDate; 114 | } 115 | 116 | public String getOrigin() { 117 | return origin; 118 | } 119 | 120 | public void setOrigin(String origin) { 121 | this.origin = origin; 122 | } 123 | 124 | public int getOriginId() { 125 | return originId; 126 | } 127 | 128 | public void setOriginId(int originId) { 129 | this.originId = originId; 130 | } 131 | 132 | public long getPublishTime() { 133 | return publishTime; 134 | } 135 | 136 | public void setPublishTime(long publishTime) { 137 | this.publishTime = publishTime; 138 | } 139 | 140 | public String getTitle() { 141 | return title; 142 | } 143 | 144 | public void setTitle(String title) { 145 | this.title = title; 146 | } 147 | 148 | public int getUserId() { 149 | return userId; 150 | } 151 | 152 | public void setUserId(int userId) { 153 | this.userId = userId; 154 | } 155 | 156 | public int getVisible() { 157 | return visible; 158 | } 159 | 160 | public void setVisible(int visible) { 161 | this.visible = visible; 162 | } 163 | 164 | public int getZan() { 165 | return zan; 166 | } 167 | 168 | public void setZan(int zan) { 169 | this.zan = zan; 170 | } 171 | 172 | @Override 173 | public String toString() { 174 | return "CollectBean{" + 175 | "author='" + author + '\'' + 176 | ", chapterId=" + chapterId + 177 | ", chapterName='" + chapterName + '\'' + 178 | ", courseId=" + courseId + 179 | ", desc='" + desc + '\'' + 180 | ", envelopePic='" + envelopePic + '\'' + 181 | ", id=" + id + 182 | ", link='" + link + '\'' + 183 | ", niceDate='" + niceDate + '\'' + 184 | ", origin='" + origin + '\'' + 185 | ", originId=" + originId + 186 | ", publishTime=" + publishTime + 187 | ", title='" + title + '\'' + 188 | ", userId=" + userId + 189 | ", visible=" + visible + 190 | ", zan=" + zan + 191 | '}'; 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/DataBean.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | /** 4 | * @author Jenly Jenly 5 | */ 6 | public class DataBean { 7 | private int curPage; 8 | 9 | private int offset; 10 | 11 | private int pageCount; 12 | 13 | private int size; 14 | 15 | private int total; 16 | 17 | private T datas; 18 | 19 | public int getCurPage() { 20 | return curPage; 21 | } 22 | 23 | public void setCurPage(int curPage) { 24 | this.curPage = curPage; 25 | } 26 | 27 | public int getOffset() { 28 | return offset; 29 | } 30 | 31 | public void setOffset(int offset) { 32 | this.offset = offset; 33 | } 34 | 35 | public int getPageCount() { 36 | return pageCount; 37 | } 38 | 39 | public void setPageCount(int pageCount) { 40 | this.pageCount = pageCount; 41 | } 42 | 43 | public int getSize() { 44 | return size; 45 | } 46 | 47 | public void setSize(int size) { 48 | this.size = size; 49 | } 50 | 51 | public int getTotal() { 52 | return total; 53 | } 54 | 55 | public void setTotal(int total) { 56 | this.total = total; 57 | } 58 | 59 | public T getDatas() { 60 | return datas; 61 | } 62 | 63 | public void setDatas(T datas) { 64 | this.datas = datas; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return "ListBean{" + 70 | "curPage=" + curPage + 71 | ", offset=" + offset + 72 | ", pageCount=" + pageCount + 73 | ", size=" + size + 74 | ", total=" + total + 75 | ", datas=" + datas + 76 | '}'; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/HotKeyBean.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | /** 4 | * @author Jenly Jenly 5 | */ 6 | public class HotKeyBean { 7 | /** 8 | * id : 6 9 | * link : 10 | * name : 面试 11 | * order : 1 12 | * visible : 1 13 | */ 14 | 15 | private int id; 16 | private String link; 17 | private String name; 18 | private int order; 19 | private int visible; 20 | 21 | public int getId() { 22 | return id; 23 | } 24 | 25 | public void setId(int id) { 26 | this.id = id; 27 | } 28 | 29 | public String getLink() { 30 | return link; 31 | } 32 | 33 | public void setLink(String link) { 34 | this.link = link; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public int getOrder() { 46 | return order; 47 | } 48 | 49 | public void setOrder(int order) { 50 | this.order = order; 51 | } 52 | 53 | public int getVisible() { 54 | return visible; 55 | } 56 | 57 | public void setVisible(int visible) { 58 | this.visible = visible; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "HotKeyBean{" + 64 | "id=" + id + 65 | ", link='" + link + '\'' + 66 | ", name='" + name + '\'' + 67 | ", order=" + order + 68 | ", visible=" + visible + 69 | '}'; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/NaviBean.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | 4 | import java.util.List; 5 | 6 | /** 7 | * @author Jenly Jenly 8 | */ 9 | public class NaviBean { 10 | 11 | private int cid; 12 | 13 | private String name; 14 | 15 | private List articles; 16 | 17 | public int getCid() { 18 | return cid; 19 | } 20 | 21 | public void setCid(int cid) { 22 | this.cid = cid; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public List getArticles() { 34 | return articles; 35 | } 36 | 37 | public void setArticles(List articles) { 38 | this.articles = articles; 39 | } 40 | 41 | @Override 42 | public boolean equals(Object o) { 43 | if (this == o) return true; 44 | if (o == null || getClass() != o.getClass()) return false; 45 | 46 | NaviBean naviBean = (NaviBean) o; 47 | 48 | if (cid != naviBean.cid) return false; 49 | return name != null ? name.equals(naviBean.name) : naviBean.name == null; 50 | } 51 | 52 | @Override 53 | public int hashCode() { 54 | int result = cid; 55 | result = 31 * result + (name != null ? name.hashCode() : 0); 56 | return result; 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return "NaviBean{" + 62 | "cid=" + cid + 63 | ", name='" + name + '\'' + 64 | ", articles=" + articles + 65 | '}'; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/Resource.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.king.wanandroid.app.comm.Status; 7 | 8 | /** 9 | * @author Jenly Jenly 10 | */ 11 | public class Resource { 12 | 13 | @Status 14 | public int status; 15 | 16 | @Nullable 17 | public String message; 18 | 19 | @Nullable 20 | public T data; 21 | 22 | public Throwable error; 23 | 24 | public Resource(@Status int status, @Nullable T data, @Nullable String message) { 25 | this.status = status; 26 | this.data = data; 27 | this.message = message; 28 | } 29 | 30 | public Resource(@Status int status,Throwable t) { 31 | this.status = status; 32 | this.error = t; 33 | } 34 | 35 | public static Resource loading() { 36 | return new Resource<>(Status.LOADING, null, null); 37 | } 38 | 39 | public static Resource loading(@Nullable T data) { 40 | return new Resource<>(Status.LOADING, data, null); 41 | } 42 | 43 | public static Resource success(@Nullable T data) { 44 | return new Resource<>(Status.SUCCESS, data, null); 45 | } 46 | 47 | public static Resource response(@Nullable BaseResult data) { 48 | if(data!=null){ 49 | if(data.isSuccess()){ 50 | return new Resource<>(Status.SUCCESS, data.getData(), null); 51 | } 52 | return new Resource<>(Status.FAILURE,null,data.getErrorMsg()); 53 | } 54 | return new Resource<>(Status.ERROR,null,null); 55 | } 56 | 57 | public static Resource failure(String msg) { 58 | return new Resource<>(Status.FAILURE, null, msg); 59 | } 60 | 61 | public static Resource error(Throwable t) { 62 | return new Resource<>(Status.ERROR,t); 63 | } 64 | 65 | public void handle(@NonNull OnHandleCallback callback){ 66 | switch (status){ 67 | case Status.LOADING: 68 | callback.onLoading(); 69 | break; 70 | case Status.SUCCESS: 71 | callback.onSuccess(data); 72 | break; 73 | case Status.FAILURE: 74 | callback.onFailure(message); 75 | break; 76 | case Status.ERROR: 77 | callback.onError(error); 78 | 79 | break; 80 | } 81 | 82 | if(status!= Status.LOADING){ 83 | callback.onCompleted(); 84 | } 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return "Resource{" + 90 | "status=" + status + 91 | ", message='" + message + '\'' + 92 | ", data=" + data + 93 | '}'; 94 | } 95 | 96 | 97 | public interface OnHandleCallback{ 98 | void onLoading(); 99 | void onSuccess(T data); 100 | void onFailure(String msg); 101 | void onError(Throwable error); 102 | void onCompleted(); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/Result.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | /** 4 | * @author Jenly Jenly 5 | */ 6 | public class Result extends BaseResult { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/SearchHistory.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | import android.arch.persistence.room.Entity; 4 | import android.arch.persistence.room.Index; 5 | import android.arch.persistence.room.PrimaryKey; 6 | 7 | /** 8 | * @author Jenly Jenly 9 | */ 10 | @Entity(indices = {@Index(value = "name", unique = true)}) 11 | public class SearchHistory { 12 | 13 | @PrimaryKey(autoGenerate = true) 14 | private long id; 15 | 16 | private String name; 17 | 18 | private long time; 19 | 20 | public SearchHistory(String name) { 21 | this.name = name; 22 | time = System.currentTimeMillis(); 23 | } 24 | 25 | public long getId() { 26 | return id; 27 | } 28 | 29 | public void setId(long id) { 30 | this.id = id; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public void setName(String name) { 38 | this.name = name; 39 | } 40 | 41 | public long getTime() { 42 | return time; 43 | } 44 | 45 | public void setTime(long time) { 46 | this.time = time; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "SearchHistory{" + 52 | "id=" + id + 53 | ", name='" + name + '\'' + 54 | ", time=" + time + 55 | '}'; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/TreeBean.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author Jenly Jenly 7 | */ 8 | public class TreeBean { 9 | /** 10 | * children : [{"children":[],"courseId":13,"id":60,"name":"Android Studio相关","order":1000,"parentChapterId":150,"visible":1},{"children":[],"courseId":13,"id":169,"name":"gradle","order":1001,"parentChapterId":150,"visible":1},{"children":[],"courseId":13,"id":269,"name":"官方发布","order":1002,"parentChapterId":150,"visible":1}] 11 | * courseId : 13 12 | * id : 150 13 | * name : 开发环境 14 | * order : 1 15 | * parentChapterId : 0 16 | * visible : 1 17 | */ 18 | 19 | private int courseId; 20 | private int id; 21 | private String name; 22 | private int order; 23 | private int parentChapterId; 24 | private int visible; 25 | private List children; 26 | 27 | public int getCourseId() { 28 | return courseId; 29 | } 30 | 31 | public void setCourseId(int courseId) { 32 | this.courseId = courseId; 33 | } 34 | 35 | public int getId() { 36 | return id; 37 | } 38 | 39 | public void setId(int id) { 40 | this.id = id; 41 | } 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public void setName(String name) { 48 | this.name = name; 49 | } 50 | 51 | public int getOrder() { 52 | return order; 53 | } 54 | 55 | public void setOrder(int order) { 56 | this.order = order; 57 | } 58 | 59 | public int getParentChapterId() { 60 | return parentChapterId; 61 | } 62 | 63 | public void setParentChapterId(int parentChapterId) { 64 | this.parentChapterId = parentChapterId; 65 | } 66 | 67 | public int getVisible() { 68 | return visible; 69 | } 70 | 71 | public void setVisible(int visible) { 72 | this.visible = visible; 73 | } 74 | 75 | public List getChildren() { 76 | return children; 77 | } 78 | 79 | public void setChildren(List children) { 80 | this.children = children; 81 | } 82 | 83 | public static class ChildrenBean { 84 | /** 85 | * children : [] 86 | * courseId : 13 87 | * id : 60 88 | * name : Android Studio相关 89 | * order : 1000 90 | * parentChapterId : 150 91 | * visible : 1 92 | */ 93 | 94 | private int courseId; 95 | private int id; 96 | private String name; 97 | private int order; 98 | private int parentChapterId; 99 | private int visible; 100 | private List children; 101 | 102 | public int getCourseId() { 103 | return courseId; 104 | } 105 | 106 | public void setCourseId(int courseId) { 107 | this.courseId = courseId; 108 | } 109 | 110 | public int getId() { 111 | return id; 112 | } 113 | 114 | public void setId(int id) { 115 | this.id = id; 116 | } 117 | 118 | public String getName() { 119 | return name; 120 | } 121 | 122 | public void setName(String name) { 123 | this.name = name; 124 | } 125 | 126 | public int getOrder() { 127 | return order; 128 | } 129 | 130 | public void setOrder(int order) { 131 | this.order = order; 132 | } 133 | 134 | public int getParentChapterId() { 135 | return parentChapterId; 136 | } 137 | 138 | public void setParentChapterId(int parentChapterId) { 139 | this.parentChapterId = parentChapterId; 140 | } 141 | 142 | public int getVisible() { 143 | return visible; 144 | } 145 | 146 | public void setVisible(int visible) { 147 | this.visible = visible; 148 | } 149 | 150 | public List getChildren() { 151 | return children; 152 | } 153 | 154 | public void setChildren(List children) { 155 | this.children = children; 156 | } 157 | 158 | @Override 159 | public String toString() { 160 | return "ChildrenBean{" + 161 | "courseId=" + courseId + 162 | ", id=" + id + 163 | ", name='" + name + '\'' + 164 | ", order=" + order + 165 | ", parentChapterId=" + parentChapterId + 166 | ", visible=" + visible + 167 | ", children=" + children + 168 | '}'; 169 | } 170 | } 171 | 172 | @Override 173 | public String toString() { 174 | return "TreeBean{" + 175 | "courseId=" + courseId + 176 | ", id=" + id + 177 | ", name='" + name + '\'' + 178 | ", order=" + order + 179 | ", parentChapterId=" + parentChapterId + 180 | ", visible=" + visible + 181 | ", children=" + children + 182 | '}'; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/User.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | /** 7 | * @author Jenly Jenly 8 | */ 9 | public class User implements Serializable{ 10 | 11 | 12 | private String email; 13 | private String icon; 14 | private int id; 15 | private String password; 16 | private int type; 17 | private String username; 18 | private List collectIds; 19 | 20 | public String getEmail() { 21 | return email; 22 | } 23 | 24 | public void setEmail(String email) { 25 | this.email = email; 26 | } 27 | 28 | public String getIcon() { 29 | return icon; 30 | } 31 | 32 | public void setIcon(String icon) { 33 | this.icon = icon; 34 | } 35 | 36 | public int getId() { 37 | return id; 38 | } 39 | 40 | public void setId(int id) { 41 | this.id = id; 42 | } 43 | 44 | public String getPassword() { 45 | return password; 46 | } 47 | 48 | public void setPassword(String password) { 49 | this.password = password; 50 | } 51 | 52 | public int getType() { 53 | return type; 54 | } 55 | 56 | public void setType(int type) { 57 | this.type = type; 58 | } 59 | 60 | public String getUsername() { 61 | return username; 62 | } 63 | 64 | public void setUsername(String username) { 65 | this.username = username; 66 | } 67 | 68 | public List getCollectIds() { 69 | return collectIds; 70 | } 71 | 72 | public void setCollectIds(List collectIds) { 73 | this.collectIds = collectIds; 74 | } 75 | 76 | @Override 77 | public String toString() { 78 | return "User{" + 79 | "email='" + email + '\'' + 80 | ", icon='" + icon + '\'' + 81 | ", id=" + id + 82 | ", password='" + password + '\'' + 83 | ", type=" + type + 84 | ", username='" + username + '\'' + 85 | ", collectIds=" + collectIds + 86 | '}'; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/bean/VersionBean.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.bean; 2 | 3 | /** 4 | * @author Jenly Jenly 5 | */ 6 | public class VersionBean { 7 | 8 | /** 9 | * versionCode : 2 10 | * versionName : 1.1 11 | * url : https://github.com/WanAndroid/app/release/app-release.apk 12 | * versionDesc : 有新的版本 13 | */ 14 | 15 | private int versionCode; 16 | private String versionName; 17 | private String url; 18 | private String versionDesc; 19 | 20 | public int getVersionCode() { 21 | return versionCode; 22 | } 23 | 24 | public void setVersionCode(int versionCode) { 25 | this.versionCode = versionCode; 26 | } 27 | 28 | public String getVersionName() { 29 | return versionName; 30 | } 31 | 32 | public void setVersionName(String versionName) { 33 | this.versionName = versionName; 34 | } 35 | 36 | public String getUrl() { 37 | return url; 38 | } 39 | 40 | public void setUrl(String url) { 41 | this.url = url; 42 | } 43 | 44 | public String getVersionDesc() { 45 | return versionDesc; 46 | } 47 | 48 | public void setVersionDesc(String versionDesc) { 49 | this.versionDesc = versionDesc; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/dao/AppDatabase.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.dao; 2 | 3 | import android.arch.persistence.room.Database; 4 | import android.arch.persistence.room.Room; 5 | import android.arch.persistence.room.RoomDatabase; 6 | import android.content.Context; 7 | 8 | import com.king.wanandroid.app.comm.Constants; 9 | import com.king.wanandroid.bean.SearchHistory; 10 | 11 | /** 12 | * @author Jenly Jenly 13 | */ 14 | @Database(entities = {SearchHistory.class}, version = 1,exportSchema = false) 15 | public abstract class AppDatabase extends RoomDatabase { 16 | 17 | private static final Object mLock = new Object(); 18 | 19 | private static AppDatabase sInstance; 20 | 21 | public static AppDatabase getInstance(Context context) { 22 | synchronized (mLock){ 23 | if(sInstance == null){ 24 | sInstance = Room.databaseBuilder(context.getApplicationContext(),AppDatabase.class, Constants.DATABASE_NAME).build(); 25 | } 26 | return sInstance; 27 | } 28 | } 29 | 30 | public abstract SearchHistoryDao searchHistoryDao(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/dao/DataSource.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.dao; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.LiveData; 5 | import android.content.Context; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.king.wanandroid.bean.SearchHistory; 9 | 10 | import java.util.List; 11 | 12 | import javax.inject.Inject; 13 | import javax.inject.Singleton; 14 | 15 | import io.reactivex.Observable; 16 | import io.reactivex.schedulers.Schedulers; 17 | 18 | /** 19 | * @author Jenly Jenly 20 | */ 21 | @Singleton 22 | public class DataSource { 23 | 24 | private Context mContext; 25 | 26 | @Inject 27 | public DataSource(@NonNull Application application){ 28 | this.mContext = application; 29 | } 30 | 31 | /** 32 | * 获取搜索历史 33 | * @param count 34 | * @return 35 | */ 36 | public LiveData> getSearchHistory(int count){ 37 | return AppDatabase.getInstance(mContext).searchHistoryDao().getHistory(count); 38 | } 39 | 40 | /** 41 | * 添加搜索历史 42 | * @param key 43 | */ 44 | public void addHistory(String key){ 45 | Observable.just(key) 46 | .subscribeOn(Schedulers.io()) 47 | .subscribe(s -> 48 | AppDatabase.getInstance(mContext).searchHistoryDao().insert(new SearchHistory(s)) 49 | ); 50 | 51 | } 52 | 53 | /** 54 | * 清空历史 55 | */ 56 | public void deleteAllHistory(){ 57 | Observable.just(1).subscribeOn(Schedulers.io()) 58 | .subscribe(integer -> { 59 | AppDatabase.getInstance(mContext).searchHistoryDao().deleteAll(); 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/dao/SearchHistoryDao.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.dao; 2 | 3 | import android.arch.lifecycle.LiveData; 4 | import android.arch.persistence.room.Dao; 5 | import android.arch.persistence.room.Delete; 6 | import android.arch.persistence.room.Insert; 7 | import android.arch.persistence.room.OnConflictStrategy; 8 | import android.arch.persistence.room.Query; 9 | 10 | import com.king.wanandroid.bean.SearchHistory; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author Jenly Jenly 16 | */ 17 | @Dao 18 | public interface SearchHistoryDao { 19 | 20 | @Insert(onConflict = OnConflictStrategy.REPLACE) 21 | void insert(SearchHistory searchHistory); 22 | 23 | @Delete 24 | void delete(SearchHistory searchHistory); 25 | 26 | @Query("DELETE FROM SearchHistory") 27 | void deleteAll(); 28 | 29 | @Query("SELECT * FROM SearchHistory") 30 | LiveData> getAllHistory(); 31 | 32 | @Query("SELECT * FROM SearchHistory ORDER BY time DESC LIMIT :count") 33 | LiveData> getHistory(int count); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/component/AppComponent.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.component; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.content.Context; 6 | 7 | import com.franmontiel.persistentcookiejar.PersistentCookieJar; 8 | import com.king.wanandroid.App; 9 | import com.king.wanandroid.api.ApiService; 10 | import com.king.wanandroid.app.base.ViewModelFactory; 11 | import com.king.wanandroid.di.module.ActivityModule; 12 | import com.king.wanandroid.di.module.AppModule; 13 | import com.king.wanandroid.di.module.HttpModule; 14 | import com.king.wanandroid.di.module.ViewModelFactoryModule; 15 | import com.king.wanandroid.di.module.ViewModelModule; 16 | 17 | import javax.inject.Singleton; 18 | 19 | import dagger.Component; 20 | import dagger.android.AndroidInjectionModule; 21 | import dagger.android.AndroidInjector; 22 | import dagger.android.support.AndroidSupportInjectionModule; 23 | 24 | /** 25 | * @author Jenly Jenly 26 | */ 27 | @Singleton 28 | @Component(modules = {AppModule.class, HttpModule.class, ActivityModule.class,ViewModelFactoryModule.class, AndroidInjectionModule.class,AndroidSupportInjectionModule.class}) 29 | public interface AppComponent extends AndroidInjector { 30 | 31 | 32 | void inject(App app); 33 | 34 | Application getApplication(); 35 | 36 | Context getContext(); 37 | 38 | ApiService getApiService(); 39 | 40 | PersistentCookieJar getCookieJar(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/component/BaseActivitySubComponent.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.component; 2 | 3 | import com.king.wanandroid.app.base.BaseActivity; 4 | 5 | import dagger.Subcomponent; 6 | import dagger.android.AndroidInjectionModule; 7 | import dagger.android.AndroidInjector; 8 | 9 | /** 10 | * @author Jenly Jenly 11 | */ 12 | @Subcomponent(modules = {AndroidInjectionModule.class}) 13 | public interface BaseActivitySubComponent extends AndroidInjector{ 14 | 15 | 16 | @Subcomponent.Builder 17 | abstract class Builder extends AndroidInjector.Builder{} 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/module/ActivityModule.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.module; 2 | 3 | import com.king.wanandroid.app.about.AboutActivity; 4 | import com.king.wanandroid.app.account.LoginActivity; 5 | import com.king.wanandroid.app.account.RegisterActivity; 6 | import com.king.wanandroid.app.collect.CollectActivity; 7 | import com.king.wanandroid.app.home.HomeActivity; 8 | import com.king.wanandroid.app.navi.NaviActivity; 9 | import com.king.wanandroid.app.search.SearchActivity; 10 | import com.king.wanandroid.app.splash.SplashActivity; 11 | import com.king.wanandroid.app.tree.TreeActivity; 12 | import com.king.wanandroid.app.tree.TreeChildrenActivity; 13 | import com.king.wanandroid.app.web.WebActivity; 14 | import com.king.wanandroid.di.component.BaseActivitySubComponent; 15 | 16 | import dagger.Module; 17 | import dagger.android.ContributesAndroidInjector; 18 | 19 | /** 20 | * @author Jenly Jenly 21 | */ 22 | @Module(subcomponents = BaseActivitySubComponent.class) 23 | public abstract class ActivityModule { 24 | 25 | // 26 | // @Binds 27 | // @IntoMap 28 | // @ActivityKey(HomeActivity.class) 29 | // public abstract AndroidInjector bindHomeActivityInjectorFactory(BaseActivitySubComponent.Builder builder); 30 | 31 | 32 | @ContributesAndroidInjector 33 | abstract SplashActivity contributesSplashActivity(); 34 | 35 | @ContributesAndroidInjector 36 | abstract HomeActivity contributesHomeActivity(); 37 | 38 | @ContributesAndroidInjector 39 | abstract WebActivity contributesWebActivity(); 40 | 41 | @ContributesAndroidInjector 42 | abstract LoginActivity contributesLoginActivity(); 43 | 44 | @ContributesAndroidInjector 45 | abstract RegisterActivity contributesRegisterActivity(); 46 | 47 | @ContributesAndroidInjector 48 | abstract CollectActivity contributesCollectActivity(); 49 | 50 | @ContributesAndroidInjector 51 | abstract TreeActivity contributesTreeActivity(); 52 | 53 | @ContributesAndroidInjector 54 | abstract TreeChildrenActivity contributesTreeChildrenActivity(); 55 | 56 | @ContributesAndroidInjector 57 | abstract SearchActivity contributesSearchActivity(); 58 | 59 | @ContributesAndroidInjector 60 | abstract NaviActivity contributesNaviActivity(); 61 | 62 | @ContributesAndroidInjector 63 | abstract AboutActivity contributesAboutActivity(); 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/module/AppModule.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.module; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.support.v4.util.ArrayMap; 6 | 7 | import java.util.Map; 8 | 9 | import javax.inject.Singleton; 10 | 11 | import dagger.Module; 12 | import dagger.Provides; 13 | 14 | /** 15 | * @author Jenly Jenly 16 | */ 17 | @Module(includes = {ViewModelModule.class}) 18 | public class AppModule { 19 | 20 | private Application app; 21 | 22 | public AppModule(Application app){ 23 | this.app = app; 24 | } 25 | 26 | @Singleton 27 | @Provides 28 | public Application provideApp(){ 29 | return app; 30 | } 31 | 32 | @Singleton 33 | @Provides 34 | public Context provideContext(){ 35 | return app; 36 | } 37 | 38 | @Singleton 39 | @Provides 40 | Map provideExtras() { 41 | return new ArrayMap<>(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/module/HomeModule.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.module; 2 | 3 | 4 | import dagger.Module; 5 | 6 | /** 7 | * @author Jenly Jenly 8 | */ 9 | @Module 10 | public class HomeModule { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/module/HttpModule.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.module; 2 | 3 | import android.content.Context; 4 | 5 | import com.franmontiel.persistentcookiejar.ClearableCookieJar; 6 | import com.franmontiel.persistentcookiejar.PersistentCookieJar; 7 | import com.franmontiel.persistentcookiejar.cache.SetCookieCache; 8 | import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; 9 | import com.king.wanandroid.api.ApiService; 10 | import com.king.wanandroid.api.LogInterceptor; 11 | 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import javax.inject.Singleton; 15 | 16 | import dagger.Module; 17 | import dagger.Provides; 18 | import okhttp3.CookieJar; 19 | import okhttp3.OkHttpClient; 20 | import retrofit2.Retrofit; 21 | import retrofit2.converter.gson.GsonConverterFactory; 22 | 23 | /** 24 | * @author Jenly Jenly 25 | */ 26 | @Module 27 | public class HttpModule { 28 | 29 | private static final int DEFAULT_TIME_OUT = 15; 30 | 31 | private String baseUrl; 32 | 33 | 34 | public HttpModule(String baseUrl){ 35 | this.baseUrl = baseUrl; 36 | } 37 | 38 | 39 | @Singleton 40 | @Provides 41 | public PersistentCookieJar provideCookieJar(Context context){ 42 | return new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context)); 43 | } 44 | 45 | @Singleton 46 | @Provides 47 | public OkHttpClient provideOkHttpClient(PersistentCookieJar cookieJar){ 48 | return new OkHttpClient.Builder() 49 | .connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS) 50 | .readTimeout(DEFAULT_TIME_OUT,TimeUnit.SECONDS) 51 | .writeTimeout(DEFAULT_TIME_OUT,TimeUnit.SECONDS) 52 | .addInterceptor(new LogInterceptor()) 53 | .cookieJar(cookieJar) 54 | .build(); 55 | 56 | } 57 | 58 | @Singleton 59 | @Provides 60 | public Retrofit provideRetrofit(OkHttpClient client){ 61 | return new Retrofit.Builder() 62 | .baseUrl(baseUrl) 63 | .client(client) 64 | .addConverterFactory(GsonConverterFactory.create()) 65 | .build(); 66 | 67 | } 68 | 69 | @Singleton 70 | @Provides 71 | public ApiService provideApiService(Retrofit retrofit){ 72 | return retrofit.create(ApiService.class); 73 | 74 | } 75 | 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/module/ViewModelFactoryModule.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.module; 2 | 3 | import android.arch.lifecycle.ViewModelProvider; 4 | 5 | import com.king.wanandroid.app.base.ViewModelFactory; 6 | 7 | import dagger.Binds; 8 | import dagger.Module; 9 | 10 | /** 11 | * @author Jenly Jenly 12 | */ 13 | @Module(includes = ViewModelModule.class) 14 | public abstract class ViewModelFactoryModule { 15 | 16 | @Binds 17 | abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory viewModelFactory); 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/module/ViewModelModule.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.module; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | 5 | import com.king.wanandroid.app.account.LoginViewModel; 6 | import com.king.wanandroid.app.base.DataViewModel; 7 | import com.king.wanandroid.app.collect.CollectViewModel; 8 | import com.king.wanandroid.app.home.HomeViewModel; 9 | import com.king.wanandroid.app.navi.NaviViewModel; 10 | import com.king.wanandroid.app.search.SearchViewModel; 11 | import com.king.wanandroid.app.tree.TreeViewModel; 12 | import com.king.wanandroid.di.scope.ViewModelKey; 13 | 14 | import dagger.Binds; 15 | import dagger.Module; 16 | import dagger.multibindings.IntoMap; 17 | 18 | /** 19 | * @author Jenly Jenly 20 | */ 21 | @Module 22 | public abstract class ViewModelModule { 23 | 24 | @Binds 25 | @IntoMap 26 | @ViewModelKey(HomeViewModel.class) 27 | abstract ViewModel bindHomeViewModel(HomeViewModel viewModel); 28 | 29 | @Binds 30 | @IntoMap 31 | @ViewModelKey(DataViewModel.class) 32 | abstract ViewModel bindDataViewModel(DataViewModel viewModel); 33 | 34 | @Binds 35 | @IntoMap 36 | @ViewModelKey(LoginViewModel.class) 37 | abstract ViewModel bindLoginViewModel(LoginViewModel viewModel); 38 | 39 | @Binds 40 | @IntoMap 41 | @ViewModelKey(CollectViewModel.class) 42 | abstract ViewModel bindCollectViewModel(CollectViewModel viewModel); 43 | 44 | @Binds 45 | @IntoMap 46 | @ViewModelKey(TreeViewModel.class) 47 | abstract ViewModel bindTreeViewModel(TreeViewModel viewModel); 48 | 49 | @Binds 50 | @IntoMap 51 | @ViewModelKey(SearchViewModel.class) 52 | abstract ViewModel bindSearchViewModel(SearchViewModel viewModel); 53 | 54 | @Binds 55 | @IntoMap 56 | @ViewModelKey(NaviViewModel.class) 57 | abstract ViewModel bindNaviViewModel(NaviViewModel viewModel); 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/scope/ActivityScope.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.scope; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Scope; 7 | 8 | /** 9 | * @author Jenly Jenly 10 | */ 11 | 12 | @Scope 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface ActivityScope { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/scope/FragmentScope.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.scope; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Scope; 7 | 8 | /** 9 | * @author Jenly Jenly 10 | */ 11 | @Scope 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface FragmentScope { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/di/scope/ViewModelKey.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.di.scope; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | 5 | import java.lang.annotation.Documented; 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | import dagger.MapKey; 12 | 13 | /** 14 | * @author Jenly Jenly 15 | */ 16 | @Documented 17 | @Target({ElementType.METHOD}) 18 | @Retention(RetentionPolicy.RUNTIME) 19 | @MapKey 20 | public @interface ViewModelKey { 21 | 22 | Class value(); 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/glide/WanGlideModule.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.glide; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.bumptech.glide.GlideBuilder; 7 | import com.bumptech.glide.annotation.GlideModule; 8 | import com.bumptech.glide.load.engine.cache.DiskLruCacheWrapper; 9 | import com.bumptech.glide.module.AppGlideModule; 10 | 11 | /** 12 | * @author Jenly Jenly 13 | */ 14 | @GlideModule 15 | public class WanGlideModule extends AppGlideModule { 16 | 17 | public static final int IMAGE_DISK_CACHE_MAX_SIZE = 100 * 1024 * 1024; 18 | 19 | @Override 20 | public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) { 21 | super.applyOptions(context, builder); 22 | 23 | builder.setDiskCache(() -> DiskLruCacheWrapper.create(context.getCacheDir(),IMAGE_DISK_CACHE_MAX_SIZE)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/util/AES.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.util; 2 | 3 | 4 | import android.text.TextUtils; 5 | 6 | import javax.crypto.Cipher; 7 | import javax.crypto.spec.IvParameterSpec; 8 | import javax.crypto.spec.SecretKeySpec; 9 | 10 | /** 11 | * @author Jenly Jenly 12 | */ 13 | public enum AES { 14 | 15 | INSTANCE; 16 | 17 | private static final String IV_STRING = "ABCD1234EFGH5678"; 18 | public static final String DEFAULT_KEY = "QWERTYUIOPASDFGH"; 19 | private static final String charset = "UTF-8"; 20 | 21 | public String encrypt(String content) { 22 | try{ 23 | encrypt(content,DEFAULT_KEY); 24 | }catch (Exception e){ 25 | e.printStackTrace(); 26 | } 27 | return null; 28 | } 29 | 30 | public String encrypt(String content, String key) throws Exception { 31 | if(TextUtils.isEmpty(content)) 32 | return null; 33 | byte[] contentBytes = content.getBytes(charset); 34 | byte[] keyBytes = key.getBytes(charset); 35 | byte[] encryptedBytes = encrypt(contentBytes, keyBytes); 36 | return Base64.encode(encryptedBytes); 37 | } 38 | 39 | public String decrypt(String content) { 40 | try{ 41 | decrypt(content,DEFAULT_KEY); 42 | }catch (Exception e){ 43 | e.printStackTrace(); 44 | } 45 | return null; 46 | } 47 | 48 | public String decrypt(String content, String key) throws Exception { 49 | if(TextUtils.isEmpty(content)) 50 | return null; 51 | byte[] encryptedBytes = Base64.decode(content); 52 | byte[] keyBytes = key.getBytes(charset); 53 | byte[] decryptedBytes = decrypt(encryptedBytes, keyBytes); 54 | return new String(decryptedBytes, charset); 55 | } 56 | 57 | public byte[] encrypt(byte[] contentBytes, byte[] keyBytes) throws Exception { 58 | return cipherOperation(contentBytes, keyBytes, Cipher.ENCRYPT_MODE); 59 | } 60 | 61 | public byte[] decrypt(byte[] contentBytes, byte[] keyBytes) throws Exception { 62 | return cipherOperation(contentBytes, keyBytes, Cipher.DECRYPT_MODE); 63 | } 64 | 65 | private byte[] cipherOperation(byte[] contentBytes, byte[] keyBytes, int mode) throws Exception { 66 | SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES"); 67 | 68 | byte[] initParam = IV_STRING.getBytes(charset); 69 | IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam); 70 | 71 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 72 | cipher.init(mode, secretKey, ivParameterSpec); 73 | 74 | return cipher.doFinal(contentBytes); 75 | } 76 | 77 | 78 | } -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/util/RandomUtils.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.util; 2 | 3 | import android.graphics.Color; 4 | import android.support.annotation.ColorInt; 5 | import android.support.annotation.IntRange; 6 | 7 | import java.util.Random; 8 | 9 | /** 10 | * @author Jenly Jenly 11 | */ 12 | public enum RandomUtils { 13 | INSTANCE; 14 | 15 | private Random mRandom = new Random(); 16 | 17 | @ColorInt 18 | public int randomColor(@IntRange(from=0,to=255) int min,@IntRange(from=0,to=255) int max){ 19 | return Color.rgb(random(min,max),random(min,max),random(min,max)); 20 | } 21 | 22 | public int random(int min,int max){ 23 | return mRandom.nextInt(max - min + 1) + min; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/wanandroid/util/TimeUtils.java: -------------------------------------------------------------------------------- 1 | package com.king.wanandroid.util; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import com.king.wanandroid.R; 7 | 8 | import java.text.SimpleDateFormat; 9 | import java.util.Date; 10 | 11 | /** 12 | * @author Jenly Jenly 13 | */ 14 | public final class TimeUtils { 15 | 16 | /** 时间格式:yyyyMMddHHmmss */ 17 | public static final String FORMAT_Y_TO_S = "yyyyMMddHHmmss"; 18 | 19 | /** 时间格式:yyyy-MM-dd HH:mm:ss */ 20 | public static final String FORMAT_Y_TO_S_EN = "yyyy-MM-dd HH:mm:ss"; 21 | 22 | /** 时间格式:yyyy-MM-dd */ 23 | public static final String FORMAT_Y_TO_D = "yyyy-MM-dd"; 24 | 25 | 26 | //------------------------------------ 27 | /** 28 | * 异常时间 29 | */ 30 | private static final int EXCEPTION_TIME = -1; 31 | 32 | /** 33 | * 一分钟的毫秒值 34 | */ 35 | public static final long ONE_MINUTE = 60 * 1000; 36 | 37 | /** 38 | * 一小时的毫秒值 39 | */ 40 | public static final long ONE_HOUR = 60 * ONE_MINUTE; 41 | 42 | /** 43 | * 一天的毫秒值 44 | */ 45 | public static final long ONE_DAY = 24 * ONE_HOUR; 46 | 47 | /** 48 | * 一月的毫秒值 49 | */ 50 | public static final long ONE_MONTH = 30 * ONE_DAY; 51 | 52 | /** 53 | * 一年的毫秒值 54 | */ 55 | public static final long ONE_YEAR = 12 * ONE_MONTH; 56 | 57 | private TimeUtils(){ 58 | } 59 | 60 | 61 | /** 62 | * 获得格式化后的时间 63 | * @param time 64 | * @return 65 | */ 66 | public static String getTime(long time){ 67 | return getTime(time,FORMAT_Y_TO_D); 68 | } 69 | 70 | /** 71 | * 获取格式化后的时间 72 | * @param time 73 | * @param format 74 | * @return 75 | */ 76 | public static String getTime(long time,String format){ 77 | SimpleDateFormat sdf = new SimpleDateFormat(format); 78 | return sdf.format(new Date(time)); 79 | } 80 | 81 | /** 82 | * 获得相对时间 83 | * @param context 84 | * @param lastUpdateTime 85 | * @return 86 | */ 87 | public static String getUpdatedRelativeTime(Context context, long lastUpdateTime){ 88 | Resources resources = context.getResources(); 89 | long currentTime = System.currentTimeMillis(); 90 | long timePassed = currentTime - lastUpdateTime; 91 | long timeIntoFormat; 92 | if (lastUpdateTime == EXCEPTION_TIME) { 93 | return ""; 94 | }else if (timePassed < ONE_MINUTE) { 95 | return resources.getString(R.string.updated_just_now); 96 | } else if (timePassed < ONE_HOUR) { 97 | timeIntoFormat = timePassed / ONE_MINUTE; 98 | int value = (int)timeIntoFormat; 99 | return String.format(resources.getString(R.string.updated_before_n_min), value); 100 | } else if (timePassed < ONE_DAY) { 101 | timeIntoFormat = timePassed / ONE_HOUR; 102 | int value = (int)timeIntoFormat; 103 | return String.format(resources.getString(R.string.updated_before_n_hour), value); 104 | } else if (timePassed < 3 * ONE_DAY) { 105 | timeIntoFormat = timePassed / ONE_DAY; 106 | int value = (int)timeIntoFormat; 107 | return String.format(resources.getString(R.string.updated_before_n_day), value); 108 | } 109 | 110 | return getTime(lastUpdateTime); 111 | 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /app/src/main/res/anim/cycle_3.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/in.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/out.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/shake.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/splash.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /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-xxhdpi/btn_back_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_back_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_back_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_back_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_bg_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_bg_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_bg_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_bg_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_black_back_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_black_back_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_black_back_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_black_back_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_clear.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_close_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_close_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_close_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_close_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_delete_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_delete_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_delete_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_delete_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_menu_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_menu_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_menu_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_menu_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_more_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_more_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_more_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_more_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_navi_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_navi_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_navi_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_navi_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_none.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_search_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_search_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_search_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/btn_search_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/collect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/collected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/collected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/github.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/home_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/home_bg.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_about_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_about_image.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_collect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_empty.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_explorer.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_github.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_menu_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_menu_about.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_menu_collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_menu_collect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_menu_logout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_menu_logout.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_menu_navi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_menu_navi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_menu_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_menu_project.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_menu_system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_menu_system.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_refresh.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_right_arrow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WanAndroid/526e34206eb39f1a5c669c11b6daf99c4c9e22db/app/src/main/res/drawable-xxhdpi/ic_top.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_back_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_black_back_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_clear_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_close_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_delete_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_menu_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_more_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_navi_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_search_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/collect_select_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | 23 | 25 | 27 | 29 | 31 | 33 | 35 | 37 | 39 | 41 | 43 | 45 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 63 | 65 | 67 | 69 | 71 | 73 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/line_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/line_drawable_8.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/search_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tag_bg_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tag_bg_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tag_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/about_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 12 | 20 | 28 | 39 | 40 | 41 | 45 | 50 | 55 | 56 | 57 | 58 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/res/layout/collect_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 27 | 28 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/empty_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/home_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 21 | 22 | 27 | 33 | 34 | 35 | 40 | 46 | 51 | 57 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /app/src/main/res/layout/line_xh.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/login_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 26 | 27 | 28 | 37 | 47 | 48 | 49 | 58 | 68 | 69 | 70 |