├── app
├── .gitignore
├── keystore.jks
├── src
│ ├── main
│ │ ├── assets
│ │ │ ├── get_user.json
│ │ │ ├── banner.json
│ │ │ └── game.json
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── styles.xml
│ │ │ │ ├── base_dimens.xml
│ │ │ │ └── base_colors.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
│ │ │ ├── drawable-xxhdpi
│ │ │ │ ├── ic_recommond.png
│ │ │ │ ├── icon_firefly.png
│ │ │ │ ├── banner_gray_mask.png
│ │ │ │ └── ic_launcher_background.xml
│ │ │ ├── xml
│ │ │ │ └── network_security_config.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ ├── activity_no_cover.xml
│ │ │ │ ├── custom_loading_view.xml
│ │ │ │ ├── game_item_date.xml
│ │ │ │ ├── activity_databinding.xml
│ │ │ │ ├── challenge_home_item_see_more.xml
│ │ │ │ ├── activity_feed_article.xml
│ │ │ │ ├── activity_paging_list.xml
│ │ │ │ ├── fragment_paging_list.xml
│ │ │ │ ├── activity_list.xml
│ │ │ │ ├── activity_game_list.xml
│ │ │ │ ├── item.xml
│ │ │ │ ├── activity_normal_fragment.xml
│ │ │ │ ├── game_item.xml
│ │ │ │ ├── fragment_cover.xml
│ │ │ │ ├── activity_cover.xml
│ │ │ │ ├── activity_cover_fragment.xml
│ │ │ │ ├── recyclerview_item_banner.xml
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── challenge_home_item_challenge.xml
│ │ │ │ ├── challenge_home_item_circle.xml
│ │ │ │ ├── recyclerview_item_banner_content.xml
│ │ │ │ └── recyclerview_item_feed_article.xml
│ │ │ ├── drawable
│ │ │ │ ├── challenge_see_more_bg.xml
│ │ │ │ ├── challenge_home_recomand_subcribe_bg.xml
│ │ │ │ ├── challenge_home_score_bg.xml
│ │ │ │ └── ic_launcher_background.xml
│ │ │ └── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── czq
│ │ │ │ └── kotlinarch
│ │ │ │ ├── template
│ │ │ │ ├── list
│ │ │ │ │ ├── Item.java
│ │ │ │ │ ├── ListContact.kt
│ │ │ │ │ ├── ListPresenter.kt
│ │ │ │ │ ├── ItemBinder.kt
│ │ │ │ │ ├── ListActivity.kt
│ │ │ │ │ └── ListFragment.kt
│ │ │ │ └── cover
│ │ │ │ │ ├── CoverContact.kt
│ │ │ │ │ ├── CoverPresenter.kt
│ │ │ │ │ ├── CoverFragment.kt
│ │ │ │ │ └── CoverActivity.kt
│ │ │ │ ├── data
│ │ │ │ ├── local
│ │ │ │ │ └── LocalDataRepository.kt
│ │ │ │ ├── viewModel
│ │ │ │ │ ├── GameDate.kt
│ │ │ │ │ ├── DataBindingVM.kt
│ │ │ │ │ ├── ChallengeRecommandSeeMoreVm.kt
│ │ │ │ │ ├── BannerList.kt
│ │ │ │ │ ├── ChallengeRecomandCircleVm.kt
│ │ │ │ │ └── ChallengeRecommandItemVm.kt
│ │ │ │ ├── model
│ │ │ │ │ ├── Result.kt
│ │ │ │ │ ├── Page.kt
│ │ │ │ │ ├── User.kt
│ │ │ │ │ ├── Game.kt
│ │ │ │ │ ├── Banner.kt
│ │ │ │ │ ├── ChallengeRecomand.kt
│ │ │ │ │ └── FeedArticle.kt
│ │ │ │ ├── remote
│ │ │ │ │ ├── api
│ │ │ │ │ │ └── RemoteApi.kt
│ │ │ │ │ ├── MockDataRepository.kt
│ │ │ │ │ └── RemoteDataRepository.kt
│ │ │ │ └── converter
│ │ │ │ │ └── ChallengeRecomondCoverter.kt
│ │ │ │ ├── example
│ │ │ │ ├── NoCoverPresenter.kt
│ │ │ │ ├── DatabindingPresenter.kt
│ │ │ │ ├── CoverContact.kt
│ │ │ │ ├── NoCoverContract.kt
│ │ │ │ ├── DatabindingContract.kt
│ │ │ │ ├── fragment
│ │ │ │ │ ├── CoverContact.kt
│ │ │ │ │ ├── PagingListContact.kt
│ │ │ │ │ ├── CoverFragment.kt
│ │ │ │ │ ├── CoverPresenter.kt
│ │ │ │ │ ├── PagingListPresenter.kt
│ │ │ │ │ └── PagingListFragment.kt
│ │ │ │ ├── FeedArticleContract.kt
│ │ │ │ ├── PagingListContact.kt
│ │ │ │ ├── GameListContact.kt
│ │ │ │ ├── CoverPresenter.kt
│ │ │ │ ├── NoCoverActivity.kt
│ │ │ │ ├── itembinder
│ │ │ │ │ ├── SeeMoreViewbinder.kt
│ │ │ │ │ ├── GameDateViewbinder.kt
│ │ │ │ │ ├── GameViewbinder.kt
│ │ │ │ │ ├── ChallengeViewbinder.kt
│ │ │ │ │ ├── CircleViewbinder.kt
│ │ │ │ │ ├── BannerItembinder.kt
│ │ │ │ │ ├── BannerContentItembinder.kt
│ │ │ │ │ └── FeedArticleItembinder.kt
│ │ │ │ ├── CoverActivity.kt
│ │ │ │ ├── FeedArticleActivity.kt
│ │ │ │ ├── DatabindingActivity.kt
│ │ │ │ ├── NormalFragmentActivity.kt
│ │ │ │ ├── CoverFragmentActivity.kt
│ │ │ │ ├── PagingListPresenter.kt
│ │ │ │ ├── GameListPresenter.kt
│ │ │ │ ├── PagingListActivity.kt
│ │ │ │ ├── GameListActivity.kt
│ │ │ │ └── FeedArticlePresenter.kt
│ │ │ │ ├── MainActivity.kt
│ │ │ │ └── App.kt
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── czq
│ │ │ └── kotlinarch
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── czq
│ │ └── kotlinarch
│ │ └── ExampleInstrumentedTest.kt
├── build.gradle
└── proguard-rules.pro
├── kotlin_arch
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ └── colors.xml
│ │ │ ├── drawable
│ │ │ │ └── state_error_btn_bg.xml
│ │ │ └── layout
│ │ │ │ ├── fragment_base.xml
│ │ │ │ ├── activity_base.xml
│ │ │ │ ├── common_empty_view.xml
│ │ │ │ ├── common_loading_view.xml
│ │ │ │ ├── fragment_base_paging.xml
│ │ │ │ ├── activity_base_paging.xml
│ │ │ │ └── common_error_view.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── czq
│ │ │ │ └── kotlin_arch
│ │ │ │ ├── paging
│ │ │ │ ├── PagingStrategy.kt
│ │ │ │ ├── offset
│ │ │ │ │ ├── OffsetPageInfo.kt
│ │ │ │ │ └── OffsetStrategy.kt
│ │ │ │ └── normal
│ │ │ │ │ ├── NormalPagingInfo.kt
│ │ │ │ │ └── NormalPagingStrategy.kt
│ │ │ │ ├── basePage
│ │ │ │ ├── paging
│ │ │ │ │ ├── IBasePagingPrensenter.kt
│ │ │ │ │ ├── IBasePagingView.kt
│ │ │ │ │ ├── BasePagingPrensenterImpl.kt
│ │ │ │ │ ├── BasePagingActivity.kt
│ │ │ │ │ └── BasePagingFragment.kt
│ │ │ │ └── base
│ │ │ │ │ ├── IBasePrensenter.kt
│ │ │ │ │ ├── IBaseView.kt
│ │ │ │ │ ├── BaseFragment.kt
│ │ │ │ │ └── BaseActivity.kt
│ │ │ │ ├── component
│ │ │ │ └── cover
│ │ │ │ │ ├── CoverListener.kt
│ │ │ │ │ ├── CoverFrameViewConfig.kt
│ │ │ │ │ └── CoverFrameLayout.kt
│ │ │ │ └── common
│ │ │ │ └── util
│ │ │ │ ├── ext
│ │ │ │ ├── Activity.kt
│ │ │ │ └── Density.kt
│ │ │ │ ├── MockUtil.kt
│ │ │ │ └── AssetUtil.kt
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── czq
│ │ │ └── kotlin_arch
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── czq
│ │ └── kotlin_arch
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── 截图
├── sc1.png
├── sc2.png
├── sc3.png
└── sc4.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── LICENSE
├── README.md
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/kotlin_arch/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':kotlin_arch'
2 |
--------------------------------------------------------------------------------
/截图/sc1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/截图/sc1.png
--------------------------------------------------------------------------------
/截图/sc2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/截图/sc2.png
--------------------------------------------------------------------------------
/截图/sc3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/截图/sc3.png
--------------------------------------------------------------------------------
/截图/sc4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/截图/sc4.png
--------------------------------------------------------------------------------
/app/keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/keystore.jks
--------------------------------------------------------------------------------
/app/src/main/assets/get_user.json:
--------------------------------------------------------------------------------
1 | {"avtar":"","id":1,"sex":0,"userName":"manondidi"}
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | kotlinArch
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/list/Item.java:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.list;
2 |
3 | public class Item {
4 | }
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/local/LocalDataRepository.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.local
2 |
3 | class LocalDataRepository {
4 | }
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_recommond.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/drawable-xxhdpi/ic_recommond.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_firefly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/drawable-xxhdpi/icon_firefly.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/banner_gray_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/drawable-xxhdpi/banner_gray_mask.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/manondidi/kotlinArch/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/viewModel/GameDate.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.viewModel
2 |
3 | class GameDate {
4 | var date: String? = null
5 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/viewModel/DataBindingVM.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.viewModel
2 |
3 | class DataBindingVM {
4 | var txt: String? = null
5 | }
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/viewModel/ChallengeRecommandSeeMoreVm.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.viewModel
2 |
3 | class ChallengeRecommandSeeMoreVm {
4 | var id: String? = null
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/model/Result.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.model
2 |
3 | class Result {
4 | var status: Int = 0
5 | var msg: String? = null
6 | var data: T? = null
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/viewModel/BannerList.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.viewModel
2 |
3 | import com.czq.kotlinarch.data.model.Banner
4 |
5 | class BannerList {
6 | var banners: List? = null
7 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | kotlin_arch
3 | 加载失败
4 | 空空如也
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/model/Page.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.model
2 |
3 | class Page {
4 | var totalNum: Int = 0
5 | var pageNo: Int = 0
6 | var pageSize: Int = 0
7 | var listData: List? = null
8 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/NoCoverPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 |
4 | class NoCoverPresenter(var mView: NoCoverContract.IView) : NoCoverContract.IPrensenter {
5 |
6 | override fun start() {
7 |
8 | }
9 |
10 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/DatabindingPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 |
4 | class DatabindingPresenter(var mView: DatabindingContract.IView) : DatabindingContract.IPrensenter {
5 |
6 | override fun start() {
7 |
8 | }
9 |
10 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Aug 09 08:57:38 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
7 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/paging/PagingStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.paging
2 |
3 | interface PagingStrategy {
4 |
5 | fun addPage(info:Any?)
6 | fun resetPage()
7 | fun getPageInfo():Any
8 | fun checkFinish(result:Any?,listSize: Int):Boolean
9 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/drawable/state_error_btn_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/viewModel/ChallengeRecomandCircleVm.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.viewModel
2 |
3 | class ChallengeRecomandCircleVm {
4 | var id: String? = null
5 | var title: String? = null
6 | var subscribedCount = 0
7 | var challengeCount = 0
8 | var icon: String? = null
9 | var hasSubscribed = false
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/model/User.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.model
2 |
3 | class User {
4 |
5 | /**
6 | * avtar :
7 | * id : 1
8 | * sex : 0
9 | * userName : manondidi
10 | */
11 |
12 | var avtar: String? = null
13 | var id: Int = 0
14 | var sex: Int = 0
15 | var userName: String? = null
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/viewModel/ChallengeRecommandItemVm.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.viewModel
2 |
3 | class ChallengeRecommandItemVm {
4 | var index = 0
5 | var id: String? = null
6 | var title: String? = null
7 | var candidateCount = 0
8 | var takeOnCount = 0
9 | var candidatePoint = 0
10 | var cover: String? = null
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/CoverContact.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBaseView
5 |
6 | interface CoverContact {
7 |
8 | interface CoverView : IBaseView {
9 |
10 | }
11 |
12 | interface CoverPrensenter : IBasePrensenter {
13 |
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/NoCoverContract.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBaseView
5 |
6 | interface NoCoverContract {
7 |
8 | interface IView : IBaseView {
9 |
10 | }
11 |
12 | interface IPrensenter : IBasePrensenter {
13 |
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/paging/offset/OffsetPageInfo.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.paging.offset
2 |
3 | class OffsetPageInfo {
4 | var type = "new"
5 | var pageSize = 20
6 | var offsetId: String? = null
7 |
8 | init {
9 | this.pageSize = pageSize
10 | }
11 |
12 | fun isFirstPage(): Boolean {
13 | return type == "new"
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/DatabindingContract.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBaseView
5 |
6 | interface DatabindingContract {
7 |
8 | interface IView : IBaseView {
9 |
10 | }
11 |
12 | interface IPrensenter : IBasePrensenter {
13 |
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/paging/normal/NormalPagingInfo.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.paging.normal
2 |
3 | class NormalPagingInfo {
4 |
5 | var pageSize: Int = 0
6 | var pageNum: Int = 0
7 | var totalCount: Int = 0
8 | var startPageNum: Int = 0//从多少开始计算的 一般分页要么是0 要么是1
9 |
10 | fun isFirstPage(): Boolean {
11 | return startPageNum == pageNum
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/cover/CoverContact.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.cover
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBaseView
5 |
6 | interface CoverContact {
7 |
8 | interface CoverView : IBaseView {
9 |
10 | }
11 |
12 | interface CoverPrensenter : IBasePrensenter {
13 |
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/fragment/CoverContact.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.fragment
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBaseView
5 |
6 | interface CoverContact {
7 |
8 | interface CoverView : IBaseView {
9 |
10 | }
11 |
12 | interface CoverPrensenter : IBasePrensenter {
13 |
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/paging/IBasePagingPrensenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.base
2 |
3 | import com.czq.kotlin_arch.paging.PagingStrategy
4 |
5 | interface IBasePagingPrensenter : IBasePrensenter {
6 |
7 |
8 | fun getPagingStrategy(): PagingStrategy?
9 |
10 | fun onLoadData(pagingStrategy: PagingStrategy?)
11 |
12 | fun resetPage()
13 |
14 | fun loadData()
15 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/layout/fragment_base.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/base/IBasePrensenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.base
2 |
3 | import androidx.lifecycle.Lifecycle
4 | import androidx.lifecycle.LifecycleObserver
5 | import androidx.lifecycle.LifecycleOwner
6 | import androidx.lifecycle.OnLifecycleEvent
7 | import org.jetbrains.annotations.NotNull
8 |
9 |
10 | interface IBasePrensenter : LifecycleObserver {
11 | fun start()
12 |
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/FeedArticleContract.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePagingPrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBasePagingView
5 |
6 | interface FeedArticleContract {
7 |
8 | interface IView : IBasePagingView {
9 |
10 | }
11 |
12 | interface IPresenter : IBasePagingPrensenter {
13 |
14 | }
15 |
16 | }
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/PagingListContact.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePagingPrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBasePagingView
5 |
6 | class PagingListContact {
7 |
8 |
9 | interface PagingListView : IBasePagingView {
10 |
11 | }
12 |
13 | interface PagingListPresenter : IBasePagingPrensenter {
14 |
15 | }
16 |
17 |
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/list/ListContact.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.list
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePagingPrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBasePagingView
5 |
6 | class ListContact {
7 |
8 |
9 | interface PagingListView : IBasePagingView {
10 |
11 | }
12 |
13 | interface PagingListPresenter : IBasePagingPrensenter {
14 |
15 | }
16 |
17 |
18 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/component/cover/CoverListener.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.component.cover
2 |
3 | import android.view.View
4 |
5 | interface CoverListener {
6 | fun onShowContent() {
7 |
8 | }
9 |
10 | fun onShowLoading(loadingView: View?) {
11 |
12 | }
13 |
14 | fun onShowError(errorView: View?) {
15 |
16 | }
17 |
18 | fun onShowEmpty(emptyView: View?) {
19 |
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/component/cover/CoverFrameViewConfig.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.component.cover
2 |
3 | import com.czq.kotlin_arch.R
4 |
5 | class CoverFrameViewConfig {
6 |
7 | companion object {
8 | var defaultLoadingViewLayout = R.layout.common_loading_view
9 | var defaultEmptyViewLayout = R.layout.common_empty_view
10 | var defaultErrorViewLayout = R.layout.common_error_view
11 | }
12 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/fragment/PagingListContact.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.fragment
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePagingPrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBasePagingView
5 |
6 | class PagingListContact {
7 |
8 |
9 | interface PagingListView : IBasePagingView {
10 |
11 | }
12 |
13 | interface PagingListPresenter : IBasePagingPrensenter {
14 |
15 | }
16 |
17 |
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/GameListContact.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import com.czq.kotlin_arch.basePage.base.IBasePagingPrensenter
4 | import com.czq.kotlin_arch.basePage.base.IBasePagingView
5 |
6 | class GameListContact {
7 |
8 |
9 | interface PagingListView : IBasePagingView {
10 | fun hello()
11 |
12 | }
13 |
14 | interface PagingListPresenter : IBasePagingPrensenter {
15 |
16 | }
17 |
18 |
19 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/czq/kotlinarch/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/layout/activity_base.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/model/Game.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.model
2 |
3 | class Game(
4 | var createTime: Int? = 0, // 1526374588
5 | var hasRecord: Boolean? = false, // false
6 | var icon: String? = "", // http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/aDEuWEbmnrqkrku.png!a-3-240x.png
7 | var iconType: String? = "", // normal
8 | var id: String? = "", // 10089387
9 | var title: String? = "" // Octocopter: Double or Squids
10 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/CoverPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import com.czq.kotlinarch.data.remote.RemoteDataRepository
4 | import com.uber.autodispose.lifecycle.autoDisposable
5 | import io.reactivex.android.schedulers.AndroidSchedulers
6 | import io.reactivex.schedulers.Schedulers
7 |
8 | class CoverPresenter(var mView: CoverContact.CoverView) : CoverContact.CoverPrensenter {
9 |
10 | override fun start() {
11 |
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/base/IBaseView.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.base
2 |
3 | import android.content.Context
4 | import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
5 |
6 | interface IBaseView {
7 |
8 | fun showContent()
9 | fun showLoading()
10 | fun showEmpty()
11 | fun showError(it: Throwable? = null)
12 | fun getContext(): Context
13 | fun autoDispose(): AndroidLifecycleScopeProvider
14 |
15 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/cover/CoverPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.cover
2 |
3 | import com.czq.kotlinarch.data.remote.RemoteDataRepository
4 | import com.uber.autodispose.lifecycle.autoDisposable
5 | import io.reactivex.android.schedulers.AndroidSchedulers
6 | import io.reactivex.schedulers.Schedulers
7 |
8 | class CoverPresenter(var mView: CoverContact.CoverView) : CoverContact.CoverPrensenter {
9 |
10 | override fun start() {
11 |
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/test/java/com/czq/kotlin_arch/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_no_cover.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #008577
5 | #00574B
6 | #D81B60
7 |
8 |
9 | #f5f5f5
10 | @color/colorPrimary
11 | @color/colorPrimary
12 | #ffffff
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/challenge_see_more_bg.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/challenge_home_recomand_subcribe_bg.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/challenge_home_score_bg.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/custom_loading_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/layout/common_empty_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/NoCoverActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 |
4 | import com.czq.kotlin_arch.basePage.base.BaseActivity
5 | import com.czq.kotlinarch.R
6 |
7 | class NoCoverActivity : BaseActivity(), NoCoverContract.IView {
8 |
9 | override fun createPresenter(): NoCoverContract.IPrensenter {
10 | return NoCoverPresenter(this)
11 | }
12 |
13 | override fun initView() {
14 | super.initView()
15 | }
16 |
17 | override fun getLayoutId(): Int {
18 | return R.layout.activity_no_cover
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/paging/IBasePagingView.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.base
2 |
3 | interface IBasePagingView : IBaseView {
4 |
5 | fun showRecyclerViewEmpty()
6 |
7 | fun showRecyclerViewError(it: Throwable? = null)
8 |
9 | fun showRecyclerViewContent()
10 |
11 | fun showRecyclerViewLoading()
12 |
13 | fun beginRefresh()
14 |
15 | fun stopRefresh()
16 |
17 | fun stopLoadingdMore(finish: Boolean)
18 |
19 | fun setRecyclerViewData(datasource: ArrayList)
20 |
21 | fun isRefreshLoading():Boolean
22 |
23 |
24 | fun notifyDataChange()
25 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/game_item_date.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/list/ListPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.list
2 |
3 | import android.annotation.SuppressLint
4 | import com.czq.kotlin_arch.basePage.base.BasePagingPrensenterImpl
5 | import com.czq.kotlin_arch.paging.PagingStrategy
6 |
7 | open class ListPresenter(mView: ListContact.PagingListView) : BasePagingPrensenterImpl(mView),
8 | ListContact.PagingListPresenter {
9 |
10 |
11 | override fun getPagingStrategy(): PagingStrategy? {
12 | return null
13 | }
14 |
15 | @SuppressLint("CheckResult")
16 | override fun onLoadData(pagingStrategy: PagingStrategy?) {
17 |
18 | }
19 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/layout/common_loading_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_databinding.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/challenge_home_item_see_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/model/Banner.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.model
2 |
3 | class Banner {
4 |
5 | /**
6 | * id : 6
7 | * title : 使用指南·如何玩转记忆点
8 | * summary : 欢迎各位玩家来到记忆点社区!
9 | * 这里有一份记忆点新手引导教学将助你踏出在记忆点社区的第一步!
10 | * cover : https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180511/EjgNUMbmnhofvAc.png
11 | * isFirefly : false
12 | * relatedType : article
13 | * relatedId : 104044
14 | * feedId : 159237
15 | */
16 |
17 | var id: Int = 0
18 | var title: String? = null
19 | var summary: String? = null
20 | var cover: String? = null
21 | var isIsFirefly: Boolean = false
22 | var relatedType: String? = null
23 | var relatedId: Int = 0
24 | var feedId: Int = 0
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/czq/kotlinarch/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch
2 |
3 | import androidx.test.InstrumentationRegistry
4 | import androidx.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.czq.kotlinarch", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/list/ItemBinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.list
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.czq.kotlinarch.R
8 | import com.drakeet.multitype.ItemViewBinder
9 |
10 |
11 | class ItemBinder : ItemViewBinder- () {
12 |
13 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder =
14 | ViewHolder(inflater.inflate(R.layout.item, parent, false))
15 |
16 | override fun onBindViewHolder(holder: ViewHolder, itemData: Item) {
17 | }
18 |
19 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
20 |
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/list/ListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.list
2 |
3 | import com.czq.kotlin_arch.basePage.paging.BasePagingActivity
4 | import com.czq.kotlinarch.R
5 |
6 |
7 | class ListActivity : BasePagingActivity(),
8 | ListContact.PagingListView {
9 |
10 |
11 | override fun registItemBinder() {
12 | multiAdapter.register(ItemBinder())
13 |
14 | }
15 |
16 | override fun initView() {
17 | super.initView()
18 |
19 | }
20 |
21 |
22 |
23 |
24 | override fun getLayoutId(): Int {
25 | return R.layout.activity_list
26 | }
27 |
28 | override fun createPresenter(): ListContact.PagingListPresenter {
29 | return ListPresenter(this)
30 | }
31 |
32 |
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/fragment/CoverFragment.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.fragment
2 |
3 | import com.czq.kotlin_arch.basePage.base.BaseFragment
4 | import com.czq.kotlinarch.R
5 | import kotlinx.android.synthetic.main.fragment_cover.*
6 |
7 | class CoverFragment : BaseFragment(), CoverContact.CoverView {
8 |
9 |
10 | companion object {
11 | fun newInstance():CoverFragment{
12 | return CoverFragment()
13 | }
14 | }
15 |
16 | override fun createPresenter(): CoverContact.CoverPrensenter {
17 | return CoverPresenter(this)
18 | }
19 |
20 | override fun initView() {
21 | super.initView()
22 |
23 | }
24 |
25 | override fun getLayoutId(): Int {
26 | return R.layout.fragment_cover
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/cover/CoverFragment.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.cover
2 |
3 | import com.czq.kotlin_arch.basePage.base.BaseFragment
4 | import com.czq.kotlinarch.R
5 | import kotlinx.android.synthetic.main.fragment_cover.*
6 |
7 | class CoverFragment : BaseFragment(), CoverContact.CoverView {
8 |
9 |
10 | companion object {
11 | fun newInstance():CoverFragment{
12 | return CoverFragment()
13 | }
14 | }
15 |
16 | override fun createPresenter(): CoverContact.CoverPrensenter {
17 | return CoverPresenter(this)
18 | }
19 |
20 | override fun initView() {
21 | super.initView()
22 |
23 | }
24 |
25 | override fun getLayoutId(): Int {
26 | return R.layout.fragment_cover
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/common/util/ext/Activity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.common.util.ext
2 |
3 | import android.content.res.Resources
4 | import android.os.Build
5 | import android.view.View
6 | import androidx.appcompat.app.AppCompatActivity
7 |
8 | fun AppCompatActivity.hideBottom() {
9 | //隐藏虚拟按键,并且全屏
10 | if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
11 | val v = window.decorView
12 | v.systemUiVisibility = View.GONE
13 | } else if (Build.VERSION.SDK_INT >= 19) { //for new api versions.
14 | val decorView = window.decorView
15 | val uiOptions = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
16 | or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN)
17 | decorView.systemUiVisibility = uiOptions
18 | }
19 | }
--------------------------------------------------------------------------------
/kotlin_arch/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/src/main/res/layout/activity_feed_article.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/list/ListFragment.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.list
2 |
3 | import com.czq.kotlin_arch.basePage.paging.BasePagingFragment
4 | import com.czq.kotlinarch.R
5 |
6 | class ListFragment : BasePagingFragment(), ListContact.PagingListView {
7 |
8 | companion object {
9 | fun newInstance():ListFragment{
10 | return ListFragment()
11 | }
12 | }
13 |
14 | override fun registItemBinder() {
15 | multiAdapter.register(ItemBinder())
16 | }
17 |
18 | override fun createPresenter(): ListContact.PagingListPresenter {
19 | return ListPresenter(this)
20 | }
21 |
22 | override fun getLayoutId(): Int {
23 | return R.layout.fragment_paging_list
24 | }
25 |
26 | override fun initView() {
27 | super.initView()
28 | }
29 |
30 |
31 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/androidTest/java/com/czq/kotlin_arch/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch;
2 |
3 | import android.content.Context;
4 | import androidx.test.InstrumentationRegistry;
5 | import androidx.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.czq.kotlin_arch.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Kotlin code style for this project: "official" or "obsolete":
15 | kotlin.code.style=official
16 | android.useAndroidX=true
17 | android.enableJetifier=true
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_paging_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_paging_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
20 |
21 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/layout/fragment_base_paging.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
14 |
19 |
20 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/layout/activity_base_paging.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/remote/api/RemoteApi.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.remote.api
2 |
3 | import com.czq.kotlinarch.data.model.*
4 | import io.reactivex.Observable
5 | import retrofit2.http.GET
6 | import retrofit2.http.Headers
7 | import retrofit2.http.Path
8 | import retrofit2.http.Query
9 |
10 | interface RemoteApi {
11 |
12 | @Headers(
13 | "X-Requested-With: XMLHttpRequest"
14 | )
15 |
16 | @GET("user/{userId}")
17 | fun getUser(@Path("userId") userId: String, @Query("password") password: String): Observable>
18 |
19 |
20 | @GET("archServer/games")
21 | fun getGames(@Query("pageNum") pageNum: Int, @Query("pageSize") pageSize: Int): Observable>>
22 |
23 | @GET("archServer/feeds")
24 | fun getArticleFeeds(@Query("pageSize") pageSize: Int, @Query("offsetId") offsetId: String?, @Query("direction") direction: String)
25 | : Observable>>
26 |
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/itembinder/SeeMoreViewbinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.viewbinder
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.czq.kotlinarch.R
8 | import com.czq.kotlinarch.data.viewModel.ChallengeRecommandSeeMoreVm
9 | import com.drakeet.multitype.ItemViewBinder
10 |
11 |
12 | class SeeMoreViewbinder : ItemViewBinder() {
13 |
14 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): SeeMoreViewbinder.ViewHolder =
15 | ViewHolder(inflater.inflate(R.layout.challenge_home_item_see_more, parent, false))
16 |
17 | override fun onBindViewHolder(holder: SeeMoreViewbinder.ViewHolder, itemData: ChallengeRecommandSeeMoreVm) {
18 | }
19 |
20 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/fragment/CoverPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.fragment
2 |
3 | import com.czq.kotlinarch.data.remote.RemoteDataRepository
4 | import com.uber.autodispose.lifecycle.autoDisposable
5 | import io.reactivex.android.schedulers.AndroidSchedulers
6 | import io.reactivex.schedulers.Schedulers
7 |
8 | class CoverPresenter(var mView: CoverContact.CoverView) : CoverContact.CoverPrensenter {
9 | val mRemoteDataRepository: RemoteDataRepository by lazy {
10 | RemoteDataRepository()
11 | }
12 |
13 | override fun start() {
14 |
15 | mView.showLoading()
16 | mRemoteDataRepository.getUser()
17 | .subscribeOn(Schedulers.io())
18 | .observeOn(AndroidSchedulers.mainThread())
19 | .autoDisposable(mView.autoDispose())
20 | .subscribe({ it ->
21 | mView.showContent()
22 | }, {
23 | mView.showError(it)
24 | })
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_game_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/CoverActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import com.czq.kotlin_arch.basePage.base.BaseActivity
4 | import com.czq.kotlinarch.R
5 | import kotlinx.android.synthetic.main.activity_cover.*
6 |
7 | class CoverActivity : BaseActivity(), CoverContact.CoverView {
8 |
9 | override fun createPresenter(): CoverContact.CoverPrensenter {
10 | return CoverPresenter(this)
11 | }
12 |
13 | override fun initView() {
14 | super.initView()
15 |
16 | btnContent.setOnClickListener {
17 | showContent()
18 | }
19 | btnEmpty.setOnClickListener {
20 | showEmpty()
21 | }
22 | btnError.setOnClickListener {
23 | showError()
24 | }
25 | btnLoading.setOnClickListener {
26 | showLoading()
27 | }
28 | }
29 |
30 | override fun getLayoutId(): Int {
31 | return R.layout.activity_cover
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/template/cover/CoverActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.template.cover
2 |
3 | import com.czq.kotlin_arch.basePage.base.BaseActivity
4 | import com.czq.kotlinarch.R
5 | import kotlinx.android.synthetic.main.activity_cover.*
6 |
7 | class CoverActivity : BaseActivity(), CoverContact.CoverView {
8 |
9 | override fun createPresenter(): CoverContact.CoverPrensenter {
10 | return CoverPresenter(this)
11 | }
12 |
13 | override fun initView() {
14 | super.initView()
15 |
16 | btnContent.setOnClickListener {
17 | showContent()
18 | }
19 | btnEmpty.setOnClickListener {
20 | showEmpty()
21 | }
22 | btnError.setOnClickListener {
23 | showError()
24 | }
25 | btnLoading.setOnClickListener {
26 | showLoading()
27 | }
28 | }
29 |
30 | override fun getLayoutId(): Int {
31 | return R.layout.activity_cover
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/itembinder/GameDateViewbinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.viewbinder
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.czq.kotlinarch.R
8 | import com.czq.kotlinarch.data.viewModel.GameDate
9 | import com.drakeet.multitype.ItemViewBinder
10 | import kotlinx.android.synthetic.main.game_item_date.view.*
11 |
12 |
13 | class GameDateViewbinder : ItemViewBinder() {
14 |
15 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): GameDateViewbinder.ViewHolder =
16 | ViewHolder(inflater.inflate(R.layout.game_item_date, parent, false))
17 |
18 | override fun onBindViewHolder(holder: GameDateViewbinder.ViewHolder, itemData: GameDate) {
19 | holder.itemView.tvDate.text = itemData.date
20 | }
21 |
22 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/FeedArticleActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 |
4 | import android.annotation.SuppressLint
5 | import com.czq.kotlin_arch.basePage.paging.BasePagingActivity
6 | import com.czq.kotlinarch.R
7 | import com.czq.kotlinarch.example.itembinder.BannerItembinder
8 | import com.czq.kotlinarch.example.itembinder.FeedArticleItembinder
9 |
10 |
11 | class FeedArticleActivity : BasePagingActivity(), FeedArticleContract.IView {
12 |
13 | @SuppressLint("CheckResult")
14 | override fun registItemBinder() {
15 |
16 | multiAdapter.register(FeedArticleItembinder())
17 | multiAdapter.register(BannerItembinder())
18 | }
19 |
20 | override fun createPresenter(): FeedArticleContract.IPresenter {
21 | return FeedArticlePresenter(this)
22 | }
23 |
24 | override fun getLayoutId(): Int {
25 | return R.layout.activity_feed_article
26 | }
27 |
28 | override fun initView() {
29 | super.initView()
30 | }
31 |
32 |
33 |
34 |
35 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/res/layout/common_error_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
17 |
18 |
26 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/common/util/MockUtil.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.common.util
2 |
3 | import android.content.Context
4 | import com.alibaba.fastjson.JSON
5 | import com.alibaba.fastjson.TypeReference
6 |
7 | class MockUtil {
8 | companion object {
9 | inline fun getMockModelList(context: Context, fileName: String, clazz: Class ): List {
10 | val jsonStr = AssetUtil.getStringFromFile(context, fileName)
11 | return JSON.parseArray(jsonStr,clazz)
12 | }
13 |
14 | inline fun getMockModel(context: Context, fileName: String, clazz: Class ): T {
15 | val jsonStr = AssetUtil.getStringFromFile(context, fileName)
16 | return JSON.parseObject(jsonStr,clazz)
17 | }
18 |
19 | inline fun getMockModel(context: Context, fileName: String, typeReference: TypeReference ): T {
20 | val jsonStr = AssetUtil.getStringFromFile(context, fileName)
21 | return JSON.parseObject(jsonStr,typeReference)
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/common/util/ext/Density.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.common.util.ext
2 |
3 | import android.content.res.Resources
4 |
5 |
6 | /**
7 | * 正常编码中一般只会用到 [dp]/[sp] ;
8 | * 其中[dp]/[sp] 会根据系统分辨率将输入的dp/sp值转换为对应的px
9 | */
10 | val Float.dp: Float // [xxhdpi](360 -> 1080)
11 | get() = android.util.TypedValue.applyDimension(
12 | android.util.TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)
13 |
14 | val Int.dp: Int
15 | get() = android.util.TypedValue.applyDimension(
16 | android.util.TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()
17 |
18 |
19 | val Float.sp: Float // [xxhdpi](360 -> 1080)
20 | get() = android.util.TypedValue.applyDimension(
21 | android.util.TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics)
22 |
23 |
24 | val Int.sp: Int
25 | get() = android.util.TypedValue.applyDimension(
26 | android.util.TypedValue.COMPLEX_UNIT_SP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/DatabindingActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 |
4 | import androidx.databinding.DataBindingUtil
5 | import com.czq.kotlin_arch.basePage.base.BaseActivity
6 | import com.czq.kotlinarch.R
7 | import com.czq.kotlinarch.data.viewModel.DataBindingVM
8 |
9 |
10 | class DatabindingActivity : BaseActivity(), DatabindingContract.IView {
11 |
12 | var binding: com.czq.kotlinarch.databinding.ActivityDatabindingBinding? = null
13 | override fun createPresenter(): DatabindingContract.IPrensenter {
14 | return DatabindingPresenter(this)
15 | }
16 |
17 | override fun initView() {
18 | super.initView()
19 | title = "databindingTest"
20 | }
21 |
22 | override fun initContentView() {
23 | binding = DataBindingUtil.setContentView(this, getLayoutId())
24 | val vm = DataBindingVM()
25 | vm.txt = "databindingTest"
26 | binding?.vm = vm
27 |
28 | }
29 |
30 | override fun getLayoutId(): Int {
31 | return R.layout.activity_databinding
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 码农弟弟
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 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/paging/offset/OffsetStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.paging.offset
2 |
3 | import com.czq.kotlin_arch.paging.PagingStrategy
4 |
5 | class OffsetStrategy(var pageSize: Int = 20, var offsetIdKey: String) : PagingStrategy {
6 |
7 | var pageInfo: OffsetPageInfo = OffsetPageInfo()
8 |
9 |
10 | fun initData() {
11 | pageInfo = OffsetPageInfo()
12 | pageInfo.pageSize = pageSize
13 | pageInfo.type = "new"
14 | pageInfo.offsetId = null
15 | }
16 |
17 | override fun addPage(info: Any?) {
18 |
19 | pageInfo.type = "old"
20 | val arr = info as? List
21 | val obj = arr?.last()
22 | if (obj != null) {
23 | pageInfo.offsetId = obj::class.java.declaredFields.find {
24 | it.isAccessible = true
25 | it.name == offsetIdKey
26 | }?.get(obj)?.toString()
27 | }
28 | }
29 |
30 | override fun resetPage() {
31 | initData()
32 | }
33 |
34 | override fun getPageInfo(): Any {
35 | return pageInfo
36 | }
37 |
38 | override fun checkFinish(result: Any?, listSize: Int): Boolean {
39 | val arr = result as? List<*>
40 | return arr?.size == 0
41 | }
42 |
43 |
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/itembinder/GameViewbinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.viewbinder
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.load.MultiTransformation
9 | import com.bumptech.glide.load.resource.bitmap.CenterCrop
10 | import com.bumptech.glide.request.RequestOptions.bitmapTransform
11 | import com.czq.kotlinarch.R
12 | import com.czq.kotlinarch.data.model.Game
13 | import com.drakeet.multitype.ItemViewBinder
14 | import kotlinx.android.synthetic.main.game_item.view.*
15 |
16 |
17 | class GameViewbinder : ItemViewBinder() {
18 |
19 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): GameViewbinder.ViewHolder =
20 | ViewHolder(inflater.inflate(R.layout.game_item, parent, false))
21 |
22 | override fun onBindViewHolder(holder: GameViewbinder.ViewHolder, itemData: Game) {
23 | Glide.with(holder.itemView.context).load(itemData?.icon)
24 | .apply(bitmapTransform(MultiTransformation(CenterCrop())))
25 | .into(holder.itemView.ivIcon!!)
26 | holder.itemView.tvName.text = itemData.title
27 | }
28 |
29 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
30 |
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/paging/normal/NormalPagingStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.paging.normal
2 |
3 | import com.czq.kotlin_arch.paging.PagingStrategy
4 | import kotlin.reflect.full.memberProperties
5 | import kotlin.reflect.jvm.isAccessible
6 | import kotlin.reflect.jvm.javaField
7 |
8 | class NormalPagingStrategy constructor(var startPageNum: Int = 0, var pageSize: Int = 20) :
9 | PagingStrategy {
10 |
11 | var pageInfo: NormalPagingInfo = NormalPagingInfo()
12 |
13 |
14 | fun initData() {
15 | pageInfo = NormalPagingInfo()
16 | pageInfo.startPageNum = this.startPageNum
17 | pageInfo.pageNum = startPageNum;
18 | pageInfo.pageSize = pageSize
19 | }
20 |
21 |
22 | override fun addPage(info: Any?) {
23 | pageInfo.pageNum += 1
24 | }
25 |
26 | override fun resetPage() {
27 | initData()
28 | }
29 |
30 | override fun getPageInfo(): Any {
31 | return pageInfo
32 | }
33 |
34 | override fun checkFinish(result: Any?, listSize: Int): Boolean {
35 | if (result == null) {
36 | return true
37 | }
38 | val count = result::class.java.declaredFields.find {
39 | it.isAccessible = true
40 | it.name == "totalNum"
41 | }?.get(result)
42 | pageInfo.totalCount = count as? Int ?: 0
43 | return pageInfo.totalCount <= listSize
44 | }
45 |
46 |
47 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
29 |
30 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_normal_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
18 |
23 |
24 |
31 |
32 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/game_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
29 |
30 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/assets/banner.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 2,
4 | "title": "萤火虫新游戏上线更新(5月23日)",
5 | "summary": "本次活动基于记忆点APP进行,所有成为【萤火虫】的玩家都可以申请到多款热门游戏的免费体验。申请萤火虫玩家需要在记忆点中达成探索者等级2级,具体流程请看 如何在记忆点参与萤火虫活动。",
6 | "cover": "https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180517/HvhHFJbmnwslhkl.jpg",
7 | "isFirefly": false,
8 | "relatedType": "article",
9 | "relatedId": 116051,
10 | "feedId": 199211
11 | },
12 | {
13 | "id": 3,
14 | "title": "发现狗狗乐园",
15 | "summary": "这是老年人叽叽之前玩的一个老年人游戏。[因为这里暂时没有这个游戏就点了一个跟它也是很像的同一个公司出的游戏]游戏里面的挖掘点数、徽章、钱,前期是特别缺的!...",
16 | "cover": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180323/IQgMtmbmjixApdj.png",
17 | "isFirefly": true,
18 | "relatedType": "game",
19 | "relatedId": 6966,
20 | "feedId": 17390
21 | },
22 | {
23 | "id": 6,
24 | "title": "使用指南·如何玩转记忆点",
25 | "summary": "欢迎各位玩家来到记忆点社区!\r\n这里有一份记忆点新手引导教学将助你踏出在记忆点社区的第一步!",
26 | "cover": "https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180511/EjgNUMbmnhofvAc.png",
27 | "isFirefly": false,
28 | "relatedType": "article",
29 | "relatedId": 104044,
30 | "feedId": 159237
31 | },
32 | {
33 | "id": 3,
34 | "title": "如何在记忆点参与萤火虫活动",
35 | "summary": "恭喜你!现在你可以作为首批用户参与到萤火虫专属 APP 中参与参与大量福利活动了!\r\n在这个新的平台中,萤火虫将提供更多的游戏以供大家选择!",
36 | "cover": "https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180403/KkRfLTbmkfceuyi.jpg",
37 | "isFirefly": false,
38 | "relatedType": "article",
39 | "relatedId": 6966,
40 | "feedId": 17390
41 | }
42 | ]
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_cover.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
19 |
20 |
25 |
26 |
31 |
32 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/common/util/AssetUtil.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.common.util
2 |
3 | import android.content.Context
4 | import java.io.BufferedReader
5 | import java.io.IOException
6 | import java.io.InputStream
7 | import java.io.InputStreamReader
8 |
9 |
10 | class AssetUtil {
11 | companion object {
12 | fun getStringFromFile(context: Context, fileName: String): String? {
13 | val content = StringBuilder()
14 | var bufferedReader: BufferedReader? = null
15 | var inputStream: InputStream? = null
16 | val assetManager = context.getAssets()
17 | try {
18 | inputStream = assetManager.open(fileName)
19 | bufferedReader = BufferedReader(InputStreamReader(inputStream))
20 | var line: String
21 | while (true) {
22 | line = bufferedReader.readLine() ?: break
23 | content.append(line)
24 | }
25 | bufferedReader!!.close()
26 | inputStream!!.close()
27 | return content.toString()
28 | } catch (e: IOException) {
29 | e.printStackTrace()
30 | } finally {
31 | try {
32 | if (bufferedReader != null) {
33 | bufferedReader!!.close()
34 | }
35 | if (inputStream != null) {
36 | inputStream!!.close()
37 | }
38 | } catch (e: IOException) {
39 | e.printStackTrace()
40 | }
41 |
42 | }
43 | return null
44 | }
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/itembinder/ChallengeViewbinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.viewbinder
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.load.MultiTransformation
9 | import com.bumptech.glide.load.resource.bitmap.CenterCrop
10 | import com.bumptech.glide.request.RequestOptions.bitmapTransform
11 | import com.czq.kotlinarch.R
12 | import com.czq.kotlinarch.data.viewModel.ChallengeRecommandItemVm
13 | import com.drakeet.multitype.ItemViewBinder
14 | import kotlinx.android.synthetic.main.challenge_home_item_challenge.view.*
15 |
16 |
17 | class ChallengeViewbinder : ItemViewBinder() {
18 |
19 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ChallengeViewbinder.ViewHolder =
20 | ViewHolder(inflater.inflate(R.layout.challenge_home_item_challenge, parent, false))
21 |
22 | override fun onBindViewHolder(holder: ChallengeViewbinder.ViewHolder, itemData: ChallengeRecommandItemVm) {
23 | holder.itemView.tvScore.text = "${itemData?.candidatePoint}积分"
24 | holder.itemView.tvTitle.text = itemData?.title
25 | holder.itemView.tvCount.text = "${itemData?.candidateCount}条有料 ${itemData?.takeOnCount}人参与"
26 | Glide.with(holder.itemView.context).load(itemData?.cover)
27 | .apply(bitmapTransform(MultiTransformation(CenterCrop())))
28 | .into(holder.itemView.ivCover!!)
29 |
30 | }
31 |
32 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
33 |
34 |
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch
2 |
3 | import android.content.Intent
4 | import androidx.appcompat.app.AppCompatActivity
5 | import android.os.Bundle
6 | import com.czq.kotlinarch.example.*
7 | import kotlinx.android.synthetic.main.activity_main.*
8 |
9 | class MainActivity : AppCompatActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContentView(R.layout.activity_main)
13 | btnBasePageNoCover.setOnClickListener {
14 | startActivity(Intent(this@MainActivity,NoCoverActivity::class.java))
15 | }
16 |
17 | btnBasePage.setOnClickListener {
18 | startActivity(Intent(this@MainActivity,CoverActivity::class.java))
19 | }
20 | btnPagingList.setOnClickListener {
21 | startActivity(Intent(this@MainActivity, PagingListActivity::class.java))
22 | }
23 |
24 | btnFragmentActivity.setOnClickListener {
25 | startActivity(Intent(this@MainActivity, NormalFragmentActivity::class.java))
26 | }
27 |
28 | btnFragmentBaseActivity.setOnClickListener {
29 | startActivity(Intent(this@MainActivity, CoverFragmentActivity::class.java))
30 | }
31 |
32 | btnGameList.setOnClickListener {
33 | startActivity(Intent(this@MainActivity, GameListActivity::class.java))
34 | }
35 |
36 | btnFeedArticle.setOnClickListener {
37 | startActivity(Intent(this@MainActivity, FeedArticleActivity::class.java))
38 | }
39 |
40 | btnDatabinding.setOnClickListener {
41 | startActivity(Intent(this@MainActivity, DatabindingActivity::class.java))
42 |
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/itembinder/CircleViewbinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.viewbinder
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.load.MultiTransformation
9 | import com.bumptech.glide.load.resource.bitmap.CenterCrop
10 | import com.bumptech.glide.request.RequestOptions.bitmapTransform
11 | import com.czq.kotlinarch.R
12 | import com.czq.kotlinarch.data.viewModel.ChallengeRecomandCircleVm
13 | import com.drakeet.multitype.ItemViewBinder
14 | import kotlinx.android.synthetic.main.challenge_home_item_circle.view.*
15 |
16 | class CircleViewbinder : ItemViewBinder() {
17 |
18 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): CircleViewbinder.ViewHolder =
19 | ViewHolder(inflater.inflate(R.layout.challenge_home_item_circle, parent, false))
20 |
21 | override fun onBindViewHolder(holder: CircleViewbinder.ViewHolder, itemData: ChallengeRecomandCircleVm) {
22 | holder.itemView.tvSubscribe.visibility = if (itemData?.hasSubscribed ?: false) {
23 | View.VISIBLE
24 | } else {
25 | View.INVISIBLE
26 | }
27 | holder.itemView.tvName.text = itemData?.title
28 | holder.itemView.tvCount.text = "共${itemData?.subscribedCount}个圈友,${itemData?.challengeCount}个挑战"
29 | Glide.with(holder.itemView.context).load(itemData?.icon)
30 | .apply(bitmapTransform(MultiTransformation(CenterCrop())))
31 | .into(holder.itemView.ivIcon!!)
32 |
33 | }
34 |
35 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
36 |
37 |
38 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/paging/BasePagingPrensenterImpl.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.base
2 |
3 | import com.czq.kotlin_arch.paging.PagingStrategy
4 |
5 | abstract class BasePagingPrensenterImpl(open val mView: IBasePagingView) : IBasePrensenter {
6 |
7 |
8 | val datasource = arrayListOf()
9 | val pagingList = arrayListOf()
10 |
11 | var mPagingStrategy: PagingStrategy? = null
12 |
13 |
14 | override fun start() {
15 | mPagingStrategy = getPagingStrategy()
16 | mView.beginRefresh()
17 | }
18 |
19 | abstract fun getPagingStrategy(): PagingStrategy?
20 |
21 | abstract fun onLoadData(pagingStrategy: PagingStrategy?)
22 |
23 | fun resetPage() {
24 | mPagingStrategy?.resetPage()
25 | }
26 |
27 | fun loadData() {
28 | onLoadData(mPagingStrategy)
29 | }
30 |
31 |
32 | fun loadFail(it: Throwable) {
33 | if (mView.isRefreshLoading()) {
34 | mView.stopRefresh()
35 | }
36 |
37 | if (mView.isRefreshLoading()) {
38 | mView.stopLoadingdMore(false)
39 | }
40 |
41 | if (datasource.isEmpty()) {
42 | mView?.showRecyclerViewError(it)
43 | }
44 | }
45 |
46 | fun loadSuccess(resultData: Any? = null) {
47 | val isFinish = mPagingStrategy?.checkFinish(resultData, pagingList.size) ?: true
48 | if (mView.isRefreshLoading()) {
49 | mView.stopRefresh()
50 | }
51 | mView.stopLoadingdMore(isFinish)
52 | mView?.setRecyclerViewData(datasource)
53 | if (datasource.isEmpty()) {
54 | mView?.showRecyclerViewEmpty()
55 | } else {
56 | mView?.showRecyclerViewContent()
57 | }
58 | mPagingStrategy?.addPage(resultData)
59 | }
60 |
61 |
62 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # kotlinArch[](https://jitpack.io/#manondidi/kotlinArch)
2 | kotlin开发脚手架
3 |
4 | > 首先这是个一个mvp框架
5 | > 我帮你做好了mvp的基类
6 | > 并做好相关的模板, 一键生成mvp 三个类 activity fragment各一套
7 | > 并且 我封装了一个coverframelayout 作为一个framelayout 为所有view的root节点
8 | > 我在内部写好了三个view 并处理好他们的逻辑关系 emptyview errorview loadingview
9 | > 并且 这些coverview 的样式 支持三种配置方式
10 | > application中统一配置
11 | > 用同名xml覆盖 我的默认xml名 全局替换
12 | > 在oncreate的时候 手动传入 coverframe.xxxview 的view
13 | > 并且 你也可以使用我的mvp框架, 而不在root节点嵌套coverframelayout,因为我是用了kotlin的 ?? 操作,预先做了判空,也不会崩溃 逻辑照样走,并且用uber的 > autodisposed框架作为生命周期观察,方便使用rxjava rxkotlin时destory时取消订阅
14 | > 另外我还做了一个 关于 recyclerView的activity 和fragment 分别继承 上面的基类,
15 | > 除了具有上述的功能外,还具有 几个功能 recyclerView item解耦, 只要注册好 类和item的关系,然后传入对应的model对象,就会自动展示,不需要维护item的类别,
16 | > 还有下拉刷新套件 ,也可以在application中统一配置或者在具体页面中单独配置并且在presenter中做好他们的生命周期,还有分页策略
17 | > 分页是基于策略模式的, 我把分页规则的计算抽象成策略, 传入不同的策略对象 会有不同的计算方式
18 | > 目前支持 pagesize 和offsetid两种,开放封闭原则
19 | > 并且做了一个模板 一键生成 对应的itembinder
20 |
21 |
22 | 开发模板androidstudio 4.1后不可使用
23 | ~~开发模板,可以一键生成mvp类,并自动写好相应通用代码 :https://github.com/manondidi/kotlinArchTemplate~~
24 |
25 |
26 | ### 混淆请参考demo工程的配法
27 |
28 | 安装
29 |
30 | ```
31 |
32 | allprojects {
33 | repositories {
34 | maven { url "https://jitpack.io" }
35 | }
36 | }
37 |
38 | ```
39 | ```
40 |
41 | implementation 'com.github.manondidi:kotlinArch:latest-version'
42 | ```
43 |
44 |
45 |
46 | ##Todo
47 | - [x] rxkotlin
48 |
49 | - [x] rxbus
50 |
51 | - [x] 页面destory rx自动取消
52 |
53 | - [x] mvp
54 |
55 | - [ ] ~~databinding或viewmodel~~(业务层自己实现)
56 |
57 | - [x] 策略模式的自动分页
58 |
59 | - [x] 各种cover封装
60 |
61 | - [x] 列表数据的解耦 itembinder
62 |
63 | - [x] mock管理
64 |
65 | - [x] 开发模板(自动生成代码)
66 |
67 | - [x] 详细案例
68 |
69 |
70 | ......
71 |
72 |
73 |
74 | 
75 |
76 | 
77 |
78 | 
79 |
80 | 
81 |
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/NormalFragmentActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import android.os.Bundle
4 | import androidx.appcompat.app.AppCompatActivity
5 | import androidx.fragment.app.Fragment
6 | import com.czq.kotlinarch.R
7 | import com.czq.kotlinarch.example.fragment.CoverFragment
8 | import com.czq.kotlinarch.example.fragment.PagingListFragment
9 | import kotlinx.android.synthetic.main.activity_normal_fragment.*
10 |
11 | class NormalFragmentActivity : AppCompatActivity() {
12 |
13 | var currentFragment: Fragment? = null
14 |
15 | val fragment1: CoverFragment by lazy {
16 | CoverFragment.newInstance()
17 | }
18 | val fragment2: PagingListFragment by lazy {
19 | PagingListFragment.newInstance()
20 | }
21 |
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | setContentView(R.layout.activity_normal_fragment)
26 |
27 | showFragment(fragment1)
28 |
29 | btn1.setOnClickListener {
30 | showFragment(fragment1)
31 | }
32 |
33 | btn2.setOnClickListener {
34 | showFragment(fragment2)
35 | }
36 | }
37 |
38 | private fun showFragment(targetFragment: Fragment) {
39 | val transaction = supportFragmentManager
40 | .beginTransaction()
41 | if (!targetFragment.isAdded) {
42 | if (currentFragment != null) {
43 | transaction.hide(currentFragment!!)
44 | }
45 | transaction.add(R.id.flContainer, targetFragment)
46 | .commit()
47 | } else {
48 | if (currentFragment != null) {
49 | transaction.hide(currentFragment!!)
50 | }
51 | transaction
52 | .show(targetFragment)
53 | .commit()
54 | }
55 | currentFragment = targetFragment
56 | }
57 |
58 |
59 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_cover.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
21 |
22 |
28 |
29 |
35 |
36 |
42 |
43 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/remote/MockDataRepository.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.remote
2 |
3 | import com.alibaba.fastjson.TypeReference
4 | import com.czq.kotlin_arch.common.util.MockUtil
5 | import com.czq.kotlinarch.App
6 | import com.czq.kotlinarch.data.model.*
7 | import io.reactivex.Observable
8 | import java.util.concurrent.TimeUnit
9 |
10 | class MockDataRepository() {
11 |
12 | fun getChallengeRecommond(): Observable> {
13 | return Observable.just(MockUtil.getMockModel(App.application, "challenge_recommond.json",
14 | object : TypeReference>() {}
15 | )).delay(1, TimeUnit.SECONDS)
16 | }
17 |
18 | fun getUser(): Observable {
19 | return Observable.just(
20 | MockUtil.getMockModel(
21 | App.application,
22 | "get_user.json",
23 | User::class.java
24 | )
25 | )
26 | .delay(1, TimeUnit.SECONDS)
27 | }
28 |
29 | fun getBanners(): Observable
> {
30 | return Observable.just(
31 | MockUtil.getMockModelList(
32 | App.application,
33 | "banner.json",
34 | Banner::class.java
35 | )
36 | )
37 | .delay(1, TimeUnit.SECONDS)
38 | }
39 |
40 | fun getGames(): Observable> {
41 | return Observable.just(
42 | MockUtil.getMockModel(
43 | App.application,
44 | "game.json",
45 | object : TypeReference>() {})
46 | )
47 | .delay(1, TimeUnit.SECONDS)
48 | }
49 |
50 | fun getFeeds(): Observable> {
51 | return Observable.just(
52 | MockUtil.getMockModel(
53 | App.application,
54 | "feeds.json",
55 | object : TypeReference>() {})
56 | )
57 | .delay(1, TimeUnit.SECONDS)
58 | }
59 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_cover_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
25 |
26 |
27 |
32 |
33 |
40 |
41 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/CoverFragmentActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import androidx.fragment.app.Fragment
4 | import com.czq.kotlin_arch.basePage.base.BaseActivity
5 | import com.czq.kotlinarch.R
6 | import com.czq.kotlinarch.example.fragment.CoverFragment
7 | import com.czq.kotlinarch.example.fragment.PagingListFragment
8 | import kotlinx.android.synthetic.main.activity_normal_fragment.*
9 |
10 |
11 | class CoverFragmentActivity : BaseActivity(), CoverContact.CoverView {
12 |
13 | var currentFragment: Fragment? = null
14 |
15 | val fragment1: CoverFragment by lazy {
16 | CoverFragment.newInstance()
17 | }
18 | val fragment2: PagingListFragment by lazy {
19 | PagingListFragment.newInstance()
20 | }
21 |
22 | override fun createPresenter(): CoverContact.CoverPrensenter {
23 | return CoverPresenter(this)
24 | }
25 |
26 | override fun initView() {
27 | super.initView()
28 | showFragment(fragment1)
29 |
30 | btn1.setOnClickListener {
31 | showFragment(fragment1)
32 | }
33 |
34 | btn2.setOnClickListener {
35 | showFragment(fragment2)
36 | }
37 | }
38 |
39 | private fun showFragment(targetFragment: Fragment) {
40 | val transaction = supportFragmentManager
41 | .beginTransaction()
42 | if (!targetFragment.isAdded) {
43 | if (currentFragment != null) {
44 | transaction.hide(currentFragment!!)
45 | }
46 | transaction.add(R.id.flContainer, targetFragment)
47 | .commit()
48 | } else {
49 | if (currentFragment != null) {
50 | transaction.hide(currentFragment!!)
51 | }
52 | transaction
53 | .show(targetFragment)
54 | .commit()
55 | }
56 | currentFragment = targetFragment
57 | }
58 |
59 | override fun getLayoutId(): Int {
60 | return R.layout.activity_cover_fragment
61 | }
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/PagingListPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import android.annotation.SuppressLint
4 | import com.czq.kotlin_arch.basePage.base.BasePagingPrensenterImpl
5 | import com.czq.kotlin_arch.paging.PagingStrategy
6 | import com.czq.kotlin_arch.paging.normal.NormalPagingInfo
7 | import com.czq.kotlin_arch.paging.normal.NormalPagingStrategy
8 | import com.czq.kotlinarch.data.converter.ChallengeRecomondCoverter
9 | import com.czq.kotlinarch.data.remote.RemoteDataRepository
10 | import com.uber.autodispose.lifecycle.autoDisposable
11 | import io.reactivex.android.schedulers.AndroidSchedulers
12 | import io.reactivex.schedulers.Schedulers
13 |
14 | open class PagingListPresenter(override val mView: PagingListContact.PagingListView) : BasePagingPrensenterImpl(mView),
15 | PagingListContact.PagingListPresenter {
16 |
17 | val mRemoteDataRepository: RemoteDataRepository by lazy {
18 | RemoteDataRepository()
19 | }
20 |
21 | override fun getPagingStrategy(): PagingStrategy? {
22 | return NormalPagingStrategy()
23 | }
24 |
25 | @SuppressLint("CheckResult")
26 | override fun onLoadData(pagingStrategy: PagingStrategy?) {
27 | val pageInfo = pagingStrategy!!.getPageInfo() as NormalPagingInfo
28 | mRemoteDataRepository.getChallengeRecommond(pageInfo.pageNum, pageInfo.pageSize)
29 | .subscribeOn(Schedulers.io())
30 | .observeOn(AndroidSchedulers.mainThread())
31 | .autoDisposable(mView.autoDispose())
32 | .subscribe({ it ->
33 | if (pageInfo.isFirstPage()) {
34 | datasource.clear()
35 | pagingList.clear()
36 | }
37 | pagingList.addAll(it?.listData?: arrayListOf())//用于计算分页的数据
38 | it.listData?.forEach {
39 | datasource.addAll(ChallengeRecomondCoverter.convert(it))//真实显示在列表上的数据
40 | }
41 | loadSuccess(it)
42 | }, {
43 | loadFail(it)
44 | })
45 | }
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/fragment/PagingListPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.fragment
2 |
3 | import android.annotation.SuppressLint
4 | import com.czq.kotlin_arch.basePage.base.BasePagingPrensenterImpl
5 | import com.czq.kotlin_arch.paging.PagingStrategy
6 | import com.czq.kotlin_arch.paging.normal.NormalPagingInfo
7 | import com.czq.kotlin_arch.paging.normal.NormalPagingStrategy
8 | import com.czq.kotlinarch.data.converter.ChallengeRecomondCoverter
9 | import com.czq.kotlinarch.data.remote.RemoteDataRepository
10 | import com.uber.autodispose.lifecycle.autoDisposable
11 | import io.reactivex.android.schedulers.AndroidSchedulers
12 | import io.reactivex.schedulers.Schedulers
13 |
14 | open class PagingListPresenter(mView: PagingListContact.PagingListView) : BasePagingPrensenterImpl(mView),
15 | PagingListContact.PagingListPresenter {
16 |
17 | val mRemoteDataRepository: RemoteDataRepository by lazy {
18 | RemoteDataRepository()
19 | }
20 |
21 | override fun getPagingStrategy(): PagingStrategy? {
22 | return NormalPagingStrategy()
23 | }
24 |
25 | @SuppressLint("CheckResult")
26 | override fun onLoadData(pagingStrategy: PagingStrategy?) {
27 | val pageInfo = pagingStrategy!!.getPageInfo() as NormalPagingInfo
28 | mRemoteDataRepository.getChallengeRecommond(pageInfo.pageNum, pageInfo.pageSize)
29 | .subscribeOn(Schedulers.io())
30 | .observeOn(AndroidSchedulers.mainThread())
31 | .autoDisposable(mView.autoDispose())
32 | .subscribe({ it ->
33 | if (pageInfo.isFirstPage()) {
34 | datasource.clear()
35 | pagingList.clear()
36 | }
37 | pagingList.addAll(it?.listData?: arrayListOf())//用于计算分页的数据
38 | it.listData?.forEach {
39 | datasource.addAll(ChallengeRecomondCoverter.convert(it))//真实显示在列表上的数据
40 | }
41 | loadSuccess(it)
42 | }, {
43 | loadFail(it)
44 | })
45 | }
46 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/recyclerview_item_banner.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
29 |
30 |
36 |
37 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/kotlin_arch/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | apply plugin: 'com.github.dcendents.android-maven'
6 | group='com.github.manondidi'
7 |
8 | android {
9 | compileSdkVersion 30
10 | defaultConfig {
11 | minSdkVersion 19
12 | targetSdkVersion 30
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 |
18 | }
19 |
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(dir: 'libs', include: ['*.jar'])
24 |
25 | api 'androidx.appcompat:appcompat:1.2.0-alpha01'
26 | api 'androidx.constraintlayout:constraintlayout:1.1.3'
27 | api 'androidx.core:core-ktx:1.1.0'
28 |
29 | api 'com.drakeet.multitype:multitype:4.1.1'
30 | //下拉刷新
31 |
32 | api 'io.github.scwang90:refresh-layout-kernel:2.0.5' //核心必须依赖
33 | api 'io.github.scwang90:refresh-header-classics:2.0.5' //经典刷新头
34 | api 'io.github.scwang90:refresh-header-radar:2.0.5' //雷达刷新头
35 | api 'io.github.scwang90:refresh-header-falsify:2.0.5' //虚拟刷新头
36 | api 'io.github.scwang90:refresh-header-material:2.0.5' //谷歌刷新头
37 | api 'io.github.scwang90:refresh-header-two-level:2.0.5' //二级刷新头
38 | api 'io.github.scwang90:refresh-footer-ball:2.0.5' //球脉冲加载
39 | api 'io.github.scwang90:refresh-footer-classics:2.0.5' //经典加载
40 |
41 |
42 | api 'io.reactivex.rxjava2:rxandroid:2.1.1'
43 | api 'io.reactivex.rxjava2:rxjava:2.2.13'
44 | api 'io.reactivex.rxjava2:rxkotlin:2.3.0'
45 |
46 | api 'com.uber.autodispose:autodispose-android-archcomponents-ktx:1.2.0'
47 | api 'com.uber.autodispose:autodispose:1.4.0'
48 | api 'com.uber.autodispose:autodispose-lifecycle-ktx:1.2.0'
49 | api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
50 |
51 | api 'com.alibaba:fastjson:1.2.62'
52 |
53 | api 'com.orhanobut:logger:2.2.0'
54 | api 'com.hwangjr.rxbus:rxbus:2.0.1'
55 |
56 | api 'androidx.recyclerview:recyclerview:1.1.0'
57 | api 'com.hjq:toast:8.0'
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/model/ChallengeRecomand.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.model
2 |
3 | class ChallengeRecomand {
4 |
5 | /**
6 | * id : 2
7 | * title : 主机单机
8 | * subscribedCount : 0
9 | * challengeCount : 7
10 | * icon : http://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180907/IvuyzvbmwzwCgbg.jpg!a-6-240x240.jpg
11 | * banner : http://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180907/dSminxbmwzxpuak.png!a-3-480x.jpg
12 | * hasSubscribed : true
13 | * challenges : [{"id":1239,"title":"这不是我想要的结局,那些令人失望的游戏结局","candidateCount":0,"takeOnCount":0,"candidatePoint":0,"cover":"http://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20181017/NQRCljbmAabbkij.jpg!a-4-x640.jpg"},{"id":1237,"title":"人见人爱花见花开的游戏角色","candidateCount":0,"takeOnCount":0,"candidatePoint":0,"cover":"http://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20181017/YuYuFBbmAaauzBz.jpg!a-4-x640.jpg"},{"id":1236,"title":"出淤泥而不染,这些游戏就是这么的奇葩","candidateCount":0,"takeOnCount":0,"candidatePoint":0,"cover":"http://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20181017/ntlYTQbmAaafylu.jpg!a-4-x640.jpg"},{"id":1235,"title":"那些令你摔键盘的BOSS们","candidateCount":0,"takeOnCount":0,"candidatePoint":0,"cover":"http://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20181017/tQxJoUbmAaabnFF.jpg!a-4-x640.jpg"}]
14 | */
15 |
16 | var id: String? = null
17 | var title: String? = null
18 | var subscribedCount = 0
19 | var challengeCount = 0
20 | var icon: String? = null
21 | var banner: String? = null
22 | var hasSubscribed = false
23 | var challenges: List? = null
24 |
25 | class ChallengesBean {
26 | /**
27 | * id : 1239
28 | * title : 这不是我想要的结局,那些令人失望的游戏结局
29 | * candidateCount : 0
30 | * takeOnCount : 0
31 | * candidatePoint : 0
32 | * cover : http://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20181017/NQRCljbmAabbkij.jpg!a-4-x640.jpg
33 | */
34 |
35 | var id: String? = null
36 | var title: String? = null
37 | var candidateCount = 0
38 | var takeOnCount = 0
39 | var candidatePoint = 0
40 | var cover: String? = null
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/itembinder/BannerItembinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.itembinder
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.czq.kotlinarch.R
8 | import com.czq.kotlinarch.data.viewModel.BannerList
9 | import com.czq.kotlinarch.example.component.GalleryLayoutManager
10 | import com.drakeet.multitype.ItemViewBinder
11 | import com.drakeet.multitype.MultiTypeAdapter
12 | import kotlinx.android.synthetic.main.recyclerview_item_banner.view.*
13 |
14 |
15 | class BannerItembinder : ItemViewBinder() {
16 |
17 |
18 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): BannerItembinder.ViewHolder =
19 | ViewHolder(inflater.inflate(R.layout.recyclerview_item_banner, parent, false))
20 |
21 | override fun onBindViewHolder(holder: BannerItembinder.ViewHolder, itemData: BannerList) {
22 |
23 | holder.adapter.items = itemData?.banners!!
24 | holder.adapter.notifyDataSetChanged()
25 | }
26 |
27 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
28 | val adapter by lazy {
29 | val adp = MultiTypeAdapter()
30 | adp.register(BannerContentItembinder())
31 | adp
32 | }
33 |
34 | init {
35 | val layoutManager = GalleryLayoutManager(GalleryLayoutManager.HORIZONTAL)
36 | layoutManager.attach(itemView.banner)
37 | layoutManager.setItemTransformer(ScaleTransformer())
38 | itemView.banner.setAdapter(adapter)
39 | }
40 | }
41 |
42 | class ScaleTransformer : GalleryLayoutManager.ItemTransformer {
43 |
44 | override fun transformItem(layoutManager: GalleryLayoutManager, item: View, fraction: Float) {
45 | item.pivotX = item.width / 2f
46 | item.pivotY = item.height / 2.0f
47 | val scale = 1 - 0.2f * Math.abs(fraction)
48 | item.scaleX = scale
49 | item.scaleY = scale
50 | }
51 |
52 |
53 | }
54 |
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/converter/ChallengeRecomondCoverter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.converter
2 |
3 |
4 | import com.czq.kotlinarch.data.model.ChallengeRecomand
5 | import com.czq.kotlinarch.data.viewModel.ChallengeRecomandCircleVm
6 | import com.czq.kotlinarch.data.viewModel.ChallengeRecommandItemVm
7 | import com.czq.kotlinarch.data.viewModel.ChallengeRecommandSeeMoreVm
8 |
9 | import java.util.ArrayList
10 |
11 | object ChallengeRecomondCoverter {
12 |
13 | fun convert(challengeRecomand: ChallengeRecomand?): List {
14 | val list = arrayListOf()
15 | if (challengeRecomand != null && !challengeRecomand.challenges!!.isEmpty()) {
16 | val circleVm = ChallengeRecomandCircleVm()
17 | circleVm.id = challengeRecomand.id
18 | circleVm.title = challengeRecomand.title
19 | circleVm.challengeCount = challengeRecomand.challengeCount
20 | circleVm.subscribedCount = challengeRecomand.subscribedCount
21 | circleVm.hasSubscribed = challengeRecomand.hasSubscribed
22 | circleVm.icon = challengeRecomand.icon
23 | list.add(circleVm)
24 | var i = 0
25 | while (i < challengeRecomand.challenges!!.size && i < 4) {
26 | val challengesBean = challengeRecomand.challenges!![i]
27 | val itemVm = ChallengeRecommandItemVm()
28 | itemVm.index = i
29 | itemVm.id = challengesBean.id
30 | itemVm.cover = challengesBean.cover
31 | itemVm.takeOnCount = challengesBean.takeOnCount
32 | itemVm.candidatePoint = challengesBean.candidatePoint
33 | itemVm.candidateCount = challengesBean.candidateCount
34 | itemVm.title = challengesBean.title
35 | list.add(itemVm)
36 | i++
37 | }
38 | if (challengeRecomand.challenges!!.size > 4) {
39 | val seeMoreVm = ChallengeRecommandSeeMoreVm()
40 | seeMoreVm.id = challengeRecomand.id
41 | list.add(seeMoreVm)
42 | }
43 | }
44 | return list
45 | }
46 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/base_dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 24dp
5 |
6 | 68dp
7 |
8 | 43dp
9 |
10 | 15dp
11 |
12 | 17dp
13 | 16dp
14 | 13dp
15 | 10dp
16 |
17 |
18 | 300dp
19 |
20 | 48dp
21 | 15dp
22 | 17dp
23 | 16dp
24 | 16dp
25 |
26 |
27 | 30dp
28 | 13dp
29 | 40dp
30 | 3dp
31 | 10dp
32 | 16dp
33 | 15dp
34 |
35 |
36 | 68dp
37 |
38 | 24dp
39 |
40 |
41 | 6dp
42 |
43 |
44 | 40dp
45 |
46 | 14dp
47 |
48 |
49 | 300dp
50 |
51 |
52 | 8dp
53 |
54 |
55 | 40dp
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/GameListPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import android.annotation.SuppressLint
4 | import com.czq.kotlin_arch.basePage.base.BasePagingPrensenterImpl
5 | import com.czq.kotlin_arch.paging.PagingStrategy
6 | import com.czq.kotlin_arch.paging.normal.NormalPagingInfo
7 | import com.czq.kotlin_arch.paging.normal.NormalPagingStrategy
8 | import com.czq.kotlinarch.data.remote.RemoteDataRepository
9 | import com.czq.kotlinarch.data.viewModel.GameDate
10 | import com.uber.autodispose.lifecycle.autoDisposable
11 | import io.reactivex.android.schedulers.AndroidSchedulers
12 | import io.reactivex.schedulers.Schedulers
13 |
14 | open class GameListPresenter(override val mView: GameListContact.PagingListView) :
15 | BasePagingPrensenterImpl(mView),
16 | GameListContact.PagingListPresenter {
17 | var day = 30
18 |
19 | val mRemoteDataRepository: RemoteDataRepository by lazy {
20 | RemoteDataRepository()
21 | }
22 |
23 | override fun getPagingStrategy(): PagingStrategy? {
24 | return NormalPagingStrategy()
25 | }
26 |
27 | @SuppressLint("CheckResult")
28 | override fun onLoadData(pagingStrategy: PagingStrategy?) {
29 | val pageInfo = pagingStrategy!!.getPageInfo() as NormalPagingInfo
30 | mRemoteDataRepository.getGames(pageInfo.pageNum, pageInfo.pageSize)
31 | .subscribeOn(Schedulers.io())
32 | .observeOn(AndroidSchedulers.mainThread())
33 | .autoDisposable(mView.autoDispose())
34 | .subscribe({ it ->
35 | if (pageInfo.isFirstPage()) {
36 | datasource.clear()
37 | pagingList.clear()
38 | val gd = GameDate()
39 | gd.date = "今日"
40 | datasource.add(gd)
41 | } else {
42 | val gd = GameDate()
43 | gd.date = "2018-12-${day--}"
44 | datasource.add(gd)
45 | }
46 | pagingList.addAll(it?.listData ?: arrayListOf())//用于计算分页的数据
47 | datasource.addAll(it?.listData ?: arrayListOf())
48 | loadSuccess(it)
49 | }, {
50 | loadFail(it)
51 | })
52 | }
53 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
16 |
22 |
23 |
29 |
30 |
36 |
37 |
43 |
44 |
50 |
56 |
57 |
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/itembinder/BannerContentItembinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.itembinder
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.load.MultiTransformation
9 | import com.bumptech.glide.load.resource.bitmap.CenterCrop
10 | import com.bumptech.glide.request.RequestOptions.bitmapTransform
11 | import com.czq.kotlinarch.R
12 | import com.czq.kotlinarch.R.id.ivFirefly
13 | import com.czq.kotlinarch.data.model.Banner
14 | import com.drakeet.multitype.ItemViewBinder
15 | import kotlinx.android.synthetic.main.recyclerview_item_banner_content.view.*
16 |
17 |
18 | class BannerContentItembinder : ItemViewBinder() {
19 |
20 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): BannerContentItembinder.ViewHolder =
21 | ViewHolder(inflater.inflate(R.layout.recyclerview_item_banner_content, parent, false))
22 |
23 | override fun onBindViewHolder(holder: BannerContentItembinder.ViewHolder, itemData: Banner) {
24 | val itemView = holder.itemView
25 | Glide.with(holder.itemView.context).load(itemData?.cover ?: "")
26 | .apply(bitmapTransform(MultiTransformation(CenterCrop())))
27 | .into(itemView.ivCover!!)
28 | if (itemData.relatedType == "article") {
29 | itemView.tvTitle.text = itemData.title
30 |
31 | itemView.tvTitle.visibility = View.VISIBLE
32 | itemView.tvGameName.visibility = View.GONE
33 | itemView.tvGameDesc.visibility = View.GONE
34 | itemView.ivFirefly.visibility = View.GONE
35 | } else {
36 | itemView.tvTitle.visibility = View.GONE
37 | itemView.tvGameName.visibility = View.VISIBLE
38 | itemView.tvGameDesc.visibility = View.VISIBLE
39 |
40 | itemView.tvGameName.text = itemData.title
41 | itemView.tvGameDesc.text = itemData.summary
42 | itemView.ivFirefly.visibility = if (itemData.isIsFirefly) {
43 | View.VISIBLE
44 | } else {
45 | View.GONE
46 | }
47 | }
48 |
49 | }
50 |
51 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
52 |
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/itembinder/FeedArticleItembinder.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.itembinder
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.load.MultiTransformation
9 | import com.bumptech.glide.load.resource.bitmap.CenterCrop
10 | import com.bumptech.glide.request.RequestOptions.bitmapTransform
11 | import com.czq.kotlinarch.R
12 | import com.czq.kotlinarch.data.model.FeedArticle
13 | import com.drakeet.multitype.ItemViewBinder
14 | import com.hwangjr.rxbus.RxBus
15 | import kotlinx.android.synthetic.main.recyclerview_item_feed_article.view.*
16 |
17 |
18 | class FeedArticleItembinder : ItemViewBinder() {
19 |
20 | override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): FeedArticleItembinder.ViewHolder =
21 | ViewHolder(inflater.inflate(R.layout.recyclerview_item_feed_article, parent, false))
22 |
23 | override fun onBindViewHolder(holder: FeedArticleItembinder.ViewHolder, itemData: FeedArticle) {
24 | val itemView = holder.itemView
25 | Glide.with(holder.itemView.context).load(itemData?.user?.avatar ?: "")
26 | .apply(bitmapTransform(MultiTransformation(CenterCrop())))
27 | .into(itemView.ivAvatar!!)
28 | Glide.with(holder.itemView.context).load(itemData?.payload?.article?.cover?.medium ?: "")
29 | .apply(bitmapTransform(MultiTransformation(CenterCrop())))
30 | .into(itemView.ivCover!!)
31 | itemView.tvTitle.text = itemData.payload?.article?.title ?: ""
32 | itemView.tvUserName.text = itemData.user?.nickname ?: ""
33 | itemView.tvGameName.text = itemData.payload?.article?.game?.name ?: ""
34 | val isFirefly = itemData.payload?.article?.isIsFireflyUser ?: false
35 | itemView.tvI.visibility = if (isFirefly) {
36 | View.VISIBLE
37 | } else {
38 | View.GONE
39 | }
40 | itemView.tvFrom.visibility = if (isFirefly) {
41 | View.VISIBLE
42 | } else {
43 | View.GONE
44 | }
45 | }
46 |
47 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
48 | init {
49 | itemView.setOnClickListener {
50 | RxBus.get().post("hi","")
51 | }
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/App.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch
2 |
3 | import android.app.Application
4 | import com.orhanobut.logger.AndroidLogAdapter
5 | import com.orhanobut.logger.Logger
6 |
7 | import com.scwang.smart.refresh.layout.api.RefreshLayout
8 | import com.scwang.smart.refresh.layout.api.RefreshFooter
9 | import com.scwang.smart.refresh.layout.SmartRefreshLayout
10 | import android.content.Context
11 | import android.view.Gravity
12 | import com.czq.kotlin_arch.component.cover.CoverFrameViewConfig
13 | import com.hjq.toast.ToastUtils
14 | import com.scwang.smart.refresh.footer.ClassicsFooter
15 | import com.scwang.smart.refresh.header.ClassicsHeader
16 | import com.scwang.smart.refresh.layout.api.RefreshHeader
17 | import com.scwang.smart.refresh.layout.listener.DefaultRefreshFooterCreator
18 | import com.scwang.smart.refresh.layout.listener.DefaultRefreshHeaderCreator
19 |
20 |
21 | class App : Application() {
22 | companion object {
23 | lateinit var application: App
24 | }
25 |
26 | override fun onCreate() {
27 | super.onCreate()
28 | application = this
29 | ToastUtils.init(this)
30 | ToastUtils.setGravity(Gravity.BOTTOM, 0, 0)
31 | Logger.addLogAdapter(object : AndroidLogAdapter() {
32 | override fun isLoggable(priority: Int, tag: String?): Boolean {
33 | return BuildConfig.DEBUG
34 | }
35 | })
36 | SmartRefreshLayout.setDefaultRefreshHeaderCreator(object : DefaultRefreshHeaderCreator {
37 | override fun createRefreshHeader(
38 | context: Context,
39 | layout: RefreshLayout
40 | ): RefreshHeader {
41 | layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white)//全局设置主题颜色
42 | return ClassicsHeader(context)//.setTimeFormat(new DynamicTimeFormat("更新于 %s"));//指定为经典Header,默认是 贝塞尔雷达Header
43 | }
44 | })
45 | //设置全局的Footer构建器
46 | SmartRefreshLayout.setDefaultRefreshFooterCreator(object : DefaultRefreshFooterCreator {
47 | override fun createRefreshFooter(
48 | context: Context,
49 | layout: RefreshLayout
50 | ): RefreshFooter {
51 | //指定为经典Footer,默认是 BallPulseFooter
52 | return ClassicsFooter(context).setDrawableSize(20f)
53 | }
54 | })
55 | //这里可以配置全局loadingview emptyview errorview的布局
56 | CoverFrameViewConfig.defaultLoadingViewLayout = R.layout.custom_loading_view
57 |
58 | }
59 |
60 |
61 | }
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | apply plugin: 'kotlin-kapt'
5 | android {
6 | signingConfigs {
7 | release {
8 | storePassword '123456'
9 | keyAlias = '123456'
10 | keyPassword '123456'
11 | storeFile file('keystore.jks')
12 | }
13 | }
14 | dataBinding {
15 | enabled = true
16 | }
17 | compileSdkVersion 30
18 | defaultConfig {
19 | applicationId "com.czq.kotlinarch"
20 | minSdkVersion 21
21 | targetSdkVersion 30
22 | versionCode 1
23 | versionName "1.0"
24 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
25 | }
26 | buildTypes {
27 | debug {
28 | }
29 | release {
30 | minifyEnabled true
31 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
32 | signingConfig signingConfigs.release
33 | }
34 | }
35 | compileOptions {
36 | sourceCompatibility JavaVersion.VERSION_1_8
37 | targetCompatibility JavaVersion.VERSION_1_8
38 | }
39 |
40 | }
41 |
42 | dependencies {
43 | implementation fileTree(include: ['*.jar'], dir: 'libs')
44 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
45 | implementation 'androidx.appcompat:appcompat:1.2.0-alpha01'
46 | testImplementation 'junit:junit:4.12'
47 | androidTestImplementation 'androidx.test:runner:1.3.0-alpha03'
48 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'
49 | implementation 'androidx.core:core-ktx:1.1.0'
50 | implementation 'com.makeramen:roundedimageview:2.3.0'
51 | implementation 'com.github.bumptech.glide:glide:4.10.0'
52 | kapt 'com.github.bumptech.glide:compiler:4.10.0'
53 | implementation 'jp.wasabeef:glide-transformations:4.0.1'
54 | implementation 'com.squareup.retrofit2:retrofit:2.7.0'
55 | implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2'
56 | implementation 'org.ligboy.retrofit2:converter-fastjson-android:2.2.0'
57 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.0'
58 | implementation('com.github.ihsanbal:LoggingInterceptor:3.0.0') {
59 | exclude group: 'org.json', module: 'json'
60 | }
61 | implementation 'androidx.cardview:cardview:1.0.0'
62 |
63 | //下拉刷新
64 |
65 | implementation project(path: ':kotlin_arch')
66 | kapt 'androidx.databinding:databinding-compiler:4.0.0'
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 |
85 | :omega
86 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/challenge_home_item_challenge.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
19 |
20 |
36 |
37 |
49 |
50 |
64 |
65 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/base/BaseFragment.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.base
2 |
3 | import android.content.Context
4 | import android.os.Bundle
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.Toast
9 | import androidx.fragment.app.Fragment
10 | import com.czq.kotlin_arch.component.cover.CoverFrameLayout
11 | import com.hjq.toast.ToastUtils
12 | import com.hwangjr.rxbus.RxBus
13 | import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
14 | import kotlinx.android.synthetic.main.fragment_base.*
15 |
16 | abstract class BaseFragment : Fragment(), IBaseView {
17 |
18 |
19 | open lateinit var mPresenter: T
20 |
21 | override fun getContext(): Context {
22 | return activity!!
23 | }
24 |
25 | override fun onCreateView(
26 | inflater: LayoutInflater,
27 | container: ViewGroup?,
28 | savedInstanceState: Bundle?
29 | ): View? {
30 | return inflater.inflate(getLayoutId(), container, false)
31 | }
32 |
33 | override fun onCreate(savedInstanceState: Bundle?) {
34 | super.onCreate(savedInstanceState)
35 | mPresenter = createPresenter()
36 | lifecycle.addObserver(mPresenter)
37 | }
38 |
39 |
40 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
41 | super.onViewCreated(view, savedInstanceState)
42 | initView()
43 | RxBus.get().register(mPresenter)
44 | mPresenter.start()
45 | }
46 |
47 | override fun onDestroyView() {
48 | RxBus.get().unregister(mPresenter)
49 | super.onDestroyView()
50 |
51 | }
52 |
53 | open fun initView() {
54 | coverLayout?.doReload = {
55 | showLoading()
56 | mPresenter?.start()
57 | }
58 | }
59 |
60 |
61 | abstract fun createPresenter(): T
62 |
63 | abstract fun getLayoutId(): Int
64 |
65 |
66 | override fun showContent() {
67 | coverLayout?.showContent()
68 | }
69 |
70 | override fun showLoading() {
71 | coverLayout?.showLoading()
72 | }
73 |
74 | override fun showEmpty() {
75 | coverLayout?.showEmpty()
76 | }
77 |
78 | override fun showError(it: Throwable?) {
79 | coverLayout?.showError()
80 | ToastUtils.show("${it?.message ?: "加载失败"}")
81 | }
82 |
83 |
84 | override fun autoDispose(): AndroidLifecycleScopeProvider {
85 | return AndroidLifecycleScopeProvider.from(this)
86 | }
87 |
88 | override fun onDestroy() {
89 | super.onDestroy()
90 | lifecycle.removeObserver(mPresenter)
91 | }
92 |
93 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/challenge_home_item_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
20 |
21 |
37 |
38 |
54 |
55 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/PagingListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import android.annotation.SuppressLint
4 | import android.graphics.Rect
5 | import android.view.View
6 | import androidx.recyclerview.widget.GridLayoutManager
7 | import androidx.recyclerview.widget.RecyclerView
8 | import com.czq.kotlin_arch.basePage.paging.BasePagingActivity
9 | import com.czq.kotlin_arch.common.util.ext.dp
10 | import com.czq.kotlinarch.R
11 | import com.czq.kotlinarch.data.viewModel.ChallengeRecommandItemVm
12 | import com.czq.kotlinarch.viewbinder.ChallengeViewbinder
13 | import com.czq.kotlinarch.viewbinder.CircleViewbinder
14 | import com.czq.kotlinarch.viewbinder.SeeMoreViewbinder
15 | import kotlinx.android.synthetic.main.activity_paging_list.*
16 |
17 | class PagingListActivity : BasePagingActivity(),
18 | PagingListContact.PagingListView {
19 |
20 | @SuppressLint("CheckResult")
21 | override fun registItemBinder() {
22 | multiAdapter.register(ChallengeViewbinder())
23 | multiAdapter.register(CircleViewbinder())
24 | multiAdapter.register(SeeMoreViewbinder())
25 | }
26 |
27 | override fun createPresenter(): PagingListContact.PagingListPresenter {
28 | return PagingListPresenter(this)
29 | }
30 |
31 | override fun getLayoutId(): Int {
32 | return R.layout.activity_paging_list
33 | }
34 |
35 | override fun initView() {
36 | super.initView()
37 | val layoutManager = GridLayoutManager(this, 2)
38 | layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
39 | override fun getSpanSize(position: Int): Int {
40 | if (multiAdapter.items[position] is ChallengeRecommandItemVm)
41 | return 1
42 | else {
43 | return 2
44 | }
45 | }
46 | }
47 | pagingRecycleview.layoutManager = layoutManager
48 | pagingRecycleview.addItemDecoration(SpaceItemDecoration())//为了弄间距
49 | }
50 |
51 | inner class SpaceItemDecoration : RecyclerView.ItemDecoration() {
52 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
53 | super.getItemOffsets(outRect, view, parent, state)
54 | val position = parent!!.getChildLayoutPosition(view)
55 |
56 | if (multiAdapter.items[position] is ChallengeRecommandItemVm) {
57 | val item = multiAdapter.items[position] as ChallengeRecommandItemVm
58 | if (item.index % 2 == 0) {
59 | outRect?.left = 15.dp
60 | outRect?.right = 5.dp
61 | } else {
62 | outRect?.left = 5.dp
63 | outRect?.right = 15.dp
64 | }
65 | } else {
66 | outRect?.left = 0
67 | outRect?.right = 0
68 | }
69 | }
70 | }
71 |
72 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/remote/RemoteDataRepository.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.remote
2 |
3 | import com.czq.kotlinarch.BuildConfig
4 | import com.czq.kotlinarch.data.model.*
5 | import com.czq.kotlinarch.data.remote.api.RemoteApi
6 | import io.reactivex.Observable
7 | import okhttp3.OkHttpClient
8 | import okhttp3.logging.HttpLoggingInterceptor
9 |
10 | import retrofit2.Retrofit
11 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
12 | import retrofit2.converter.fastjson.FastJsonConverterFactory
13 | import java.util.concurrent.TimeUnit
14 |
15 |
16 | class RemoteDataRepository {
17 | private val mMockDataRepository = MockDataRepository()
18 |
19 | private val okHttpClient: OkHttpClient by lazy {
20 |
21 | val logging = HttpLoggingInterceptor()
22 | if (BuildConfig.DEBUG) {
23 | // development build
24 | logging.setLevel(HttpLoggingInterceptor.Level.BODY);
25 | } else {
26 | // production build
27 | logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
28 | }
29 |
30 | val client = OkHttpClient.Builder()
31 | .retryOnConnectionFailure(true)//连接失败后是否重新连接
32 | .connectTimeout(5, TimeUnit.SECONDS)//超时时间15S
33 | .addInterceptor(logging)
34 | .build()
35 | client
36 | }
37 | private val retrofit by lazy {
38 | Retrofit.Builder()
39 | .client(okHttpClient)
40 | .baseUrl("http://47.98.129.57:8080/info-admin-web/")
41 | .addConverterFactory(FastJsonConverterFactory.create())
42 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
43 | .build()
44 | }
45 |
46 | private val remoteApi: RemoteApi by lazy { retrofit.create(RemoteApi::class.java!!) }
47 |
48 |
49 | fun getChallengeRecommond(pageNo: Int, pageSize: Int): Observable> {
50 | return mMockDataRepository.getChallengeRecommond()
51 | }
52 |
53 | fun getUser(): Observable {
54 | return remoteApi.getUser("manondidi", "12345566").map { getData(it) }
55 | // return mMockDataRepository.getUser()
56 | }
57 |
58 |
59 | fun getGames(pageNum: Int, pageSize: Int): Observable> {
60 | // return remoteApi.getGames(pageNum, pageSize).map { getData(it) }
61 | return mMockDataRepository.getGames()
62 | }
63 |
64 | fun getFeedArticles(
65 | pageSize: Int,
66 | offsetId: String?,
67 | direction: String
68 | ): Observable> {
69 | // return remoteApi.getArticleFeeds(pageSize, offsetId, direction).map { getData(it) }
70 | return mMockDataRepository.getFeeds()
71 | }
72 |
73 | fun getBanners(): Observable> {
74 | return mMockDataRepository.getBanners()
75 | }
76 |
77 | fun getData(result: Result): T? {
78 | if (result.status != 0) {
79 | throw RuntimeException(result.msg)
80 | }
81 | return result.data
82 | }
83 |
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/fragment/PagingListFragment.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example.fragment
2 |
3 | import android.graphics.Rect
4 | import android.view.View
5 | import androidx.recyclerview.widget.GridLayoutManager
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.czq.kotlin_arch.basePage.paging.BasePagingFragment
8 | import com.czq.kotlin_arch.common.util.ext.dp
9 | import com.czq.kotlinarch.R
10 | import com.czq.kotlinarch.data.viewModel.ChallengeRecommandItemVm
11 | import com.czq.kotlinarch.viewbinder.ChallengeViewbinder
12 | import com.czq.kotlinarch.viewbinder.CircleViewbinder
13 | import com.czq.kotlinarch.viewbinder.SeeMoreViewbinder
14 | import kotlinx.android.synthetic.main.fragment_paging_list.*
15 |
16 | class PagingListFragment : BasePagingFragment(), PagingListContact.PagingListView {
17 |
18 | companion object {
19 | fun newInstance():PagingListFragment{
20 | return PagingListFragment()
21 | }
22 | }
23 |
24 | override fun registItemBinder() {
25 | multiAdapter.register(ChallengeViewbinder())
26 | multiAdapter.register(CircleViewbinder())
27 | multiAdapter.register(SeeMoreViewbinder())
28 | }
29 |
30 | override fun createPresenter(): PagingListContact.PagingListPresenter {
31 | return PagingListPresenter(this)
32 | }
33 |
34 | override fun getLayoutId(): Int {
35 | return R.layout.fragment_paging_list
36 | }
37 |
38 | override fun initView() {
39 | super.initView()
40 | val layoutManager = GridLayoutManager(context,2)
41 | layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
42 | override fun getSpanSize(position: Int): Int {
43 | if (multiAdapter.items[position] is ChallengeRecommandItemVm)
44 | return 1
45 | else {
46 | return 2
47 | }
48 | }
49 | }
50 | pagingRecycleview.layoutManager=layoutManager
51 | pagingRecycleview.addItemDecoration(SpaceItemDecoration())//为了弄间距
52 | }
53 |
54 | inner class SpaceItemDecoration : RecyclerView.ItemDecoration() {
55 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
56 | super.getItemOffsets(outRect, view, parent, state)
57 | val position = parent!!.getChildLayoutPosition(view)
58 |
59 | if (multiAdapter.items[position] is ChallengeRecommandItemVm) {
60 | val item = multiAdapter.items[position] as ChallengeRecommandItemVm
61 | if (item.index % 2 == 0) {
62 | outRect?.left = 15.dp
63 | outRect?.right = 5.dp
64 | } else {
65 | outRect?.left = 5.dp
66 | outRect?.right = 15.dp
67 | }
68 | } else {
69 | outRect?.left = 0
70 | outRect?.right = 0
71 | }
72 | }
73 | }
74 |
75 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/base/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.base
2 |
3 | import android.app.Activity
4 | import android.content.Context
5 | import android.os.Build
6 | import android.os.Bundle
7 | import android.view.MenuItem
8 | import android.view.View
9 | import android.view.Window
10 | import android.widget.Toast
11 | import androidx.appcompat.app.AppCompatActivity
12 | import com.czq.kotlin_arch.component.cover.CoverFrameLayout
13 | import com.hjq.toast.ToastUtils
14 | import com.hwangjr.rxbus.RxBus
15 | import com.orhanobut.logger.Logger
16 | import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
17 | import kotlinx.android.synthetic.main.activity_base.*
18 |
19 | abstract class BaseActivity : AppCompatActivity(), IBaseView {
20 |
21 | open lateinit var mPresenter: T
22 |
23 | override fun getContext(): Context {
24 | return this
25 | }
26 |
27 | override fun onCreate(savedInstanceState: Bundle?) {
28 | super.onCreate(savedInstanceState)
29 | if (!needTitle()) {
30 | supportActionBar?.hide()
31 | } else {
32 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
33 | }
34 |
35 | initContentView()
36 | initView()
37 | mPresenter = createPresenter()
38 | lifecycle.addObserver(mPresenter)
39 | RxBus.get().register(mPresenter)
40 | mPresenter.start()
41 | }
42 |
43 |
44 |
45 |
46 |
47 | override fun autoDispose(): AndroidLifecycleScopeProvider {
48 | return AndroidLifecycleScopeProvider.from(this)
49 | }
50 |
51 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
52 | if (item?.itemId == android.R.id.home) {
53 | onBackPressed()
54 | }
55 | return super.onOptionsItemSelected(item)
56 | }
57 |
58 | open fun needTitle(): Boolean {
59 | return true
60 | }
61 |
62 | abstract fun createPresenter(): T
63 |
64 | abstract fun getLayoutId(): Int
65 |
66 | open fun initContentView() {
67 | setContentView(getLayoutId())
68 | }
69 |
70 | open fun initView() {
71 | title = "BaseActivity"
72 | coverLayout?.doReload = {
73 | showLoading()
74 | mPresenter?.start()
75 | }
76 |
77 | }
78 |
79 |
80 | override fun showContent() {
81 | coverLayout?.showContent()
82 | }
83 |
84 | override fun showLoading() {
85 | coverLayout?.showLoading()
86 | }
87 |
88 | override fun showEmpty() {
89 | coverLayout?.showEmpty()
90 | }
91 |
92 | override fun showError(it: Throwable?) {
93 | coverLayout?.showError()
94 | Logger.e(it, it?.message ?: "")
95 | ToastUtils.show("${it?.message ?: "加载失败"}")
96 | }
97 |
98 |
99 | override fun onDestroy() {
100 | super.onDestroy()
101 | lifecycle.removeObserver(mPresenter)
102 | RxBus.get().unregister(mPresenter)
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/component/cover/CoverFrameLayout.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.component.cover
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.widget.FrameLayout
8 | import androidx.core.view.children
9 | import com.czq.kotlin_arch.R
10 | import kotlinx.android.synthetic.main.common_error_view.view.*
11 |
12 | class CoverFrameLayout : FrameLayout {
13 |
14 | var loadingView: View? = null
15 | var emptyView: View? = null
16 | var errorView: View? = null
17 | var doReload: (() -> Unit)? = null
18 | var coverListener: CoverListener? = null
19 |
20 | private val inflater by lazy { LayoutInflater.from(context) }
21 |
22 | constructor(context: Context) : super(context)
23 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
24 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
25 | context,
26 | attrs,
27 | defStyleAttr
28 | )
29 |
30 |
31 | fun showLoading() {
32 | if (loadingView == null) {
33 | loadingView = inflater.inflate(CoverFrameViewConfig.defaultLoadingViewLayout, null)
34 | }
35 | if (loadingView?.parent == null) {
36 | val lp = loadingView?.layoutParams
37 | this.addView(loadingView)
38 | }
39 | loadingView?.visibility = View.VISIBLE
40 | emptyView?.visibility = View.GONE
41 | errorView?.visibility = View.GONE
42 | coverListener?.onShowLoading(loadingView)
43 |
44 | }
45 |
46 | fun showEmpty() {
47 | if (emptyView == null) {
48 | emptyView = inflater.inflate(CoverFrameViewConfig.defaultEmptyViewLayout, null)
49 | emptyView?.setOnClickListener {
50 | reload()
51 | }
52 | }
53 | if (emptyView?.parent == null) {
54 | this.addView(emptyView)
55 | }
56 |
57 | emptyView?.visibility = View.VISIBLE
58 | loadingView?.visibility = View.GONE
59 | errorView?.visibility = View.GONE
60 | coverListener?.onShowEmpty(emptyView)
61 | }
62 |
63 | fun showError() {
64 | if (errorView == null) {
65 | errorView = inflater.inflate(CoverFrameViewConfig.defaultErrorViewLayout, null)
66 | errorView?.btnRetry?.setOnClickListener {
67 | reload()
68 | }
69 | }
70 | if (errorView?.parent == null) {
71 | val lp = errorView?.layoutParams
72 | this.addView(errorView)
73 | }
74 | errorView?.visibility = View.VISIBLE
75 | loadingView?.visibility = View.GONE
76 | emptyView?.visibility = View.GONE
77 | coverListener?.onShowError(errorView)
78 | }
79 |
80 | fun showContent() {
81 | errorView?.visibility = View.GONE
82 | loadingView?.visibility = View.GONE
83 | emptyView?.visibility = View.GONE
84 | coverListener?.onShowContent()
85 | }
86 |
87 | fun reload() {
88 | if (loadingView?.visibility == View.VISIBLE){
89 | return
90 | }
91 | doReload?.invoke()
92 | }
93 | }
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/paging/BasePagingActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.paging
2 |
3 | import android.os.Bundle
4 | import androidx.recyclerview.widget.LinearLayoutManager
5 | import com.czq.kotlin_arch.R
6 | import com.czq.kotlin_arch.basePage.base.BaseActivity
7 | import com.czq.kotlin_arch.basePage.base.IBasePagingPrensenter
8 | import com.czq.kotlin_arch.basePage.base.IBasePagingView
9 | import com.drakeet.multitype.MultiTypeAdapter
10 | import com.scwang.smart.refresh.layout.constant.RefreshState
11 | import kotlinx.android.synthetic.main.activity_base_paging.*
12 | import kotlinx.android.synthetic.main.activity_base_paging.coverLayout
13 | import kotlinx.android.synthetic.main.activity_base_paging.pagingRecycleview
14 | import kotlinx.android.synthetic.main.activity_base_paging.refreshLayout
15 | import kotlinx.android.synthetic.main.fragment_base_paging.*
16 |
17 | abstract class BasePagingActivity : BaseActivity(), IBasePagingView {
18 | val multiAdapter: MultiTypeAdapter = MultiTypeAdapter()
19 | override fun onCreate(savedInstanceState: Bundle?) {
20 | super.onCreate(savedInstanceState)
21 | registItemBinder()
22 | }
23 |
24 | override fun initView() {
25 | super.initView()
26 | title = "BasePagingActivity"
27 | pagingRecycleview.layoutManager = LinearLayoutManager(this)
28 | pagingRecycleview.adapter = multiAdapter
29 | // showRecyclerViewLoading()
30 | refreshLayout.setOnRefreshListener {
31 | mPresenter.resetPage()
32 | mPresenter.loadData()
33 | }
34 | refreshLayout.setOnLoadMoreListener {
35 | mPresenter.loadData()
36 | }
37 | coverLayout?.doReload = {
38 | beginRefresh()
39 | }
40 | }
41 |
42 | abstract fun registItemBinder()
43 |
44 |
45 | override fun getLayoutId(): Int {
46 | return R.layout.activity_base_paging
47 | }
48 |
49 | override fun showRecyclerViewEmpty() {
50 | showEmpty()
51 | }
52 |
53 | override fun showRecyclerViewError(it: Throwable?) {
54 | showError(it)
55 | }
56 |
57 | override fun showRecyclerViewContent() {
58 | showContent()
59 | }
60 |
61 | override fun showRecyclerViewLoading() {
62 | showLoading()
63 | }
64 |
65 | override fun isRefreshLoading(): Boolean {
66 | return refreshLayout.state == RefreshState.Refreshing || refreshLayout.state == RefreshState.Loading
67 | }
68 |
69 |
70 | override fun beginRefresh() {
71 | if (isRefreshLoading()) {
72 | return
73 | }
74 | showRecyclerViewContent()
75 | refreshLayout.autoRefresh()
76 | }
77 |
78 | override fun stopRefresh() {
79 | refreshLayout.finishRefresh()
80 | }
81 |
82 | override fun stopLoadingdMore(finish: Boolean) {
83 | if (finish) {
84 | refreshLayout.finishLoadMoreWithNoMoreData()
85 | } else {
86 | refreshLayout.finishLoadMore()
87 | }
88 | }
89 |
90 | override fun setRecyclerViewData(datasource: ArrayList) {
91 | multiAdapter.items = datasource
92 | multiAdapter.notifyDataSetChanged()
93 | }
94 | override fun notifyDataChange() {
95 | multiAdapter.notifyDataSetChanged()
96 | }
97 |
98 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/GameListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 | import android.graphics.Color
4 | import android.view.View
5 | import androidx.recyclerview.widget.LinearLayoutManager
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.czq.kotlin_arch.basePage.paging.BasePagingActivity
8 | import com.czq.kotlinarch.R
9 | import com.czq.kotlinarch.data.viewModel.GameDate
10 | import com.czq.kotlinarch.viewbinder.GameDateViewbinder
11 | import com.czq.kotlinarch.viewbinder.GameViewbinder
12 | import com.scwang.smart.refresh.header.BezierRadarHeader
13 | import com.scwang.smart.refresh.layout.api.RefreshHeader
14 | import com.scwang.smart.refresh.layout.constant.RefreshState
15 | import com.scwang.smart.refresh.layout.simple.SimpleMultiListener
16 | import kotlinx.android.synthetic.main.activity_game_list.*
17 | import kotlinx.android.synthetic.main.game_item_date.view.*
18 |
19 |
20 | class GameListActivity : BasePagingActivity(), GameListContact.PagingListView {
21 |
22 |
23 | override fun registItemBinder() {
24 | multiAdapter.register(GameViewbinder())
25 | multiAdapter.register(GameDateViewbinder())
26 |
27 | }
28 |
29 | override fun initView() {
30 | super.initView()
31 |
32 | preparStickyView()
33 |
34 | refreshLayout.setRefreshHeader(BezierRadarHeader(this))
35 |
36 | pagingRecycleview.addOnScrollListener(object : RecyclerView.OnScrollListener() {
37 | override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
38 | super.onScrolled(recyclerView, dx, dy)
39 | if (refreshLayout.state != RefreshState.None) return
40 |
41 | val layoutManager = recyclerView.layoutManager as LinearLayoutManager
42 | val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
43 | val gameDate = findNearHeadItem(firstVisibleItemPosition) as? GameDate
44 | if (gameDate != null) {
45 | stickyHeaderView.visibility = View.VISIBLE
46 | stickyHeaderView?.tvDate?.text = gameDate?.date
47 | } else {
48 | stickyHeaderView.visibility = View.GONE
49 | }
50 | }
51 | })
52 |
53 | }
54 |
55 | private fun preparStickyView() {
56 | stickyHeaderView?.visibility = View.GONE
57 | refreshLayout.setOnMultiListener(object : SimpleMultiListener() {
58 | override fun onHeaderMoving(header: RefreshHeader?, isDragging: Boolean, percent: Float, offset: Int, headerHeight: Int, maxDragHeight: Int) {
59 | super.onHeaderMoving(header, isDragging, percent, offset, headerHeight, maxDragHeight)
60 | if (isDragging) {
61 | stickyHeaderView?.visibility = View.GONE
62 | }
63 | }
64 | })
65 | }
66 |
67 | fun findNearHeadItem(position: Int): Any? {
68 | return multiAdapter.items.findLast {
69 | val b = it is GameDate && multiAdapter.items.indexOf(it) <= position
70 | b
71 | }
72 | }
73 |
74 |
75 | override fun createPresenter(): GameListContact.PagingListPresenter {
76 | return GameListPresenter(this)
77 | }
78 |
79 | override fun getLayoutId(): Int {
80 | return R.layout.activity_game_list
81 | }
82 |
83 |
84 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/recyclerview_item_banner_content.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
16 |
17 |
26 |
27 |
42 |
43 |
44 |
58 |
59 |
75 |
76 |
82 |
--------------------------------------------------------------------------------
/kotlin_arch/src/main/java/com/czq/kotlin_arch/basePage/paging/BasePagingFragment.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlin_arch.basePage.paging
2 |
3 | import android.os.Bundle
4 | import androidx.recyclerview.widget.LinearLayoutManager
5 | import com.czq.kotlin_arch.R
6 | import com.czq.kotlin_arch.basePage.base.BaseFragment
7 | import com.czq.kotlin_arch.basePage.base.IBasePagingPrensenter
8 | import com.czq.kotlin_arch.basePage.base.IBasePagingView
9 | import com.czq.kotlin_arch.component.cover.CoverFrameLayout
10 | import com.drakeet.multitype.MultiTypeAdapter
11 | import com.scwang.smart.refresh.layout.constant.RefreshState
12 | import kotlinx.android.synthetic.main.activity_base_paging.*
13 | import kotlinx.android.synthetic.main.fragment_base_paging.*
14 | import kotlinx.android.synthetic.main.fragment_base_paging.coverLayout
15 | import kotlinx.android.synthetic.main.fragment_base_paging.pagingRecycleview
16 | import kotlinx.android.synthetic.main.fragment_base_paging.refreshLayout
17 |
18 | abstract class BasePagingFragment : BaseFragment(), IBasePagingView {
19 |
20 | val multiAdapter: MultiTypeAdapter = MultiTypeAdapter()
21 |
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | registItemBinder()
26 | }
27 |
28 | override fun initView() {
29 | super.initView()
30 | pagingRecycleview.layoutManager = LinearLayoutManager(context)
31 | pagingRecycleview.adapter = multiAdapter
32 | // showRecyclerViewLoading()
33 | refreshLayout.setOnRefreshListener {
34 | mPresenter.resetPage()
35 | mPresenter.loadData()
36 | }
37 | refreshLayout.setOnLoadMoreListener {
38 | mPresenter.loadData()
39 | }
40 |
41 | coverLayout?.doReload = {
42 | beginRefresh()
43 | }
44 | }
45 |
46 | abstract fun registItemBinder()
47 |
48 |
49 | override fun getLayoutId(): Int {
50 | return R.layout.activity_base_paging
51 | }
52 |
53 | override fun showRecyclerViewEmpty() {
54 | showEmpty()
55 | }
56 |
57 | override fun showRecyclerViewError(it: Throwable?) {
58 | showError(it)
59 | }
60 |
61 | override fun showRecyclerViewContent() {
62 | showContent()
63 | }
64 |
65 | override fun showRecyclerViewLoading() {
66 | showLoading()
67 | }
68 |
69 | override fun isRefreshLoading(): Boolean {
70 | return return refreshLayout.state == RefreshState.Refreshing || refreshLayout.state == RefreshState.Loading
71 | }
72 |
73 | override fun beginRefresh() {
74 | if (isRefreshLoading()) {
75 | return
76 | }
77 | showRecyclerViewContent()
78 | refreshLayout.autoRefresh()
79 | }
80 |
81 | override fun stopRefresh() {
82 | refreshLayout.finishRefresh()
83 | }
84 |
85 | override fun stopLoadingdMore(finish: Boolean) {
86 | if (finish) {
87 | refreshLayout.finishLoadMoreWithNoMoreData()
88 | } else {
89 | refreshLayout.finishLoadMore()
90 | }
91 | }
92 |
93 | override fun setRecyclerViewData(datasource: ArrayList) {
94 | multiAdapter.items = datasource
95 | multiAdapter.notifyDataSetChanged()
96 | }
97 |
98 | override fun notifyDataChange() {
99 | multiAdapter.notifyDataSetChanged()
100 | }
101 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/base_colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ffffffff
4 | #ffcccccc
5 | #ffffffff
6 | #ff0cc975
7 | #ff05b969
8 |
9 |
10 | #f3f3f3
11 |
12 |
13 | #ff1c1c1c
14 |
15 | #ff717171
16 |
17 | #ffaaaaaa
18 |
19 | #fff5f5f5
20 |
21 | @color/base_background
22 |
23 |
24 | #ffffff
25 |
26 |
27 | #00000000
28 |
29 | #ff0a0a0a
30 | #ff1c1c1c
31 | @color/base_color_accent
32 | #ffaaaaaa
33 |
34 |
35 | @color/base_text_2_color
36 | #ffaaaaaa
37 |
38 |
39 | #0062b0
40 |
41 |
42 |
43 |
44 | #ffffffff
45 |
46 | #4dffffff
47 |
48 |
49 | #aaaaaa
50 |
51 | #d01716
52 |
53 |
54 |
55 |
56 | #ff000000
57 |
58 | #7f000000
59 |
60 | #33000000
61 | #19000000
62 | #66000000
63 |
64 | #0B000000
65 | #1A000000
66 | #FF000000
67 | #FFffffff
68 | #1Affffff
69 | #33000000
70 | #33ffffff
71 | #4D000000
72 | #4Dffffff
73 | #66000000
74 | #66ffffff
75 | #80000000
76 | #80ffffff
77 | #9A000000
78 | #9Affffff
79 | #B3000000
80 | #B3ffffff
81 | #CC000000
82 | #CCffffff
83 | #E5000000
84 | #E5ffffff
85 | #00ffffff
86 |
87 |
88 | #ffffffff
89 | #4dffffff
90 |
91 | #fffa0d0d
92 |
93 |
94 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/example/FeedArticlePresenter.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.example
2 |
3 |
4 | import android.annotation.SuppressLint
5 | import android.widget.Toast
6 | import com.czq.kotlin_arch.basePage.base.BasePagingPrensenterImpl
7 | import com.czq.kotlin_arch.paging.PagingStrategy
8 | import com.czq.kotlin_arch.paging.offset.OffsetPageInfo
9 | import com.czq.kotlin_arch.paging.offset.OffsetStrategy
10 | import com.czq.kotlinarch.data.model.FeedArticle
11 | import com.czq.kotlinarch.data.remote.RemoteDataRepository
12 | import com.czq.kotlinarch.data.viewModel.BannerList
13 | import com.uber.autodispose.lifecycle.autoDisposable
14 | import io.reactivex.Observable
15 | import io.reactivex.android.schedulers.AndroidSchedulers
16 | import io.reactivex.functions.BiFunction
17 | import io.reactivex.schedulers.Schedulers
18 | import com.hwangjr.rxbus.thread.EventThread
19 | import com.hwangjr.rxbus.annotation.Subscribe
20 | import com.hwangjr.rxbus.annotation.Tag
21 |
22 |
23 | class FeedArticlePresenter(override val mView: FeedArticleContract.IView) : BasePagingPrensenterImpl(mView),
24 | FeedArticleContract.IPresenter {
25 | val mRemoteDataRepository: RemoteDataRepository by lazy {
26 | RemoteDataRepository()
27 | }
28 |
29 | override fun getPagingStrategy(): PagingStrategy? {
30 | return OffsetStrategy(10, "id")
31 | }
32 |
33 | @SuppressLint("CheckResult")
34 | override fun onLoadData(pagingStrategy: PagingStrategy?) {
35 | val pageInfo = pagingStrategy!!.getPageInfo() as OffsetPageInfo
36 |
37 | if (pageInfo.isFirstPage()) {
38 | Observable.zip(getBannerList(),
39 | getFeedArticle(pageInfo.pageSize, pageInfo.offsetId, pageInfo.type),
40 | BiFunction, Map>
41 | { bannerList, feedArticles ->
42 | val map = mutableMapOf()
43 | map.put("feedArticles", feedArticles)
44 | map.put("bannerList", bannerList)
45 | map
46 | }).subscribeOn(Schedulers.io())
47 | .observeOn(AndroidSchedulers.mainThread())
48 | .autoDisposable(mView.autoDispose())
49 | .subscribe({ it ->
50 | val feedArticles = it.get("feedArticles") as? List
51 | val bannerList = it.get("bannerList") as? BannerList
52 | datasource.clear()
53 | pagingList.clear()
54 | if (bannerList != null) {
55 | datasource.add(bannerList)
56 | }
57 | pagingList.addAll(feedArticles ?: arrayListOf())//用于计算分页的数据
58 | datasource.addAll(feedArticles ?: arrayListOf())
59 | loadSuccess(it)
60 | }, {
61 | loadFail(it)
62 | })
63 |
64 | } else {
65 |
66 | getFeedArticle(pageInfo.pageSize, pageInfo.offsetId, pageInfo.type)
67 | .subscribeOn(Schedulers.io())
68 | .observeOn(AndroidSchedulers.mainThread())
69 | .autoDisposable(mView.autoDispose())
70 | .subscribe({ it ->
71 | pagingList.addAll(it ?: arrayListOf())//用于计算分页的数据
72 | datasource.addAll(it ?: arrayListOf())
73 | loadSuccess(it)
74 | }, {
75 | loadFail(it)
76 | })
77 | }
78 |
79 |
80 | }
81 |
82 | fun getBannerList(): Observable {
83 | return mRemoteDataRepository.getBanners().map {
84 | val bannerList = BannerList()
85 | bannerList.banners = it
86 | bannerList
87 | }.onErrorReturn { null }
88 | }
89 |
90 | fun getFeedArticle(pageSize: Int, offsetId: String?, direction: String): Observable> {
91 | return mRemoteDataRepository.getFeedArticles(pageSize, offsetId, direction)
92 | }
93 |
94 | @Subscribe(thread = EventThread.MAIN_THREAD, tags = [Tag("hi")])
95 | fun hi(str:String) {
96 | Toast.makeText(mView.getContext(),"hi",Toast.LENGTH_LONG).show()
97 | }
98 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/recyclerview_item_feed_article.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
21 |
22 |
33 |
34 |
35 |
45 |
46 |
62 |
63 |
68 |
69 |
77 |
78 |
89 |
90 |
101 |
102 |
103 |
115 |
116 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 |
2 | #============================== 项目 ==============================
3 | # data包下不可混淆 注意:需要改成你自己的
4 | -keep class com.czq.kotlinarch.data.**{*;}
5 |
6 | # 如果有自定义分页策略 即 自定义类似 com.czq.kotlin_arch.paging 包下的东西,也要避免混淆,因为我用了反射
7 |
8 | # kotlinArch框架
9 | -keep class com.czq.kotlin_arch.**{*;}
10 |
11 | #============================== 压缩参数配置 ==============================
12 | # 参考 https://www.jianshu.com/p/7436a1a32891 https://www.jianshu.com/p/be7ec1819d2f
13 | # 表示proguard对代码进行迭代优化的次数,Android一般为5
14 | -optimizationpasses 5
15 |
16 | # 不使用大小写混合类名
17 | -dontusemixedcaseclassnames
18 |
19 | # 不跳过library中的非public的类
20 | -dontskipnonpubliclibraryclasses
21 |
22 | # 不进行预校验,预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度
23 | -dontpreverify
24 |
25 | # 优化已默认关闭。 Dex不喜欢通过ProGuard优化和预验证步骤运行代码(并自行执行某些优化)
26 | -dontoptimize
27 |
28 | # 不输出提示
29 | -dontnote
30 |
31 | # 输出混淆日志
32 | -verbose
33 |
34 | #============================== Android ==============================
35 | # 保留注解参数
36 | -keepattributes *Annotation*
37 | -keep class * extends java.lang.annotation.Annotation {*;}
38 | -keep class * implements java.lang.annotation.Annotation {*;}
39 |
40 | # 泛型与反射
41 | -keepattributes Signature
42 | -keepattributes EnclosingMethod
43 |
44 | # 不混淆内部类
45 | -keepattributes InnerClasses
46 |
47 | # 保持Support库不被混淆
48 | -keep class android.support.**{*;}
49 | # 保持androidx库不被混淆
50 | -keep class androidx.**{*;}
51 |
52 | # 保持androidx库不被混淆
53 | -keep class com.google.android.material.** {*;}
54 | -keep class androidx.** {*;}
55 | -keep public class * extends androidx.**
56 | -keep interface androidx.** {*;}
57 | -dontwarn com.google.android.material.**
58 | -dontnote com.google.android.material.**
59 | -dontwarn androidx.**
60 |
61 | # 保持Parcelable不被混淆
62 | -keep class * implements android.os.Parcelable {
63 | public static final android.os.Parcelable$Creator *;
64 | }
65 | # 保持Serializable不被混淆
66 | -keepnames class * implements java.io.Serializable
67 | -keep public class * implements java.io.Serializable {
68 | public *;
69 | }
70 | -keepclassmembers class * implements java.io.Serializable {
71 | static final long serialVersionUID;
72 | private static final java.io.ObjectStreamField[] serialPersistentFields;
73 | !static !transient ;
74 | private void writeObject(java.io.ObjectOutputStream);
75 | private void readObject(java.io.ObjectInputStream);
76 | java.lang.Object writeReplace();
77 | java.lang.Object readResolve();
78 | }
79 |
80 | # 保持枚举类型部分方法不要混淆
81 | -keepclassmembers enum * {
82 | public static **[] values();
83 | public static ** valueOf(java.lang.String);
84 | }
85 |
86 | # 保持R文件不被混淆
87 | -keep class **.R{*;}
88 |
89 | # 保持 native 方法不被混淆
90 | -keepclasseswithmembernames class * {
91 | native ;
92 | }
93 |
94 | # 保留Google原生服务需要的类
95 | -keep public class com.google.vending.licensing.ILicensingService
96 | -keep public class com.android.vending.licensing.ILicensingService
97 |
98 | # java sdk
99 | -dontwarn javax.lang.model.**
100 | -dontwarn java.lang.invoke.*
101 |
102 | #第三方库
103 | #============================== Retrofit ==============================
104 | -dontwarn okio.**
105 | -dontwarn javax.annotation.**
106 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
107 | -keep class retrofit2.**{*;}
108 |
109 | #============================== OKHTTP ==============================
110 | -dontwarn okhttp3.**
111 | # JSR 305 annotations are for embedding nullability information.
112 | -dontwarn javax.annotation.**
113 | # A resource is loaded with a relative path so the package of this class must be preserved.
114 | -keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
115 | # Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
116 | -dontwarn org.codehaus.mojo.animal_sniffer.*
117 |
118 |
119 | #============================== Glide ==============================
120 | -keep public class * implements com.bumptech.glide.module.GlideModule
121 | -keep public class * extends com.bumptech.glide.module.AppGlideModule
122 | -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
123 | **[] $VALUES;
124 | public *;
125 | }
126 | #============================== FastJson ==============================
127 |
128 | -keep class kotlin.reflect.jvm.internal.** { *; }
129 | -dontwarn com.alibaba.fastjson.**
130 | -keepattributes Signature
131 | -keepattributes *Annotation*
132 | -keep class com.alibaba.fastjson.** {*;}
133 |
134 | #============================== RxJava ==============================
135 | -dontwarn io.reactivex.**
136 | -keep class io.reactivex.** { *; }
137 | # retrolambda
138 | -dontwarn java.lang.invoke.*
139 |
140 | #============================== RxBus ==============================
141 | -keep class com.hwangjr.rxbus.**{*;}
142 |
143 |
144 | #============================== ToastUtil ==============================
145 | -keep class com.hjq.toast.** {*;}
146 |
147 |
148 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/assets/game.json:
--------------------------------------------------------------------------------
1 | {
2 | "listData": [
3 | {
4 | "createTime": 1526374588,
5 | "hasRecrod": false,
6 | "icon": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/aDEuWEbmnrqkrku.png!a-3-240x.png",
7 | "iconType": "normal",
8 | "id": 10089387,
9 | "title": "Octocopter: Double or Squids"
10 | },
11 | {
12 | "createTime": 1526373552,
13 | "hasRecrod": false,
14 | "icon": "http://i3.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/GsTOXvbmnrplwcv.png!a-3-240x.png",
15 | "iconType": "normal",
16 | "id": 10089386,
17 | "title": "Animated Jigsaws: Beautiful Japanese Scenery"
18 | },
19 | {
20 | "createTime": 1526373067,
21 | "hasRecrod": false,
22 | "icon": "http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/hwoeaubmnroBavg.png!a-3-240x.png",
23 | "iconType": "normal",
24 | "id": 10089385,
25 | "title": "Splat the Fruit"
26 | },
27 | {
28 | "createTime": 1526369564,
29 | "hasRecrod": false,
30 | "icon": "http://i3.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/CdtVwWbmnrltlco.png!a-3-240x.png",
31 | "iconType": "normal",
32 | "id": 10089380,
33 | "title": "The Adventures of Elena Temple"
34 | },
35 | {
36 | "createTime": 1526366953,
37 | "hasRecrod": false,
38 | "icon": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/CPiBQDbmnrjadba.png!a-3-240x.png",
39 | "iconType": "shouyou-icon",
40 | "id": 10089379,
41 | "title": "龙曜三国"
42 | },
43 | {
44 | "createTime": 1526365811,
45 | "hasRecrod": false,
46 | "icon": "http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/MFWGPcbmnrhCtsn.jpg!a-3-240x.png",
47 | "iconType": "normal",
48 | "id": 10089378,
49 | "title": "命运石之门0"
50 | },
51 | {
52 | "createTime": 1526362429,
53 | "hasRecrod": false,
54 | "icon": "http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/tRHDznbmnrotwAD.jpg!a-3-240x.png",
55 | "iconType": "normal",
56 | "id": 10089384,
57 | "title": "三国群英录"
58 | },
59 | {
60 | "createTime": 1526349378,
61 | "hasRecrod": false,
62 | "icon": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/tIrrlsbmnqymwBn.jpg!a-3-240x.png",
63 | "iconType": "normal",
64 | "id": 10089377,
65 | "title": "追逐地平线"
66 | },
67 | {
68 | "createTime": 1526295977,
69 | "hasRecrod": false,
70 | "icon": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/TGWQdobmnpfkiye.png!a-3-240x.png",
71 | "iconType": "shouyou-icon",
72 | "id": 10089376,
73 | "title": "联盟战争"
74 | },
75 | {
76 | "createTime": 1526293977,
77 | "hasRecrod": false,
78 | "icon": "http://i3.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/kVdqLbbmnpdmsdE.png!a-3-240x.png",
79 | "iconType": "shouyou-icon",
80 | "id": 10089375,
81 | "title": "名侦探柯南HD"
82 | },
83 | {
84 | "createTime": 1526292870,
85 | "hasRecrod": false,
86 | "icon": "http://i3.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/jmrFzQbmnpcqqgF.png!a-3-240x.png",
87 | "iconType": "shouyou-icon",
88 | "id": 10089374,
89 | "title": "欧陆战争6:1804"
90 | },
91 | {
92 | "createTime": 1526292644,
93 | "hasRecrod": false,
94 | "icon": "http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/swhwlnbmnpcdtwa.png!a-3-240x.png",
95 | "iconType": "shouyou-icon",
96 | "id": 10089373,
97 | "title": "FRACTER"
98 | },
99 | {
100 | "createTime": 1526292419,
101 | "hasRecrod": false,
102 | "icon": "http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/FuQhUIbmnpbCjjn.png!a-3-240x.png",
103 | "iconType": "shouyou-icon",
104 | "id": 10089372,
105 | "title": "洛奇手机版"
106 | },
107 | {
108 | "createTime": 1526292276,
109 | "hasRecrod": false,
110 | "icon": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180515/StfxJibmnrhCDwg.jpg!a-3-240x.png",
111 | "iconType": "shouyou-icon",
112 | "id": 10089371,
113 | "title": "龙珠最强之战"
114 | },
115 | {
116 | "createTime": 1526291881,
117 | "hasRecrod": false,
118 | "icon": "http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/QMXUfgbmnpbpwio.png!a-3-240x.png",
119 | "iconType": "shouyou-icon",
120 | "id": 10089370,
121 | "title": "最终幻想11"
122 | },
123 | {
124 | "createTime": 1526290946,
125 | "hasRecrod": false,
126 | "icon": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/vzsvsCbmnparaBe.jpg!a-3-240x.png",
127 | "iconType": "normal",
128 | "id": 10089369,
129 | "title": "逻辑麻雀创龙:四人麻将/三人麻将"
130 | },
131 | {
132 | "createTime": 1526289847,
133 | "hasRecrod": false,
134 | "icon": "http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/zMvOUxbmnoFomds.png!a-3-240x.png",
135 | "iconType": "normal",
136 | "id": 10089368,
137 | "title": "ACA NEOGEO Gururin"
138 | },
139 | {
140 | "createTime": 1526289012,
141 | "hasRecrod": false,
142 | "icon": "http://i3.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/TyXtjKbmnoEwuAb.png!a-3-240x.png",
143 | "iconType": "normal",
144 | "id": 10089367,
145 | "title": "Eternal Edge"
146 | },
147 | {
148 | "createTime": 1526288429,
149 | "hasRecrod": false,
150 | "icon": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/adcFrQbmnoEhycf.png!a-3-240x.png",
151 | "iconType": "normal",
152 | "id": 10089366,
153 | "title": "狗头王牌"
154 | },
155 | {
156 | "createTime": 1526288064,
157 | "hasRecrod": false,
158 | "icon": "http://i1.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180514/fOyoIobmnoDyFtC.png!a-3-240x.png",
159 | "iconType": "normal",
160 | "id": 10089365,
161 | "title": "天空之怒DX"
162 | }
163 | ],
164 | "pageNo": 0,
165 | "pageSize": 20,
166 | "totalNum": 99
167 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czq/kotlinarch/data/model/FeedArticle.kt:
--------------------------------------------------------------------------------
1 | package com.czq.kotlinarch.data.model
2 |
3 | class FeedArticle {
4 |
5 | /**
6 | * id : 170950
7 | * createTime : 1526367486
8 | * payload : {"article":{"id":106572,"title":"《电竞俱乐部》一款经营类的电竞游戏","cover":{"url":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-4-x640.jpg","thumb":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-3-240x.jpg","medium":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-4-x480.jpg"},"summary":"首先感谢萤火虫提供的激活码。 游戏是一款以电竞为题材的模拟类游戏,包含了PFS和MOBA两大主流电竞比赛项目。 游戏中需要创建俱乐部,签约选手,组建战...","replyCount":4,"likeCount":5,"shareCount":0,"retweetCount":0,"likeStatus":"normal","createTime":1526367486,"game":{"id":10070273,"name":"电竞俱乐部","icon":"http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180112/vuBdnkbmduwqCkA.jpg!a-3-240x.png","iconType":"normal","recordedUserCount":31,"hasRecord":false},"isFireflyArticle":true,"userId":127480428,"nickname":"西决","isFireflyUser":true,"avatar":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180417/mktifubmljjagvh.jpg!a-1-120x120.jpg"}}
9 | * type : create-article
10 | * user : {"avatar":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180417/mktifubmljjagvh.jpg!a-1-120x120.jpg","nickname":"西决","id":127480428,"followStatus":"unfollowed","isFireflyUser":true}
11 | */
12 |
13 | var id: String ?= null
14 | var createTime: Int = 0
15 | var payload: Payload? = null
16 | var type: String? = null
17 | var user: User? = null
18 |
19 | class Payload {
20 | /**
21 | * article : {"id":106572,"title":"《电竞俱乐部》一款经营类的电竞游戏","cover":{"url":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-4-x640.jpg","thumb":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-3-240x.jpg","medium":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-4-x480.jpg"},"summary":"首先感谢萤火虫提供的激活码。 游戏是一款以电竞为题材的模拟类游戏,包含了PFS和MOBA两大主流电竞比赛项目。 游戏中需要创建俱乐部,签约选手,组建战...","replyCount":4,"likeCount":5,"shareCount":0,"retweetCount":0,"likeStatus":"normal","createTime":1526367486,"game":{"id":10070273,"name":"电竞俱乐部","icon":"http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180112/vuBdnkbmduwqCkA.jpg!a-3-240x.png","iconType":"normal","recordedUserCount":31,"hasRecord":false},"isFireflyArticle":true,"userId":127480428,"nickname":"西决","isFireflyUser":true,"avatar":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180417/mktifubmljjagvh.jpg!a-1-120x120.jpg"}
22 | */
23 |
24 | var article: Article? = null
25 |
26 | class Article {
27 | /**
28 | * id : 106572
29 | * title : 《电竞俱乐部》一款经营类的电竞游戏
30 | * cover : {"url":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-4-x640.jpg","thumb":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-3-240x.jpg","medium":"https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-4-x480.jpg"}
31 | * summary : 首先感谢萤火虫提供的激活码。 游戏是一款以电竞为题材的模拟类游戏,包含了PFS和MOBA两大主流电竞比赛项目。 游戏中需要创建俱乐部,签约选手,组建战...
32 | * replyCount : 4
33 | * likeCount : 5
34 | * shareCount : 0
35 | * retweetCount : 0
36 | * likeStatus : normal
37 | * createTime : 1526367486
38 | * game : {"id":10070273,"name":"电竞俱乐部","icon":"http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180112/vuBdnkbmduwqCkA.jpg!a-3-240x.png","iconType":"normal","recordedUserCount":31,"hasRecord":false}
39 | * isFireflyArticle : true
40 | * userId : 127480428
41 | * nickname : 西决
42 | * isFireflyUser : true
43 | * avatar : https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180417/mktifubmljjagvh.jpg!a-1-120x120.jpg
44 | */
45 |
46 | var id: Int = 0
47 | var title: String? = null
48 | var cover: Cover? = null
49 | var summary: String? = null
50 | var replyCount: Int = 0
51 | var likeCount: Int = 0
52 | var shareCount: Int = 0
53 | var retweetCount: Int = 0
54 | var likeStatus: String? = null
55 | var createTime: Int = 0
56 | var game: Game? = null
57 | var isIsFireflyArticle: Boolean = false
58 | var userId: Int = 0
59 | var nickname: String? = null
60 | var isIsFireflyUser: Boolean = false
61 | var avatar: String? = null
62 |
63 | class Cover {
64 | /**
65 | * url : https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-4-x640.jpg
66 | * thumb : https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-3-240x.jpg
67 | * medium : https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180515/yyDclQbmnrjpadn.jpg!a-4-x480.jpg
68 | */
69 |
70 | var url: String? = null
71 | var thumb: String? = null
72 | var medium: String? = null
73 | }
74 |
75 | class Game {
76 | /**
77 | * id : 10070273
78 | * name : 电竞俱乐部
79 | * icon : http://i2.17173cdn.com/9axtlo/YWxqaGBf/gamelib/20180112/vuBdnkbmduwqCkA.jpg!a-3-240x.png
80 | * iconType : normal
81 | * recordedUserCount : 31
82 | * hasRecord : false
83 | */
84 |
85 | var id: Int = 0
86 | var name: String? = null
87 | var icon: String? = null
88 | var iconType: String? = null
89 | var recordedUserCount: Int = 0
90 | var isHasRecord: Boolean = false
91 | }
92 | }
93 | }
94 |
95 | class User {
96 | /**
97 | * avatar : https://i.17173cdn.com/gdthue/YWxqaGBf/snsapp/20180417/mktifubmljjagvh.jpg!a-1-120x120.jpg
98 | * nickname : 西决
99 | * id : 127480428
100 | * followStatus : unfollowed
101 | * isFireflyUser : true
102 | */
103 |
104 | var avatar: String? = null
105 | var nickname: String? = null
106 | var id: Int = 0
107 | var followStatus: String? = null
108 | var isIsFireflyUser: Boolean = false
109 | }
110 | }
111 |
--------------------------------------------------------------------------------