├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── onestravel │ │ └── kotlin │ │ └── demo │ │ └── mvp │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cn │ │ │ ├── onestravel │ │ │ └── kotlin │ │ │ │ └── demo │ │ │ │ ├── BaseLoader.java │ │ │ │ ├── BaseServiceManager.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── OrderRecordLoader.kt │ │ │ │ ├── OrderRecordService.kt │ │ │ │ ├── model │ │ │ │ ├── User.kt │ │ │ │ └── UserModel.java │ │ │ │ ├── presenter │ │ │ │ ├── impl │ │ │ │ │ └── UserPresenterImpl.kt │ │ │ │ └── interf │ │ │ │ │ └── UserPresenter.kt │ │ │ │ ├── ui │ │ │ │ └── activity │ │ │ │ │ └── UserActivity.kt │ │ │ │ └── view │ │ │ │ └── UserView.kt │ │ │ └── test │ │ │ ├── MainContract.kt │ │ │ ├── MainPresenterImpl.kt │ │ │ └── TestMainActivity.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── layout_item.xml │ │ └── layout_test.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cn │ └── onestravel │ └── kotlin │ └── demo │ └── mvp │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kotlinbase ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cn │ │ │ └── onestravel │ │ │ └── library │ │ │ ├── common │ │ │ ├── GlobalGlideConfig.kt │ │ │ ├── activity │ │ │ │ ├── OneActivity.kt │ │ │ │ └── OneListActivity.kt │ │ │ ├── adapter │ │ │ │ └── OneRecyclerAdapter.kt │ │ │ ├── extend │ │ │ │ └── ImageViewExtend.kt │ │ │ ├── fragment │ │ │ │ ├── OneFragment.kt │ │ │ │ └── OneListFragment.kt │ │ │ ├── utils │ │ │ │ ├── DensityUtil.kt │ │ │ │ └── ImageUtils.kt │ │ │ └── view │ │ │ │ ├── CircleTextView.kt │ │ │ │ ├── ClassicalFooter.kt │ │ │ │ ├── EmptyView.kt │ │ │ │ ├── LoadMoreRecyclerView.kt │ │ │ │ ├── LoadMoreView.kt │ │ │ │ ├── LoadingDialog.kt │ │ │ │ ├── NoScrollViewPager.kt │ │ │ │ └── ShapeImageView.kt │ │ │ ├── mvp │ │ │ ├── activity │ │ │ │ ├── OneMvpActivity.kt │ │ │ │ ├── OneMvpListActivity.kt │ │ │ │ ├── OneRxMvpActivity.kt │ │ │ │ └── OneRxMvpListActivity.kt │ │ │ ├── fragment │ │ │ │ ├── OneMvpFragment.kt │ │ │ │ ├── OneMvpListFragment.kt │ │ │ │ ├── OneRxMvpFragment.kt │ │ │ │ └── OneRxMvpListFragment.kt │ │ │ ├── model │ │ │ │ └── OneMvpModel.kt │ │ │ ├── presenter │ │ │ │ ├── OneMvpPresenter.kt │ │ │ │ └── impl │ │ │ │ │ └── OneMvpPresenterImpl.kt │ │ │ └── view │ │ │ │ └── OneMvpView.kt │ │ │ ├── mvvm │ │ │ ├── activity │ │ │ │ └── OneMvvmActivity.kt │ │ │ ├── fragment │ │ │ │ └── OneMvvmFragment.kt │ │ │ ├── model │ │ │ │ └── OneMvvmModel.kt │ │ │ └── viewmodel │ │ │ │ └── OneMvvmViewModel.kt │ │ │ └── rxrequest │ │ │ ├── activity │ │ │ ├── OneRxActivity.kt │ │ │ └── OneRxListActivity.kt │ │ │ ├── common │ │ │ ├── HttpCommonInterceptor.kt │ │ │ ├── ObserverResult.kt │ │ │ ├── OneObserver.kt │ │ │ ├── OneObserver1.kt │ │ │ ├── OneObserver2.kt │ │ │ ├── OneResponse.kt │ │ │ ├── ResponseResult.kt │ │ │ ├── ResponseResult1.kt │ │ │ ├── ResponseResult2.kt │ │ │ └── RetryInterceptor.kt │ │ │ ├── fragment │ │ │ ├── OneRxFragment.kt │ │ │ └── OneRxListFragment.kt │ │ │ ├── loader │ │ │ └── OneLoader.kt │ │ │ └── service │ │ │ ├── OneService.kt │ │ │ └── RetrofitServiceManager.kt │ └── res │ │ ├── drawable │ │ ├── bg_round_white.xml │ │ ├── circle_text_bg.xml │ │ ├── empty_no_data.png │ │ ├── ic_loading.png │ │ ├── load_error.png │ │ ├── loading.xml │ │ ├── loading_0.png │ │ ├── loading_1.png │ │ ├── loading_10.png │ │ ├── loading_11.png │ │ ├── loading_12.png │ │ ├── loading_2.png │ │ ├── loading_3.png │ │ ├── loading_4.png │ │ ├── loading_5.png │ │ ├── loading_6.png │ │ ├── loading_7.png │ │ ├── loading_8.png │ │ ├── loading_9.png │ │ ├── loading_bg.xml │ │ └── loading_gif.gif │ │ ├── layout │ │ ├── dialog_progress.xml │ │ ├── layout_base_list.xml │ │ ├── layout_tab_button.xml │ │ └── view_empty.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cn │ └── onestravel │ └── library │ └── common │ └── one │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 | 116 | 118 |
119 |
-------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 28 7 | defaultConfig { 8 | applicationId "cn.onestravel.kotlin.base" 9 | minSdkVersion 15 10 | targetSdkVersion 28 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(include: ['*.jar'], dir: 'libs') 25 | implementation project(':kotlinbase') 26 | androidTestImplementation 'androidx.test:runner:1.1.0' 27 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 28 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 29 | } 30 | repositories { 31 | mavenCentral() 32 | } 33 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/onestravel/kotlin/demo/mvp/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo.mvp 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("cn.onestravel.kotlin.base.mvp", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/BaseLoader.java: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo; 2 | 3 | import cn.onestravel.library.rxrequest.loader.OneLoader; 4 | import cn.onestravel.library.rxrequest.service.OneService; 5 | import cn.onestravel.library.rxrequest.service.RetrofitServiceManager; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | /** 9 | * @author onestravel 10 | * @createTime 2019-08-03 10:47 11 | * @description TODO 12 | */ 13 | public abstract class BaseLoader extends OneLoader { 14 | @NotNull 15 | @Override 16 | public RetrofitServiceManager createServiceManager() { 17 | return BaseServiceManager.INSTANCE; 18 | } 19 | 20 | 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/BaseServiceManager.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo 2 | 3 | import cn.onestravel.library.rxrequest.service.RetrofitServiceManager 4 | 5 | /** 6 | * @author onestravel 7 | * @createTime 2019-08-03 10:49 8 | * @description TODO 9 | */ 10 | object BaseServiceManager : RetrofitServiceManager() { 11 | override fun getBaseUrl(): String { 12 | return "https://onestravel.cn/" 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo 2 | 3 | 4 | import cn.onestravel.kotlin.demo.model.User 5 | import cn.onestravel.kotlin.demo.mvp.R 6 | import cn.onestravel.library.common.adapter.OneRecyclerAdapter 7 | import cn.onestravel.library.common.adapter.VH 8 | import cn.onestravel.library.rxrequest.activity.OneRxActivity 9 | import cn.onestravel.library.rxrequest.common.OneObserver1 10 | import cn.onestravel.library.rxrequest.common.ResponseResult1 11 | 12 | class MainActivity : OneRxActivity() { 13 | override fun getLayoutId(): Int { 14 | return R.layout.layout_test 15 | } 16 | 17 | val adapter = TestAdapter() 18 | 19 | 20 | override fun initView() { 21 | super.initView() 22 | } 23 | 24 | override fun initListener() { 25 | super.initListener() 26 | 27 | // adapter.setOnItemClick { view, position, data -> 28 | // showToast("点击了条目$position") 29 | // } 30 | // 31 | // adapter.setOnItemLongClick { view, position, data -> 32 | // showToast("长按了条目$position") 33 | // return@setOnItemLongClick true 34 | // } 35 | } 36 | 37 | override fun initData() { 38 | super.initData() 39 | // setAdapter(adapter) 40 | // addData(adapter) 41 | // refreshComplete() 42 | // loadMoreComplete() 43 | // .compose(this.bindToLifecycle()) 44 | 45 | 46 | val userObserver: OneObserver1 = object : OneObserver1() { 47 | override fun onSuccess(result: ResponseResult1) { 48 | 49 | 50 | } 51 | 52 | override fun onFinish() { 53 | super.onFinish() 54 | } 55 | 56 | 57 | } 58 | val loader = OrderRecordLoader() 59 | loader.getOrderDetailInfo(HashMap() as Map) 60 | .compose(bindToLifecycle>()) 61 | .subscribe(userObserver) 62 | } 63 | 64 | private fun addData(adapter: TestAdapter, isRefresh: Boolean = false) { 65 | val list = ArrayList() 66 | val url = "http://static.open-open.com/lib/uploadImg/20150716/20150716115042_431.jpg" 67 | (1..10).forEach { 68 | val user = User() 69 | user.name = "我是张三 $it" 70 | user.headUrl = url 71 | list.add(user) 72 | } 73 | if (isRefresh) { 74 | adapter.setDatas(list) 75 | } else { 76 | adapter.addDatas(list) 77 | } 78 | } 79 | 80 | // override fun refreshDatas() { 81 | // super.refreshDatas() 82 | // getRecyclerView().postDelayed({ 83 | // refreshComplete() 84 | // addData(adapter, true) 85 | // }, 2000) 86 | // } 87 | // 88 | // 89 | // override fun loadMoreDatas() { 90 | // super.loadMoreDatas() 91 | // getRecyclerView().postDelayed({ 92 | // loadMoreComplete() 93 | // addData(adapter) 94 | // }, 2000) 95 | // } 96 | 97 | 98 | } 99 | 100 | 101 | class TestAdapter() : OneRecyclerAdapter() { 102 | override fun onBindVH(holder: VH, position: Int, data: User) { 103 | holder.setText(R.id.tvName, data.name) 104 | holder.setImageUrl(R.id.ivHead, data.headUrl) 105 | // holder.setOnClick(R.id.tvName){ 106 | // showToast(data.name) 107 | // } 108 | } 109 | 110 | override fun getLayoutId(viewType: Int): Int { 111 | return R.layout.layout_item 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/OrderRecordLoader.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo 2 | 3 | 4 | import cn.onestravel.kotlin.demo.model.User 5 | import cn.onestravel.library.rxrequest.common.ResponseResult1 6 | import io.reactivex.Observable 7 | 8 | /** 9 | * 类描述:订单记录请求的相关loader 10 | * 创建人: 11 | * 创建时间:2018/8/23 12 | */ 13 | 14 | class OrderRecordLoader : BaseLoader() { 15 | 16 | 17 | override fun createService(): OrderRecordService { 18 | return mServiceManager.create(OrderRecordService::class.java) 19 | } 20 | 21 | /** 22 | * 请求订单记录列表 23 | * 24 | * @param map 25 | * @return 订单列表的Bean 26 | */ 27 | fun getOrderRecordList(map: Map): Observable { 28 | return observe(mService.getOrderRecordList(map)) 29 | } 30 | 31 | /** 32 | * 请求订单列表的详情 33 | * 34 | * @param map 35 | * @return 详情的Bean 36 | */ 37 | fun getOrderDetailInfo(map: Map): Observable> { 38 | return observe(mService.getOrderDetailInfo(map)) 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/OrderRecordService.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo 2 | 3 | import cn.onestravel.kotlin.demo.model.User 4 | import cn.onestravel.library.rxrequest.common.ResponseResult1 5 | import cn.onestravel.library.rxrequest.service.OneService 6 | import io.reactivex.Observable 7 | import retrofit2.http.FieldMap 8 | import retrofit2.http.FormUrlEncoded 9 | import retrofit2.http.POST 10 | 11 | /** 12 | * 类描述:订单记录相关的请求service 13 | * 创建人: 14 | * 创建时间:2018/8/23 15 | */ 16 | 17 | interface OrderRecordService : OneService { 18 | //获取订单记录列表 19 | @FormUrlEncoded 20 | @POST("orderList") 21 | fun getOrderRecordList(@FieldMap map: Map): Observable 22 | 23 | //获取订单详情 24 | @FormUrlEncoded 25 | @POST("orderDetail") 26 | fun getOrderDetailInfo(@FieldMap map: Map): Observable> 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/model/User.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo.model 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * @name cn.onestravel.kotlin.base.mvp.user 7 | * @description //TODO 8 | * @createTime 2018/11/30 14:49 9 | * @author onestravel 10 | * @version 1.0.0 11 | */ 12 | 13 | class User:Serializable{ 14 | var name:String ="" 15 | var headUrl:String ="" 16 | var age:Int =0 17 | var sex:String ="男" 18 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/model/UserModel.java: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo.model; 2 | 3 | import cn.onestravel.library.mvp.model.OneMvpModel; 4 | 5 | /** 6 | * @author onestravel 7 | * @createTime 2019-08-04 00:12 8 | * @description TODO 9 | */ 10 | public class UserModel implements OneMvpModel { 11 | public String getUserName(){ 12 | return ""; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/presenter/impl/UserPresenterImpl.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo.presenter.impl 2 | 3 | import cn.onestravel.kotlin.demo.model.UserModel 4 | import cn.onestravel.kotlin.demo.presenter.interf.UserPresenter 5 | import cn.onestravel.kotlin.demo.view.UserView 6 | import cn.onestravel.library.mvp.presenter.impl.OneMvpPresenterImpl 7 | 8 | /** 9 | * @name cn.onestravel.kotlin.base.mvp.mPresenter.impl.UserPresenterImpl 10 | * @description //TODO 11 | * @createTime 2018/12/26 14:48 12 | * @author onestravel 13 | * @version 1.0.0 14 | */ 15 | class UserPresenterImpl: OneMvpPresenterImpl(), 16 | UserPresenter { 17 | override fun init() { 18 | } 19 | 20 | override fun createModel(): UserModel { 21 | return UserModel() 22 | } 23 | 24 | override fun requestUserInfo() { 25 | 26 | } 27 | 28 | override fun requestUserList(page: Int) { 29 | 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/presenter/interf/UserPresenter.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo.presenter.interf 2 | 3 | import cn.onestravel.kotlin.demo.view.UserView 4 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 5 | 6 | /** 7 | * @name cn.onestravel.kotlin.base.mvp.mPresenter.interf.UserPresenter 8 | * @description //TODO 9 | * @createTime 2018/12/26 14:36 10 | * @author onestravel 11 | * @version 1.0.0 12 | */ 13 | interface UserPresenter: OneMvpPresenter { 14 | fun requestUserInfo() 15 | fun requestUserList(page:Int) 16 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/ui/activity/UserActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo.ui.activity 2 | 3 | import cn.onestravel.kotlin.demo.mvp.R 4 | import cn.onestravel.kotlin.demo.presenter.impl.UserPresenterImpl 5 | import cn.onestravel.kotlin.demo.presenter.interf.UserPresenter 6 | import cn.onestravel.kotlin.demo.view.UserView 7 | import cn.onestravel.library.mvp.activity.OneMvpActivity 8 | 9 | /** 10 | * @name cn.onestravel.kotlin.base.mvp.ui.activity.UserActivity 11 | * @description //TODO 12 | * @createTime 2018/12/26 14:52 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | class UserActivity: OneMvpActivity() { 17 | override fun createPresenter(): UserPresenter { 18 | return UserPresenterImpl() 19 | } 20 | 21 | override fun getLayoutId(): Int { 22 | return R.layout.activity_main 23 | } 24 | 25 | 26 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/onestravel/kotlin/demo/view/UserView.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo.view 2 | 3 | import cn.onestravel.kotlin.demo.model.User 4 | import cn.onestravel.library.mvp.view.OneMvpView 5 | 6 | /** 7 | * @name cn.onestravel.kotlin.base.mvp.view.UserView 8 | * @description //TODO 9 | * @createTime 2018/12/26 14:40 10 | * @author onestravel 11 | * @version 1.0.0 12 | */ 13 | interface UserView:OneMvpView { 14 | fun setUserInfo(user: User) 15 | 16 | fun setUserList(list:MutableList) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/test/MainContract.kt: -------------------------------------------------------------------------------- 1 | package cn.test 2 | 3 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 4 | import cn.onestravel.library.mvp.view.OneMvpView 5 | 6 | /** 7 | * @name cn.onestravel.library.kotlin.mvp.MainContract 8 | * @description //TODO 9 | * @createTime 2018/12/12 17:14 10 | * @author onestravel 11 | * @version 1.0.0 12 | */ 13 | 14 | public interface IMainView : OneMvpView { 15 | 16 | /** 17 | * 测试 18 | */ 19 | fun setTestContent() 20 | } 21 | 22 | public interface IMainPresenter : OneMvpPresenter { 23 | 24 | /** 25 | * 测试 26 | */ 27 | fun requestTestContent() 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/cn/test/MainPresenterImpl.kt: -------------------------------------------------------------------------------- 1 | package cn.test 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.kotlin.demo.model.UserModel 5 | import cn.onestravel.library.mvp.presenter.impl.OneMvpPresenterImpl 6 | 7 | /** 8 | * @name cn.test.MainPresenterImpl 9 | * @description //TODO 10 | * @createTime 2018/12/12 17:27 11 | * @author onestravel 12 | * @version 1.0.0 13 | */ 14 | class MainPresenterImpl : OneMvpPresenterImpl(), IMainPresenter { 15 | override fun createModel(): UserModel? { 16 | return null 17 | } 18 | 19 | 20 | override fun init() { 21 | } 22 | 23 | 24 | 25 | override fun requestTestContent() { 26 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 27 | } 28 | 29 | override fun onMvpAttachView(view: IMainView, savedInstanceState: Bundle?) { 30 | super.onMvpAttachView(view, savedInstanceState) 31 | } 32 | 33 | override fun onMvpStart() { 34 | super.onMvpStart() 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/test/TestMainActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.test 2 | 3 | import cn.onestravel.kotlin.demo.mvp.R 4 | import cn.onestravel.library.mvp.activity.OneMvpActivity 5 | 6 | /** 7 | * @name cn.test.TestMainActivity 8 | * @description //TODO 9 | * @createTime 2018/12/12 17:15 10 | * @author onestravel 11 | * @version 1.0.0 12 | */ 13 | class TestMainActivity: OneMvpActivity() { 14 | override fun createPresenter(): IMainPresenter { 15 | return MainPresenterImpl() 16 | } 17 | 18 | override fun getLayoutId(): Int { 19 | return R.layout.activity_main 20 | } 21 | 22 | override fun initData() { 23 | super.initData() 24 | 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/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/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MVPBaseForKotlin 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/cn/onestravel/kotlin/demo/mvp/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.kotlin.demo.mvp 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 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.3.10' 5 | ext.anko_version = '0.10.4' 6 | repositories { 7 | google() 8 | jcenter() 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.2.1' 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | jcenter() 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | android.useAndroidX=true 23 | android.enableJetifier=true 24 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | :omega 85 | -------------------------------------------------------------------------------- /kotlinbase/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /kotlinbase/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-kapt' 4 | apply plugin: 'kotlin-android-extensions' 5 | 6 | android { 7 | compileSdkVersion 29 8 | 9 | 10 | defaultConfig { 11 | minSdkVersion 15 12 | targetSdkVersion 29 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | buildToolsVersion = '29.0.2' 25 | kapt { 26 | generateStubs = true 27 | } 28 | } 29 | 30 | dependencies { 31 | api fileTree(include: ['*.jar'], dir: 'libs') 32 | api 'androidx.appcompat:appcompat:1.1.0' 33 | api 'com.google.android.material:material:1.0.0' 34 | api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 35 | api "org.jetbrains.anko:anko:$anko_version" 36 | api 'androidx.constraintlayout:constraintlayout:1.1.3' 37 | api 'androidx.core:core-ktx:1.0.2' 38 | api 'com.android.support:design' 39 | api 'androidx.legacy:legacy-support-v4:1.0.0' 40 | 41 | api 'com.github.bumptech.glide:glide:4.8.0' 42 | kapt 'com.github.bumptech.glide:compiler:4.8.0' 43 | 44 | // RxJava2 45 | // implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' 46 | api "io.reactivex.rxjava2:rxjava:2.1.9" 47 | api "io.reactivex.rxjava2:rxandroid:2.0.2" 48 | api 'com.trello.rxlifecycle3:rxlifecycle:3.1.0' 49 | api 'com.trello.rxlifecycle3:rxlifecycle-android:3.1.0' 50 | // If you want to use Android Lifecycle for providers 51 | api 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.1.0' 52 | api 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0' 53 | 54 | api 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' 55 | api 'com.squareup.retrofit2:retrofit:2.3.0' 56 | api 'com.squareup.retrofit2:converter-gson:2.3.0' 57 | api 'com.squareup.retrofit2:converter-scalars:2.3.0' 58 | api 'com.squareup.okhttp3:okhttp:3.10.0' 59 | api 'com.alibaba:fastjson:1.2.47' 60 | } 61 | -------------------------------------------------------------------------------- /kotlinbase/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 | -------------------------------------------------------------------------------- /kotlinbase/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/GlobalGlideConfig.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common 2 | 3 | import android.content.Context 4 | import com.bumptech.glide.Glide 5 | import com.bumptech.glide.Registry 6 | import com.bumptech.glide.annotation.GlideModule 7 | import com.bumptech.glide.module.LibraryGlideModule 8 | 9 | /** 10 | */ 11 | @GlideModule 12 | class GlobalGlideConfig : LibraryGlideModule() { 13 | override fun registerComponents( 14 | context: Context, 15 | glide: Glide, 16 | registry: Registry 17 | ) { 18 | super.registerComponents(context, glide, registry) 19 | } 20 | 21 | 22 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/activity/OneActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.activity 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import org.jetbrains.anko.AnkoLogger 6 | import org.jetbrains.anko.startActivity 7 | import org.jetbrains.anko.toast 8 | 9 | /** 10 | * @name OneActivity 11 | * @description 所有Activity的基类 12 | * @createTime 2018/11/28 17:52 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneActivity : AppCompatActivity(),AnkoLogger { 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | setContentView(getLayoutId()) 21 | initView() 22 | initListener() 23 | initData() 24 | } 25 | 26 | 27 | /** 28 | * 获取布局ID,子类必须实现 29 | */ 30 | protected abstract fun getLayoutId(): Int 31 | 32 | 33 | /** 34 | * 初始化 View 的相关操作,若有需要可在子类实现 35 | */ 36 | protected open fun initView() {} 37 | 38 | /** 39 | * 初始化 Listener 事件的相关操作,若有需要可在子类实现 40 | */ 41 | protected open fun initListener() {} 42 | 43 | 44 | /** 45 | * 初始化 Data 数据的相关操作,若有需要可在子类实现 46 | */ 47 | protected open fun initData() {} 48 | 49 | 50 | /** 51 | * 在主线程弹出Toast 提示 52 | * @param msg 需要弹出的提示信息 53 | */ 54 | protected open fun showToast(msg:String){ 55 | runOnUiThread { 56 | toast(msg) 57 | } 58 | } 59 | 60 | /** 61 | * 在主线程弹出Toast 提示 62 | * @param stringRes 需要弹出的提示信息的string资源ID 63 | */ 64 | protected open fun showToast(stringRes:Int){ 65 | runOnUiThread { 66 | toast(getString(stringRes)) 67 | } 68 | } 69 | 70 | /** 71 | * 跳转到另一个Activity,并且finish 掉当前Activity 72 | * 需要跳转的Activity必须继承于BaseActivity 或者 73 | * @param params 可变参数,需要通过intent传递的参数 eg:"key" to "value" 74 | */ 75 | inline fun startActivityAndFinish(vararg params: Pair) { 76 | startActivity(*params) 77 | finish() 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/activity/OneListActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.activity 2 | 3 | import android.graphics.Color 4 | import androidx.annotation.ColorInt 5 | import androidx.annotation.ColorRes 6 | import cn.onestravel.library.common.one.R 7 | import cn.onestravel.library.common.adapter.OneRecyclerAdapter 8 | import cn.onestravel.library.common.view.ClassicalFooter 9 | import cn.onestravel.library.common.view.LoadMoreRecyclerView 10 | import kotlinx.android.synthetic.main.layout_base_list.* 11 | 12 | /** 13 | * @name OneListActivity 14 | * @description 默认含有RecyclerView的可下拉刷新,上拉加载(可隐藏)Activity基类 15 | * @createTime 2018/11/28 18:02 16 | * @author onestravel 17 | * @version 1.0.0 18 | */ 19 | open class OneListActivity : OneActivity() { 20 | 21 | /** 22 | * 初始化布局ID 23 | */ 24 | override fun getLayoutId(): Int { 25 | return R.layout.layout_base_list 26 | } 27 | 28 | /** 29 | * 初始化View 的相关操作 30 | */ 31 | override fun initView() { 32 | super.initView() 33 | mRecyclerView.layoutManager = getLayoutManager() 34 | mRefreshLayout.setColorSchemeColors(Color.RED, Color.BLUE, Color.GREEN) 35 | mRecyclerView.setLoadMoreView(ClassicalFooter(this)) 36 | } 37 | 38 | /** 39 | * 初始化View的相关事件 40 | */ 41 | override fun initListener() { 42 | super.initListener() 43 | mRefreshLayout.setOnRefreshListener { 44 | refreshDatas() 45 | } 46 | mRecyclerView.setLoadMoreListener { 47 | loadMoreDatas() 48 | } 49 | } 50 | 51 | 52 | protected fun getRecyclerView():LoadMoreRecyclerView{ 53 | return mRecyclerView 54 | } 55 | 56 | /** 57 | * 获取recyclerView的布局管理器,子类可重写该方法,来更改布局管理器 58 | */ 59 | protected open fun getLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager { 60 | val layoutManager: androidx.recyclerview.widget.LinearLayoutManager = 61 | androidx.recyclerview.widget.LinearLayoutManager(this) 62 | //设置为垂直布局,这也是默认的 63 | layoutManager.orientation = androidx.recyclerview.widget.OrientationHelper.VERTICAL 64 | return layoutManager 65 | } 66 | 67 | 68 | /** 69 | * 设置RecyclerView 的Adapter适配器 70 | * @param adapter 设置的Adapter,必须是BaseRecyclerAdapter的子类 71 | */ 72 | protected fun setAdapter(adapter: OneRecyclerAdapter) { 73 | mRecyclerView.adapter = adapter 74 | } 75 | 76 | /** 77 | * 设置刷新控件的颜色 78 | */ 79 | protected fun setRefreshColorSchemeColors(@ColorInt vararg colors: Int) { 80 | mRefreshLayout.setColorSchemeColors(*colors) 81 | } 82 | /** 83 | * 设置刷新控件的颜色 84 | */ 85 | protected fun setColorSchemeResources(@ColorRes vararg colorIds: Int) { 86 | mRefreshLayout.setColorSchemeResources(*colorIds) 87 | } 88 | 89 | /** 90 | * 设置刷新控件是否显示 91 | */ 92 | protected fun isRefresh(isRefresh: Boolean) { 93 | mRefreshLayout.isRefreshing = false 94 | } 95 | 96 | /** 97 | * 刷新完成 98 | */ 99 | protected fun refreshComplete() { 100 | mRefreshLayout.isRefreshing = false 101 | } 102 | 103 | /** 104 | * 刷新数据,子类实现该方法,进行数据请求 105 | */ 106 | protected open fun refreshDatas() { 107 | 108 | } 109 | 110 | /** 111 | * 加载更多完成 112 | */ 113 | protected fun loadMoreComplete() { 114 | mRecyclerView.loadMoreComplete(true) 115 | } 116 | 117 | /** 118 | * 设置是否可以加载更多 119 | */ 120 | protected fun canLoadMore(canLoadMore: Boolean) { 121 | mRecyclerView.loadMoreEnable = canLoadMore 122 | } 123 | 124 | /** 125 | * 设置是否还有更多的数据 126 | */ 127 | protected fun hasLoadMore(hasLoadMore: Boolean) { 128 | mRecyclerView.hasMore = hasLoadMore 129 | } 130 | 131 | /** 132 | * 加载新数据,子类实现该方法,进行数据请求 133 | */ 134 | protected open fun loadMoreDatas() { 135 | 136 | } 137 | 138 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/adapter/OneRecyclerAdapter.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.adapter 2 | 3 | import android.content.Context 4 | import android.content.res.ColorStateList 5 | import android.graphics.Bitmap 6 | import android.graphics.ColorFilter 7 | import android.graphics.drawable.Drawable 8 | import android.text.Spannable 9 | import android.text.TextUtils 10 | import android.view.LayoutInflater 11 | import android.view.View 12 | import android.view.ViewGroup 13 | import android.widget.CompoundButton 14 | import android.widget.ImageView 15 | import android.widget.TextView 16 | import androidx.annotation.* 17 | import androidx.recyclerview.widget.RecyclerView 18 | import cn.onestravel.library.common.extend.loadImage 19 | import cn.onestravel.library.common.one.R 20 | import org.jetbrains.anko.find 21 | import org.jetbrains.anko.imageResource 22 | import org.jetbrains.anko.runOnUiThread 23 | import org.jetbrains.anko.toast 24 | 25 | 26 | /** 27 | * @name OneRecyclerAdapter 28 | * @description 所有RecyclerView 的Adapter 的基类 29 | * @createTime 2018/11/29 14:32 30 | * @author onestravel 31 | * @version 1.0.0 32 | */ 33 | abstract class OneRecyclerAdapter : RecyclerView.Adapter(), View.OnClickListener, 34 | View.OnLongClickListener { 35 | private val mDatas: MutableList = ArrayList() 36 | private lateinit var context: Context 37 | private var clickListener: OnItemClickListener? = null 38 | private var longClickListener: OnItemLongClickListener? = null 39 | 40 | 41 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH { 42 | context = parent.context 43 | val convertView = 44 | LayoutInflater.from(parent.context).inflate(getLayoutId(viewType), parent, false) 45 | convertView.setOnClickListener(this) 46 | convertView.setOnLongClickListener(this) 47 | return VH(convertView) 48 | } 49 | 50 | /** 51 | * 设置Item 的点击事件 52 | */ 53 | fun setOnItemClick(listener: OnItemClickListener) { 54 | clickListener = listener 55 | } 56 | 57 | /** 58 | * 设置Item 的点击事件 59 | */ 60 | fun setOnItemClick(onClick: (view: View, position: Int, data: T) -> Unit) { 61 | clickListener = object : OnItemClickListener { 62 | override fun onItemClick(view: View, position: Int, data: T) { 63 | onClick(view, position, data) 64 | } 65 | } 66 | } 67 | 68 | /** 69 | * 设置Item 的长按事件 70 | */ 71 | fun setOnItemLongClick(listener: OnItemLongClickListener) { 72 | longClickListener = listener 73 | } 74 | 75 | /** 76 | * 设置Item 的长按事件 77 | */ 78 | fun setOnItemLongClick(onLongClick: (view: View, position: Int, data: T) -> Boolean) { 79 | longClickListener = object : OnItemLongClickListener { 80 | override fun onItemLongClick(view: View, position: Int, data: T): Boolean { 81 | return onLongClick(view, position, data) 82 | } 83 | } 84 | } 85 | 86 | override fun onClick(p0: View?) { 87 | val position: Int = p0?.getTag(R.id.itemViewPosition) as Int 88 | val data: T = mDatas.get(position) 89 | clickListener?.onItemClick(p0, position, data) 90 | } 91 | 92 | override fun onLongClick(p0: View?): Boolean { 93 | val position: Int = p0?.getTag(R.id.itemViewPosition) as Int 94 | val data: T = mDatas.get(position) 95 | return longClickListener?.onItemLongClick(p0, position, data) ?: true 96 | } 97 | 98 | /** 99 | * 设置数据,并且会清空原数据列表 100 | * @param datas 新的数据列表 101 | */ 102 | open fun setDatas(datas: List) { 103 | mDatas.clear() 104 | mDatas.addAll(datas) 105 | notifyDataSetChanged() 106 | } 107 | 108 | /** 109 | * 添加新的数据列表到原数据列表末尾 110 | * @param datas 新的数据列表 111 | */ 112 | open fun addDatas(datas: List) { 113 | mDatas.addAll(datas) 114 | notifyDataSetChanged() 115 | } 116 | 117 | /** 118 | * 添加新的数据列表到原数据列表的指定位置 119 | * @param position 需要添加的指定位置 120 | * @param datas 新的数据列表 121 | */ 122 | open fun addDatas(position: Int, datas: List) { 123 | val pos = if (position > mDatas.size) { 124 | mDatas.size 125 | } else position 126 | mDatas.addAll(pos, datas) 127 | notifyDataSetChanged() 128 | } 129 | 130 | /** 131 | * 更新数据列表指定位置上的数据 132 | * @param position 需要更新数据的位置 133 | * @param data 更新后的数据 134 | */ 135 | open fun updateData(position: Int, data: T) { 136 | if (position < mDatas.size) { 137 | mDatas.removeAt(position) 138 | mDatas.add(position, data) 139 | notifyItemChanged(position) 140 | } 141 | } 142 | 143 | /** 144 | * 添加新的数据到原数据列表末尾 145 | * @param datas 新的数据 146 | */ 147 | open fun addData(data: T) { 148 | mDatas.add(data) 149 | notifyItemInserted(mDatas.size - 1) 150 | } 151 | 152 | /** 153 | * 添加新的数据到原数据列表的指定位置 154 | * @param position 需要添加的指定位置 155 | * @param data 新的数据 156 | */ 157 | open fun addData(position: Int, data: T) { 158 | val pos = if (position > mDatas.size) { 159 | mDatas.size 160 | } else position 161 | mDatas.add(pos, data) 162 | notifyItemInserted(pos) 163 | } 164 | 165 | /** 166 | * 移除指定位置上的数据 167 | * @param position 需要添加的指定位置 168 | */ 169 | open fun removeDataAt(position: Int) { 170 | if (position < mDatas.size) { 171 | mDatas.removeAt(position) 172 | notifyItemRemoved(position) 173 | } 174 | } 175 | 176 | protected open fun showToast(msg: String) { 177 | context.runOnUiThread { 178 | context.toast(msg) 179 | } 180 | } 181 | 182 | /** 183 | * 移除指定的数据 184 | * @param data 需要移除的数据实体 185 | */ 186 | open fun removeData(data: T) { 187 | if (mDatas.contains(data)) { 188 | val position = mDatas.indexOf(data) 189 | mDatas.removeAt(position) 190 | notifyItemRemoved(position) 191 | } 192 | } 193 | 194 | /** 195 | * 根据View的类型获取对应的Item布局的ID 196 | */ 197 | @LayoutRes 198 | abstract fun getLayoutId(viewType: Int): Int 199 | 200 | 201 | /** 202 | * 绑定ViewHolder 时执行的方法,在此方法里处理对Item的view的操作 203 | */ 204 | abstract fun onBindVH(holder: VH, position: Int, datas: T) 205 | 206 | /** 207 | * 返回数据的数量 208 | */ 209 | override fun getItemCount(): Int { 210 | return mDatas.size 211 | } 212 | 213 | override fun onBindViewHolder(holder: VH, position: Int) { 214 | holder.itemView.setTag(R.id.itemViewPosition, position) 215 | onBindVH(holder, position, mDatas.get(position)) 216 | } 217 | 218 | 219 | } 220 | 221 | /** 222 | *Item 的点击事件 223 | */ 224 | interface OnItemClickListener { 225 | fun onItemClick(view: View, position: Int, data: T) 226 | } 227 | 228 | /** 229 | *Item 的长按事件 230 | */ 231 | interface OnItemLongClickListener { 232 | fun onItemLongClick(view: View, position: Int, data: T): Boolean 233 | } 234 | 235 | /** 236 | * 所有的Adapter 使用的ViewHolder 237 | */ 238 | class VH(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) { 239 | 240 | 241 | /** 242 | * 根据View的id获取对应的View 243 | */ 244 | inline fun getView(@IdRes viewId: Int): E { 245 | return itemView.find(viewId) 246 | } 247 | 248 | /** 249 | * 对TextView及其子类设置文本内容 250 | * @param viewId 对应的View 的id 251 | * @param value 需要设置的文本内容 252 | */ 253 | inline fun setText(@IdRes viewId: Int, value: String) { 254 | val view: View = this.getView(viewId) 255 | if (view is TextView) { 256 | val tv: TextView = view 257 | tv.text = value 258 | } 259 | } 260 | 261 | /** 262 | * 对TextView及其子类设置文本内容 263 | * @param viewId 对应的View 的id 264 | * @param value 需要设置的文本内容 265 | */ 266 | inline fun setText(@IdRes viewId: Int, value: Spannable) { 267 | val view: View = this.getView(viewId) 268 | if (view is TextView) { 269 | val tv: TextView = view 270 | tv.text = value 271 | } 272 | } 273 | 274 | /** 275 | * 对TextView及其子类设置文本内容 276 | * @param viewId 对应的View 的id 277 | * @param stringRes 需要设置的文本资源的id 278 | */ 279 | inline fun setText(@IdRes viewId: Int, @StringRes stringRes: Int) { 280 | val view: View = this.getView(viewId) 281 | if (view is TextView) { 282 | val tv: TextView = view 283 | tv.setText(stringRes) 284 | } 285 | } 286 | 287 | /** 288 | * 对ImageView及其子类设置图片 289 | * @param viewId 对应的View 的id 290 | * @param resId 需要设置的图片资源的id 291 | */ 292 | inline fun setImageResource(@IdRes viewId: Int, @DrawableRes resId: Int) { 293 | val view: View = getView(viewId) 294 | if (view is ImageView) { 295 | val iv: ImageView = view 296 | iv.imageResource = resId 297 | } 298 | } 299 | 300 | /** 301 | * 对ImageView及其子类设置图片 302 | * @param viewId 对应的View 的id 303 | * @param imgUrl 需要设置的网络图片的地址 304 | */ 305 | inline fun setImageUrl(@IdRes viewId: Int, imgUrl: String) { 306 | val view: View = getView(viewId) 307 | if (view is ImageView) { 308 | val iv: ImageView = view 309 | iv.loadImage(imgUrl) 310 | } 311 | } 312 | 313 | /** 314 | * 对ImageView及其子类设置图片 315 | * @param viewId 对应的View 的id 316 | * @param imgUrl 需要设置的网络图片的地址 317 | */ 318 | inline fun setImageUrl(@IdRes viewId: Int, imgUrl: String, width: Int, height: Int) { 319 | val view: View = getView(viewId) 320 | if (view is ImageView) { 321 | val iv: ImageView = view 322 | iv.loadImage(imgUrl,width,height) 323 | } 324 | } 325 | 326 | /** 327 | * 对View及其子类设置背景图片 328 | * @param viewId 对应的View 的id 329 | * @param resId 需要设置的背景图片的资源地址 330 | */ 331 | inline fun setBackgroundResource(@IdRes viewId: Int, @DrawableRes resId: Int) { 332 | val view: View = getView(viewId) 333 | view.setBackgroundResource(resId) 334 | } 335 | 336 | /** 337 | * 对View及其子类设置背景颜色 338 | * @param viewId 对应的View 的id 339 | * @param color 需要设置的背景颜色 340 | */ 341 | inline fun setBackgroundColor(@IdRes viewId: Int, @ColorInt color: Int) { 342 | val view: View = getView(viewId) 343 | view.setBackgroundColor(color) 344 | } 345 | 346 | 347 | /** 348 | * 对View及其子类设置点击事件 349 | * @param viewId 对应的View 的id 350 | * @param color 需要设置的背景颜色 351 | */ 352 | inline fun setOnClick(@IdRes viewId: Int, crossinline onClick: (View) -> Unit) { 353 | val view: View = getView(viewId) 354 | view.setOnClickListener { 355 | onClick.invoke(it) 356 | } 357 | } 358 | 359 | 360 | fun findViewById(@IdRes id: Int): View? { 361 | return itemView.findViewById(id) 362 | } 363 | 364 | 365 | fun setTextSize(@IdRes id: Int, size: Int) { 366 | val view = itemView.findViewById(id) 367 | if (view != null && view is TextView) { 368 | view.textSize = size.toFloat() 369 | } 370 | } 371 | 372 | fun setTextColor(@IdRes id: Int, @ColorInt color: Int) { 373 | val view = itemView.findViewById(id) 374 | if (view != null && view is TextView) { 375 | view.setTextColor(color) 376 | } 377 | } 378 | 379 | fun setTextColor(@IdRes id: Int, color: ColorStateList?) { 380 | val view = itemView.findViewById(id) 381 | if (view != null && view is TextView) { 382 | view.setTextColor(color) 383 | } 384 | } 385 | 386 | fun setImageRes(@IdRes id: Int, @DrawableRes resId: Int) { 387 | val view = itemView.findViewById(id) 388 | if (view != null && view is ImageView) { 389 | view.setImageResource(resId) 390 | } 391 | } 392 | 393 | fun setImageDrawable(@IdRes id: Int, drawable: Drawable?) { 394 | if (drawable == null) { 395 | return 396 | } 397 | val view = itemView.findViewById(id) 398 | if (view != null && view is ImageView) { 399 | view.setImageDrawable(drawable) 400 | } 401 | } 402 | 403 | 404 | fun setImageBitmap(@IdRes id: Int, bitmap: Bitmap?) { 405 | if (bitmap == null) { 406 | return 407 | } 408 | val view = itemView.findViewById(id) 409 | if (view != null && view is ImageView) { 410 | view.setImageBitmap(bitmap) 411 | } 412 | } 413 | 414 | fun setImageColorFilter(@IdRes id: Int, colorFilter: ColorFilter?) { 415 | val view = itemView.findViewById(id) 416 | if (view != null && view is ImageView) { 417 | view.colorFilter = colorFilter 418 | } 419 | } 420 | 421 | 422 | fun setChecked(@IdRes id: Int, checked: Boolean) { 423 | val view = itemView.findViewById(id) 424 | if (view != null && view is CompoundButton) { 425 | view.isChecked = checked 426 | } 427 | } 428 | 429 | fun setSelected(@IdRes id: Int, selected: Boolean) { 430 | val view = itemView.findViewById(id) 431 | if (view != null && view is CompoundButton) { 432 | view.isSelected = selected 433 | } 434 | } 435 | 436 | fun setVisibility(@IdRes id: Int, visibility: Int) { 437 | val view = itemView.findViewById(id) 438 | if (view != null) { 439 | view.visibility = visibility 440 | } 441 | } 442 | 443 | fun setEnable(@IdRes id: Int, enable: Boolean) { 444 | val view = itemView.findViewById(id) 445 | if (view != null) { 446 | view.isEnabled = enable 447 | } 448 | } 449 | 450 | fun setClickable(@IdRes id: Int, clickable: Boolean) { 451 | val view = itemView.findViewById(id) 452 | if (view != null) { 453 | view.isClickable = clickable 454 | } 455 | } 456 | 457 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/extend/ImageViewExtend.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.extend 2 | 3 | import android.graphics.Bitmap 4 | import android.widget.ImageView 5 | import cn.onestravel.library.common.utils.ImageUtils 6 | import com.bumptech.glide.request.RequestListener 7 | 8 | /** 9 | * @name ImageViewExtend 10 | * @description ImageView 加载网络图片的扩展方法 11 | * @createTime 2018/11/29 15:32 12 | * @author onestravel 13 | * @version 1.0.0 14 | */ 15 | 16 | 17 | /** 18 | * 19 | */ 20 | inline fun ImageView.loadImage(imgUrl: String): ImageView { 21 | ImageUtils.loadImageUrl(this.context, imgUrl, this) 22 | return this 23 | } 24 | 25 | inline fun ImageView.loadImage(imgUrl: String, width: Int, height: Int): ImageView { 26 | ImageUtils.loadImageUrl(this.context, imgUrl, this,width, height) 27 | return this 28 | } 29 | 30 | inline fun ImageView.loadBitmap(imgUrl: String): ImageView { 31 | ImageUtils.loadImageBitmap(this.context, imgUrl, this) 32 | return this 33 | } 34 | 35 | inline fun ImageView.loadGif(imgUrl: String): ImageView { 36 | ImageUtils.loadImageGif(this.context, imgUrl, this) 37 | return this 38 | } 39 | 40 | inline fun ImageView.loadImgCallBack(imgUrl: String, requestListener: RequestListener): ImageView { 41 | ImageUtils.loadImageCallBack(this.context, imgUrl, this, requestListener) 42 | return this 43 | } 44 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/fragment/OneFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.fragment 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import org.jetbrains.anko.* 8 | 9 | /** 10 | * @name OneFragment 11 | * @description 所有 Fragment 的基类 12 | * @createTime 2018/11/28 18:22 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneFragment : androidx.fragment.app.Fragment(), AnkoLogger { 17 | 18 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 19 | val view = inflater.inflate(getLayoutId(), null) 20 | initView(view) 21 | initListener(view) 22 | return view 23 | } 24 | 25 | override fun onActivityCreated(savedInstanceState: Bundle?) { 26 | super.onActivityCreated(savedInstanceState) 27 | initData() 28 | } 29 | 30 | 31 | /** 32 | * 获取布局ID,子类必须实现 33 | */ 34 | protected abstract fun getLayoutId(): Int 35 | 36 | 37 | /** 38 | * 初始化 View 的相关操作,若有需要可在子类实现 39 | */ 40 | protected open fun initView(contentView: View) {} 41 | 42 | /** 43 | * 初始化 Listener 事件的相关操作,若有需要可在子类实现 44 | */ 45 | protected open fun initListener(contentView: View) {} 46 | 47 | 48 | /** 49 | * 初始化 Data 数据的相关操作,若有需要可在子类实现 50 | */ 51 | protected open fun initData() {} 52 | 53 | 54 | /** 55 | * 在主线程弹出Toast 提示 56 | * @param msg 需要弹出的提示信息 57 | */ 58 | protected open fun showToast(msg: String) { 59 | activity!!.runOnUiThread { 60 | activity!!.toast(msg) 61 | } 62 | } 63 | 64 | /** 65 | * 在主线程弹出Toast 提示 66 | * @param stringRes 需要弹出的提示信息的string资源ID 67 | */ 68 | protected open fun showToast(stringRes: Int) { 69 | activity!!.runOnUiThread { 70 | activity!!.toast(getString(stringRes)) 71 | } 72 | } 73 | 74 | 75 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/fragment/OneListFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.fragment 2 | 3 | import android.graphics.Color 4 | import androidx.annotation.ColorInt 5 | import androidx.annotation.ColorRes 6 | import android.view.View 7 | import cn.onestravel.library.common.one.R 8 | import cn.onestravel.library.common.adapter.OneRecyclerAdapter 9 | import kotlinx.android.synthetic.main.layout_base_list.* 10 | 11 | /** 12 | * @name OneListFragment 13 | * @description 默认含有RecyclerView的可下拉刷新,上拉加载(可隐藏)Fragment基类 14 | * @createTime 2018/11/28 18:25 15 | * @author onestravel 16 | * @version 1.0.0 17 | */ 18 | open class OneListFragment:OneFragment() { 19 | override fun getLayoutId(): Int { 20 | return R.layout.layout_base_list 21 | } 22 | 23 | /** 24 | * 初始化View 的相关操作 25 | */ 26 | override fun initView(contentView: View) { 27 | super.initView(contentView) 28 | mRecyclerView.layoutManager = getLayoutManager() 29 | mRefreshLayout.setColorSchemeColors(Color.RED, Color.BLUE, Color.GREEN) 30 | } 31 | 32 | /** 33 | * 初始化View的相关事件 34 | */ 35 | override fun initListener(contentView:View) { 36 | super.initListener(contentView) 37 | mRefreshLayout.setOnRefreshListener { 38 | refreshDatas() 39 | } 40 | mRecyclerView.setLoadMoreListener { 41 | loadMoreDatas() 42 | } 43 | } 44 | 45 | /** 46 | * 获取recyclerView的布局管理器,子类可重写该方法,来更改布局管理器 47 | */ 48 | protected open fun getLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager { 49 | val layoutManager: androidx.recyclerview.widget.LinearLayoutManager = 50 | androidx.recyclerview.widget.LinearLayoutManager(context) 51 | //设置为垂直布局,这也是默认的 52 | layoutManager.orientation = androidx.recyclerview.widget.OrientationHelper.VERTICAL 53 | return layoutManager 54 | } 55 | 56 | 57 | /** 58 | * 设置RecyclerView 的Adapter适配器 59 | * @param adapter 设置的Adapter,必须是BaseRecyclerAdapter的子类 60 | */ 61 | protected fun setAdapter(adapter: OneRecyclerAdapter) { 62 | mRecyclerView.adapter = adapter 63 | } 64 | 65 | /** 66 | * 设置刷新控件的颜色 67 | */ 68 | protected fun setRefreshColorSchemeColors(@ColorInt vararg colors: Int) { 69 | mRefreshLayout.setColorSchemeColors(*colors) 70 | } 71 | /** 72 | * 设置刷新控件的颜色 73 | */ 74 | protected fun setColorSchemeResources(@ColorRes vararg colorIds: Int) { 75 | mRefreshLayout.setColorSchemeResources(*colorIds) 76 | } 77 | 78 | /** 79 | * 设置刷新控件是否显示 80 | */ 81 | protected fun isRefresh(isRefresh: Boolean) { 82 | mRefreshLayout.isRefreshing = false 83 | } 84 | 85 | /** 86 | * 刷新完成 87 | */ 88 | protected fun refreshComplete() { 89 | mRefreshLayout.isRefreshing = false 90 | } 91 | 92 | /** 93 | * 刷新数据,子类实现该方法,进行数据请求 94 | */ 95 | protected open fun refreshDatas() { 96 | 97 | } 98 | 99 | /** 100 | * 加载更多完成 101 | */ 102 | protected fun loadMoreComplete() { 103 | mRecyclerView.loadMoreComplete(true) 104 | } 105 | 106 | /** 107 | * 设置是否可以加载更多 108 | */ 109 | protected fun canLoadMore(canLoadMore: Boolean) { 110 | mRecyclerView.loadMoreEnable = canLoadMore 111 | } 112 | 113 | /** 114 | * 设置是否还有更多的数据 115 | */ 116 | protected fun hasLoadMore(hasLoadMore: Boolean) { 117 | mRecyclerView.hasMore = hasLoadMore 118 | } 119 | 120 | /** 121 | * 加载新数据,子类实现该方法,进行数据请求 122 | */ 123 | protected open fun loadMoreDatas() { 124 | 125 | } 126 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/utils/DensityUtil.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.utils 2 | 3 | import android.content.res.Resources 4 | 5 | /** 6 | * @name DensityUtil 7 | * @description 尺寸转换工具类 8 | * @createTime 2018/11/30 15:27 9 | * @author onestravel 10 | * @version 1.0.0 11 | */ 12 | object DensityUtil { 13 | val density = Resources.getSystem().getDisplayMetrics().density 14 | 15 | /** 16 | * dip转换为px 17 | */ 18 | fun dip2px(dp: Int): Int { 19 | return (dp * density).toInt() 20 | } 21 | 22 | 23 | /** 24 | * px转换为dip 25 | */ 26 | fun px2dip(px: Float): Int { 27 | return (px / density).toInt() 28 | } 29 | 30 | /** 31 | * 获取屏幕宽度 32 | */ 33 | fun appWidth(): Int { 34 | return Resources.getSystem().getDisplayMetrics().widthPixels 35 | } 36 | 37 | /** 38 | * 获取屏幕高度 39 | */ 40 | fun appHeight(): Int { 41 | return Resources.getSystem().getDisplayMetrics().heightPixels 42 | } 43 | 44 | 45 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/utils/ImageUtils.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.utils 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.graphics.Canvas 6 | import android.graphics.drawable.BitmapDrawable 7 | import android.graphics.drawable.ColorDrawable 8 | import android.graphics.drawable.Drawable 9 | import android.widget.ImageView 10 | import com.bumptech.glide.Glide 11 | import com.bumptech.glide.request.RequestListener 12 | 13 | /** 14 | * @name ImageUtils1 15 | * @description 实现使用图片加载框架加载网络图片 16 | * @createTime 2018/11/29 15:01 17 | * @author onestravel 18 | * @version 1.0.0 19 | */ 20 | object ImageUtils{ 21 | private val BITMAP_CONFIG = Bitmap.Config.ARGB_8888 22 | private const val COLORDRAWABLE_DIMENSION = 2 23 | fun loadImageUrl(context:Context,imgUrl:String,imageView: ImageView){ 24 | Glide.with(context).load(imgUrl).into(imageView) 25 | } 26 | 27 | fun loadImageUrl(context:Context,imgUrl:String,imageView: ImageView, width: Int, height: Int){ 28 | Glide.with(context).load(imgUrl).into(imageView) 29 | } 30 | 31 | fun loadImageBitmap(context:Context,imgUrl:String,imageView: ImageView){ 32 | Glide.with(context).asBitmap().load(imgUrl).into(imageView) 33 | } 34 | 35 | fun loadImageGif(context:Context,imgUrl:String,imageView: ImageView){ 36 | Glide.with(context).asGif().load(imgUrl).into(imageView) 37 | } 38 | 39 | fun loadImageCallBack(context:Context,imgUrl:String,imageView: ImageView,requestListener: RequestListener){ 40 | Glide.with(context).asBitmap().load(imgUrl).addListener(requestListener).into(imageView) 41 | } 42 | 43 | 44 | fun getBitmapFromDrawable(drawable: Drawable?): Bitmap? { 45 | if (drawable == null) { 46 | return null 47 | } 48 | 49 | if (drawable is BitmapDrawable) { 50 | return drawable.bitmap 51 | } 52 | 53 | try { 54 | val bitmap: Bitmap 55 | 56 | if (drawable is ColorDrawable) { 57 | bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG) 58 | } else { 59 | bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, BITMAP_CONFIG) 60 | } 61 | 62 | val canvas = Canvas(bitmap) 63 | drawable.setBounds(0, 0, canvas.width, canvas.height) 64 | drawable.draw(canvas) 65 | return bitmap 66 | } catch (e: Exception) { 67 | e.printStackTrace() 68 | return null 69 | } 70 | 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/view/CircleTextView.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.view 2 | 3 | import android.content.Context 4 | import android.graphics.Canvas 5 | import android.graphics.Color 6 | import android.graphics.Paint 7 | import android.graphics.PaintFlagsDrawFilter 8 | import androidx.appcompat.widget.AppCompatTextView 9 | import android.util.AttributeSet 10 | 11 | /** 12 | * @author onestravel 13 | * @version 1.0.0 14 | * @projectName BrZhongYiAndroid 15 | * @desctrion 自定义圆形的TextView,以适应不同的显示需求 16 | * @createTime 2017/7/7.˙ 17 | */ 18 | class CircleTextView : AppCompatTextView { 19 | 20 | private val mBgPaint = Paint() 21 | 22 | private var pfd = PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG) 23 | 24 | constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { 25 | // TODO Auto-generated constructor stub 26 | } 27 | 28 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { 29 | // TODO Auto-generated constructor stub 30 | mBgPaint.color = Color.WHITE 31 | mBgPaint.isAntiAlias = true 32 | } 33 | 34 | constructor(context: Context) : super(context) { 35 | // TODO Auto-generated constructor stub 36 | mBgPaint.color = Color.WHITE 37 | mBgPaint.isAntiAlias = true 38 | } 39 | 40 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 41 | // TODO Auto-generated method stub 42 | super.onMeasure(widthMeasureSpec, heightMeasureSpec) 43 | val measuredWidth = measuredWidth 44 | val measuredHeight = measuredHeight 45 | val max = Math.max(measuredWidth, measuredHeight) 46 | setMeasuredDimension(max, max) 47 | } 48 | 49 | override fun setBackgroundColor(color: Int) { 50 | // TODO Auto-generated method stub 51 | mBgPaint.color = color 52 | } 53 | 54 | /** 55 | * 设置通知个数显示 56 | * @param text 57 | */ 58 | fun setNotifiText(text: Int) { 59 | setText(text.toString() + "") 60 | } 61 | 62 | override fun draw(canvas: Canvas) { 63 | // TODO Auto-generated method stub 64 | canvas.drawFilter = pfd 65 | canvas.drawCircle( 66 | (width / 2).toFloat(), 67 | (height / 2).toFloat(), 68 | (Math.max(width, height) / 2).toFloat(), 69 | mBgPaint 70 | ) 71 | super.draw(canvas) 72 | } 73 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/view/ClassicalFooter.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.view 2 | 3 | import android.content.Context 4 | import android.graphics.Color 5 | import androidx.annotation.AttrRes 6 | import android.util.AttributeSet 7 | import android.view.Gravity 8 | import android.view.View 9 | import android.view.animation.Animation 10 | import android.view.animation.LinearInterpolator 11 | import android.view.animation.RotateAnimation 12 | import android.widget.FrameLayout 13 | import android.widget.ImageView 14 | import android.widget.LinearLayout 15 | import android.widget.TextView 16 | 17 | import cn.onestravel.library.common.utils.DensityUtil 18 | 19 | /** 20 | * @author onestravel 21 | * @version 1.0.0 22 | * @name ClassicalFooter 23 | * @description 经典上拉加载 24 | * @createTime 2018/11/30 15:23 25 | */ 26 | class ClassicalFooter @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) : FrameLayout(context, attrs, defStyleAttr), LoadMoreView { 27 | private var recyclerView: LoadMoreRecyclerView? = null 28 | private val arrawImg: ImageView 29 | private val textTitle: TextView 30 | private val rotateAnimation = RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f) 31 | 32 | init { 33 | val root = LinearLayout(context) 34 | root.orientation = LinearLayout.HORIZONTAL 35 | root.gravity = Gravity.CENTER 36 | addView(root, FrameLayout.LayoutParams.MATCH_PARENT, DensityUtil.dip2px(50)) 37 | (root.layoutParams as FrameLayout.LayoutParams).gravity = Gravity.CENTER 38 | arrawImg = ImageView(context) 39 | // arrawImg.layoutParams = LayoutParams(50,50) 40 | // arrawImg.padding = 5 41 | // arrawImg.setImageResource(R.drawable.ic_loading) 42 | // arrawImg.scaleType = ImageView.ScaleType.CENTER 43 | // root.addView(arrawImg) 44 | textTitle = TextView(context) 45 | textTitle.textSize =16f 46 | textTitle.text = "上拉或点击加载更多..." 47 | textTitle.setTextColor(Color.parseColor("#999999")) 48 | val params = LinearLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT) 49 | params.leftMargin = 20 50 | root.addView(textTitle, params) 51 | rotateAnimation.duration = 800 52 | rotateAnimation.interpolator = LinearInterpolator() 53 | rotateAnimation.repeatCount = Animation.INFINITE 54 | rotateAnimation.repeatMode = Animation.RESTART 55 | setPadding(0, 1, 0, 1) 56 | setOnClickListener { recyclerView!!.startLoadMore() } 57 | } 58 | 59 | 60 | override fun shouldLoadMore(recyclerView: LoadMoreRecyclerView): Boolean { 61 | this.recyclerView = recyclerView 62 | return false 63 | } 64 | 65 | 66 | override fun onLoadMore(recyclerView: LoadMoreRecyclerView) { 67 | arrawImg.visibility = View.VISIBLE 68 | arrawImg.startAnimation(rotateAnimation) 69 | textTitle.text = "正在加载..." 70 | } 71 | 72 | 73 | override fun onComplete(recyclerView: LoadMoreRecyclerView, hasMore: Boolean) { 74 | arrawImg.clearAnimation() 75 | textTitle.text = if (hasMore) "上拉或点击加载更多..." else "没有更多数据" 76 | arrawImg.visibility = View.GONE 77 | } 78 | 79 | 80 | override fun onError(recyclerView: LoadMoreRecyclerView, errorCode: Int) { 81 | arrawImg.clearAnimation() 82 | textTitle.text = "加载失败,点击重新加载" 83 | arrawImg.visibility = View.GONE 84 | } 85 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/view/LoadMoreRecyclerView.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.view 2 | 3 | import android.content.Context 4 | import androidx.collection.SparseArrayCompat 5 | import android.util.AttributeSet 6 | import android.view.View 7 | import android.view.ViewGroup 8 | 9 | /** 10 | * @name LoadMoreRecyclerView 11 | * @description 可以实现上拉加载,下拉刷新的 RecyclerView 12 | * @createTime 2018/11/29 17:53 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | class LoadMoreRecyclerView(context: Context, attrs: AttributeSet?, defStyle: Int) : androidx.recyclerview.widget.RecyclerView(context, attrs, defStyle) { 17 | private val ITEM_TYPE_HEADER_INIT = 100000 18 | private val ITEM_TYPE_FOOTER_INIT = 200000 19 | private val ITEM_TYPE_LOADMORE = 300000 20 | var hasMore: Boolean = false 21 | set(value) { 22 | field = value 23 | if (value) showMore = true 24 | } 25 | var showMore:Boolean = false 26 | private var mLoading: Boolean = false 27 | var loadMoreEnable: Boolean = true 28 | private var mWrapAdapter: WrapAdapter = WrapAdapter() 29 | private var mInnerAdapter: Adapter? = null 30 | private var mLoadMoreView: LoadMoreView? = null 31 | private val mHeaderViews = SparseArrayCompat() 32 | private val mFooterViews = SparseArrayCompat() 33 | private var mLoadMoreListener: ((androidx.recyclerview.widget.RecyclerView) -> Unit)? = null 34 | 35 | constructor(context: Context) : this(context, null) 36 | constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) 37 | override fun setAdapter(adapter: Adapter?) { 38 | if (mInnerAdapter!=null){ 39 | mInnerAdapter?.unregisterAdapterDataObserver(mDataObserver) 40 | } 41 | mInnerAdapter = adapter 42 | mInnerAdapter?.registerAdapterDataObserver(mDataObserver) 43 | super.setAdapter(mWrapAdapter) 44 | } 45 | 46 | /** 47 | * 添加HeaderView 48 | */ 49 | fun addHeaderView(view: View) { 50 | mHeaderViews.put(mHeaderViews.size() + ITEM_TYPE_HEADER_INIT, view) 51 | mWrapAdapter.notifyDataSetChanged() 52 | } 53 | 54 | /** 55 | * 添加FooterView 56 | */ 57 | fun addFooterView(view: View) { 58 | mFooterViews.put(mFooterViews.size() + ITEM_TYPE_FOOTER_INIT, view) 59 | mWrapAdapter.notifyDataSetChanged() 60 | } 61 | 62 | 63 | /** 64 | * 设置LoadMoreView 65 | * 必须是一个视图View 66 | */ 67 | fun setLoadMoreView(loadMoreView: LoadMoreView) { 68 | if (loadMoreView !is View) { 69 | throw IllegalStateException("LoadMoreView must is a View?") 70 | } 71 | this.mLoadMoreView = loadMoreView 72 | mWrapAdapter.notifyDataSetChanged() 73 | removeOnScrollListener(defaultScrollListener) 74 | if (!(mLoadMoreView?.shouldLoadMore(this) ?: true)) { 75 | addOnScrollListener(defaultScrollListener) 76 | } 77 | } 78 | 79 | 80 | 81 | /** 82 | * 开始加载更多 83 | */ 84 | fun startLoadMore() { 85 | if (!mLoading && loadMoreEnable && hasMore) { 86 | mLoading = true 87 | mLoadMoreView?.onLoadMore(this) 88 | mLoadMoreListener?.invoke(this) 89 | } 90 | } 91 | 92 | 93 | 94 | /** 95 | * 加载完成 96 | */ 97 | fun loadMoreComplete(hasMore: Boolean) { 98 | mLoading = false 99 | mLoadMoreView?.onComplete(this, hasMore) 100 | this.hasMore = hasMore 101 | } 102 | 103 | 104 | 105 | fun loadMoreError(errorCode: Int) { 106 | mLoading = false 107 | mLoadMoreView?.onError(this, errorCode) 108 | } 109 | 110 | 111 | 112 | /** 113 | * 设置加载更多监听 114 | */ 115 | 116 | fun setLoadMoreListener(loadMoreListener: (recyclerView: androidx.recyclerview.widget.RecyclerView) -> Unit): Unit { 117 | mLoadMoreListener = loadMoreListener 118 | } 119 | 120 | 121 | 122 | /** 123 | * 默认的加载触发时机 124 | */ 125 | private val defaultScrollListener = object : OnScrollListener() { 126 | override fun onScrolled(recyclerView: androidx.recyclerview.widget.RecyclerView, dx: Int, dy: Int) { 127 | if (!recyclerView.canScrollVertically(1)) { 128 | startLoadMore() 129 | } 130 | } 131 | } 132 | 133 | 134 | private inner class WrapAdapter : Adapter() { 135 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 136 | if (!isContent(position)) { 137 | return 138 | } 139 | mInnerAdapter?.onBindViewHolder(holder, position - mHeaderViews.size()) 140 | } 141 | 142 | 143 | 144 | override fun getItemCount(): Int { 145 | val adapterCount = mInnerAdapter?.itemCount ?: 0 146 | if (adapterCount > 0) { 147 | return adapterCount + mHeaderViews.size() + mFooterViews.size() + if (mLoadMoreView == null||!showMore) 0 else 1 148 | } else {//防止没有内容的时候加载更多显示出来 149 | return mHeaderViews.size() + mFooterViews.size() 150 | } 151 | } 152 | 153 | 154 | 155 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 156 | if (mHeaderViews[viewType] != null) { 157 | return object : ViewHolder(mHeaderViews[viewType]!!) { 158 | init { 159 | itemView.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) 160 | } 161 | } 162 | } 163 | if (viewType == ITEM_TYPE_LOADMORE) 164 | return object : ViewHolder(mLoadMoreView as View) { 165 | init { 166 | itemView.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) 167 | } 168 | } 169 | if (mFooterViews[viewType] != null) { 170 | return object : ViewHolder(mFooterViews[viewType]!!) { 171 | init { 172 | itemView.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) 173 | } 174 | } 175 | } 176 | return mInnerAdapter?.onCreateViewHolder(parent, viewType)!! 177 | } 178 | 179 | 180 | override fun getItemViewType(position: Int): Int { 181 | if (position < mHeaderViews.size()) { 182 | return mHeaderViews.keyAt(position) 183 | } 184 | if (mLoadMoreView != null && position == itemCount - 1&&showMore) { 185 | return ITEM_TYPE_LOADMORE 186 | } 187 | if (position >= mHeaderViews.size() + (mInnerAdapter?.itemCount ?: 0)) { 188 | return mFooterViews.keyAt(position - mHeaderViews.size() - (mInnerAdapter?.itemCount ?: 0)) 189 | } 190 | return mInnerAdapter?.getItemViewType(position - mHeaderViews.size()) ?: -1 191 | } 192 | 193 | override fun onAttachedToRecyclerView(recyclerView: androidx.recyclerview.widget.RecyclerView) { 194 | mInnerAdapter?.onAttachedToRecyclerView(recyclerView) 195 | val layoutManager = layoutManager 196 | if (layoutManager is androidx.recyclerview.widget.GridLayoutManager) { 197 | layoutManager.spanSizeLookup = object : androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup() { 198 | override fun getSpanSize(position: Int): Int { 199 | if (!isContent(position)) { 200 | return layoutManager.spanCount 201 | } 202 | return 1 203 | } 204 | } 205 | } 206 | } 207 | 208 | override fun onViewAttachedToWindow(holder: ViewHolder) { 209 | mInnerAdapter?.onViewAttachedToWindow(holder) 210 | val position = holder.layoutPosition 211 | val layoutParams = holder.itemView.layoutParams 212 | if (!isContent(position) && layoutParams != null && layoutParams is androidx.recyclerview.widget.StaggeredGridLayoutManager.LayoutParams) { 213 | layoutParams.isFullSpan = true 214 | } 215 | } 216 | 217 | fun isContent(position: Int): Boolean { 218 | if (position < mHeaderViews.size()) 219 | return false 220 | if (mLoadMoreView != null && position == itemCount - 1) 221 | return false 222 | if (position >= mHeaderViews.size() + (mInnerAdapter?.itemCount ?: 0)) 223 | return false 224 | return true 225 | } 226 | } 227 | 228 | private val mDataObserver = object : AdapterDataObserver() { 229 | override fun onChanged() { 230 | mWrapAdapter.notifyDataSetChanged() 231 | } 232 | override fun onItemRangeChanged(positionStart: Int, itemCount: Int) { 233 | mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount) 234 | } 235 | 236 | override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) { 237 | mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload) 238 | } 239 | 240 | override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { 241 | mWrapAdapter.notifyItemRangeInserted(positionStart, itemCount) 242 | } 243 | 244 | override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { 245 | mWrapAdapter.notifyItemMoved(fromPosition, toPosition) 246 | } 247 | 248 | override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { 249 | mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount) 250 | } 251 | } 252 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/view/LoadMoreView.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.view 2 | 3 | /** 4 | * @name LoadMoreView 5 | * @description 上拉加载的 footer view 6 | * @createTime 2018/11/29 17:52 7 | * @author onestravel 8 | * @version 1.0.0 9 | */ 10 | interface LoadMoreView { 11 | /** 12 | * 自定义适当的加载时机 13 | * @return true 自定义生效 false默认的加载时机 14 | */ 15 | fun shouldLoadMore(recyclerView: LoadMoreRecyclerView):Boolean 16 | 17 | 18 | /** 19 | * 正在加载 20 | */ 21 | fun onLoadMore(recyclerView: LoadMoreRecyclerView) 22 | 23 | /** 24 | * 加载完成 25 | * @param hasMore 是否还有更多数据 26 | */ 27 | fun onComplete(recyclerView: LoadMoreRecyclerView, hasMore:Boolean) 28 | 29 | 30 | 31 | /** 32 | * 加载失败 33 | * @param errorCode 错误码,由用户定义 34 | */ 35 | fun onError(recyclerView: LoadMoreRecyclerView, errorCode:Int) 36 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/view/LoadingDialog.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.view 2 | 3 | import android.app.Dialog 4 | import android.content.Context 5 | import android.os.Handler 6 | import androidx.annotation.StyleRes 7 | import android.view.Gravity 8 | import android.view.LayoutInflater 9 | import android.view.View 10 | import android.view.WindowManager 11 | import android.widget.ImageView 12 | import android.widget.LinearLayout 13 | import android.widget.TextView 14 | import cn.onestravel.library.common.one.R 15 | import com.bumptech.glide.Glide 16 | 17 | import java.lang.ref.WeakReference 18 | 19 | 20 | /** 21 | * Created by Administrator on 2016/5/5. 22 | */ 23 | open class LoadingDialog : Dialog, View.OnClickListener { 24 | private var tvTitle: TextView? = null 25 | private var layoutContent: LinearLayout? = null 26 | private var isCancelable = true 27 | private var lp: WindowManager.LayoutParams? = null 28 | private var ivLoading: ImageView? = null 29 | public var title="正在加载..." 30 | set(value) { tvTitle!!.text = title} 31 | 32 | 33 | private constructor(context: Context, @StyleRes themeResId: Int = R.style.Dialog_View) : super( 34 | context, 35 | themeResId 36 | ) { 37 | initView(context) 38 | } 39 | 40 | 41 | private fun initView(context: Context) { 42 | val layout = LayoutInflater.from(context).inflate(R.layout.dialog_progress, null) 43 | setContentView(layout) 44 | 45 | layoutContent = layout.findViewById(R.id.layout_content) 46 | ivLoading = layout.findViewById(R.id.iv_loading) 47 | tvTitle = layout.findViewById(R.id.tv_title) 48 | layoutContent!!.setOnClickListener(this) 49 | // 设置window属性 50 | lp = window!!.attributes 51 | lp!!.gravity = Gravity.CENTER 52 | lp!!.dimAmount = 0f // 去背景遮盖 53 | lp!!.alpha = 1.0f 54 | window!!.attributes = lp 55 | try { 56 | Glide.with(context) 57 | .load(R.drawable.loading_gif) 58 | .into(ivLoading!!) 59 | } catch (e: Exception) { 60 | e.printStackTrace() 61 | } 62 | 63 | } 64 | 65 | 66 | override fun show() { 67 | try { 68 | super.show() 69 | } catch (e: Exception) { 70 | e.printStackTrace() 71 | } 72 | 73 | } 74 | 75 | 76 | /** 77 | * 设置是否可以点击取消 78 | * 79 | * @param isCancelable 80 | */ 81 | override fun setCancelable(isCancelable: Boolean) { 82 | this.isCancelable = isCancelable 83 | } 84 | 85 | override fun dismiss() { 86 | Handler().postDelayed({ 87 | try { 88 | super.dismiss() 89 | } catch (e: Exception) { 90 | 91 | } 92 | }, 200) 93 | } 94 | 95 | override fun onClick(v: View) { 96 | if (isCancelable) { 97 | dismiss() 98 | } 99 | } 100 | 101 | fun destroy(){ 102 | if (sWeakReferenceInstance != null) { 103 | sWeakReferenceInstance!!.clear() 104 | sWeakReferenceInstance = null 105 | } 106 | } 107 | 108 | companion object { 109 | private var sWeakReferenceInstance: WeakReference? = null 110 | 111 | fun getInstance(context: Context): LoadingDialog { 112 | if (sWeakReferenceInstance != null) { 113 | sWeakReferenceInstance!!.clear() 114 | sWeakReferenceInstance = null 115 | } 116 | sWeakReferenceInstance = WeakReference(LoadingDialog(context, R.style.Dialog)) 117 | return sWeakReferenceInstance!!.get()!! 118 | } 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/view/NoScrollViewPager.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.MotionEvent 6 | 7 | /** 8 | * @author onestravel 9 | * @version 1.0.0 10 | * @project MyApplication 11 | * @description 12 | * @createTime 2017/9/21 13 | */ 14 | 15 | class NoScrollViewPager : androidx.viewpager.widget.ViewPager { 16 | private var noScroll = false 17 | 18 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { 19 | // TODO Auto-generated constructor stub 20 | } 21 | 22 | constructor(context: Context) : super(context) {} 23 | 24 | fun setNoScroll(noScroll: Boolean) { 25 | this.noScroll = noScroll 26 | } 27 | 28 | override fun scrollTo(x: Int, y: Int) { 29 | super.scrollTo(x, y) 30 | } 31 | 32 | override fun onTouchEvent(arg0: MotionEvent): Boolean { 33 | /* return false;//super.onTouchEvent(arg0); */ 34 | return if (noScroll) 35 | false 36 | else 37 | super.onTouchEvent(arg0) 38 | } 39 | 40 | override fun onInterceptTouchEvent(arg0: MotionEvent): Boolean { 41 | return if (noScroll) 42 | false 43 | else 44 | super.onInterceptTouchEvent(arg0) 45 | } 46 | 47 | override fun setCurrentItem(item: Int, smoothScroll: Boolean) { 48 | super.setCurrentItem(item, smoothScroll) 49 | } 50 | 51 | override fun setCurrentItem(item: Int) { 52 | super.setCurrentItem(item) 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/common/view/ShapeImageView.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.common.view 2 | 3 | import android.content.Context 4 | import android.graphics.* 5 | import android.graphics.drawable.Drawable 6 | import androidx.appcompat.widget.AppCompatImageView 7 | import android.util.AttributeSet 8 | import android.widget.ImageView 9 | import cn.onestravel.library.common.one.R 10 | import cn.onestravel.library.common.utils.ImageUtils 11 | 12 | 13 | /** 14 | * @author onestravel 15 | * @version 1.0.0 16 | * @projectName EasouAndroid-zy 17 | * @desctrion 自定义形状的ImageView ,REC 表示矩形的ImageView,CIRCLE 表示圆形的ImageView,OVAL 表示椭圆的ImageView 18 | * @createTime 2017/7/7.˙ 19 | */ 20 | 21 | class ShapeImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : 22 | AppCompatImageView(context, attrs, defStyle) { 23 | 24 | var borderSize = 0f 25 | private set // 边框大小,默认为0,即无边框 26 | private var mBorderColor = Color.WHITE // 边框颜色,默认为白色 27 | var shape = SHAPE_REC // 形状,默认为直接矩形 28 | private var mRoundRadius = 0f // 矩形的圆角半径,默认为0,即直角矩形 29 | private val mBorderPaint = Paint(Paint.ANTI_ALIAS_FLAG) 30 | private val mViewRect = RectF() // imageview的矩形区域 31 | private val mBorderRect = RectF() // 边框的矩形区域 32 | 33 | private val mShaderMatrix = Matrix() 34 | private val mBitmapPaint = Paint() 35 | private var mBitmapShader: BitmapShader? = null 36 | private var mBitmap: Bitmap? = null 37 | 38 | var borderColor: Int 39 | get() = mBorderColor 40 | set(mBorderColor) { 41 | this.mBorderColor = mBorderColor 42 | mBorderPaint.color = mBorderColor 43 | invalidate() 44 | } 45 | 46 | var roundRadius: Float 47 | get() = mRoundRadius 48 | set(mRoundRadius) { 49 | this.mRoundRadius = mRoundRadius 50 | invalidate() 51 | } 52 | 53 | fun setBorderSize(mBorderSize: Int) { 54 | this.borderSize = mBorderSize.toFloat() 55 | mBorderPaint.strokeWidth = mBorderSize.toFloat() 56 | initRect() 57 | invalidate() 58 | } 59 | 60 | init { 61 | init(attrs) 62 | mBorderPaint.style = Paint.Style.STROKE 63 | mBorderPaint.strokeWidth = borderSize 64 | mBorderPaint.color = mBorderColor 65 | mBorderPaint.isAntiAlias = true 66 | mBitmapPaint.isAntiAlias = true 67 | // super.setScaleType(ScaleType.CENTER_CROP); // 固定为CENTER_CROP,其他不生效 68 | }// 虽然此处会调用setImageDrawable,但此时成员变量还未被正确初始化 69 | 70 | 71 | override fun setImageResource(resId: Int) { 72 | super.setImageResource(resId) 73 | mBitmap = ImageUtils.getBitmapFromDrawable(drawable) 74 | setupBitmapShader() 75 | } 76 | 77 | override fun setImageDrawable(drawable: Drawable?) { 78 | super.setImageDrawable(drawable) 79 | mBitmap = ImageUtils.getBitmapFromDrawable(drawable) 80 | setupBitmapShader() 81 | } 82 | 83 | override fun setScaleType(scaleType: ImageView.ScaleType) { 84 | if (scaleType != ImageView.ScaleType.CENTER_CROP) { 85 | // throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); 86 | } 87 | } 88 | 89 | private fun init(attrs: AttributeSet?) { 90 | 91 | val a = context.obtainStyledAttributes( 92 | attrs, 93 | R.styleable.ShapeImageView 94 | ) 95 | shape = a.getInt(R.styleable.ShapeImageView_viewShape, shape) 96 | mRoundRadius = a.getDimension(R.styleable.ShapeImageView_round_radius, mRoundRadius) 97 | borderSize = a.getDimension(R.styleable.ShapeImageView_border_size, borderSize) 98 | mBorderColor = a.getColor(R.styleable.ShapeImageView_border_color, mBorderColor) 99 | a.recycle() 100 | } 101 | 102 | /** 103 | * 对于普通的view,在执行到onDraw()时,背景图已绘制完成 104 | * 105 | * 106 | * 对于ViewGroup,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法, 107 | * 当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用, 108 | */ 109 | public override fun onDraw(canvas: Canvas) { 110 | 111 | if (drawable != null) { 112 | if (shape == SHAPE_CIRCLE) { 113 | canvas.drawCircle( 114 | (width / 2).toFloat(), (height / 2).toFloat(), 115 | (Math.min(width, height) / 2).toFloat(), mBitmapPaint 116 | ) 117 | } else if (shape == SHAPE_OVAL) { 118 | canvas.drawOval(mViewRect, mBitmapPaint) 119 | } else { 120 | canvas.drawRoundRect(mViewRect, mRoundRadius, mRoundRadius, mBitmapPaint) 121 | } 122 | } 123 | 124 | 125 | if (borderSize > 0) { // 绘制边框 126 | if (shape == SHAPE_CIRCLE) { 127 | canvas.drawCircle( 128 | mViewRect.right / 2, mViewRect.bottom / 2, 129 | Math.min(mViewRect.right, mViewRect.bottom) / 2 - borderSize / 2, mBorderPaint 130 | ) 131 | } else if (shape == SHAPE_OVAL) { 132 | canvas.drawOval(mBorderRect, mBorderPaint) 133 | } else { 134 | canvas.drawRoundRect(mBorderRect, mRoundRadius, mRoundRadius, mBorderPaint) 135 | } 136 | } 137 | } 138 | 139 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { 140 | super.onSizeChanged(w, h, oldw, oldh) 141 | initRect() 142 | setupBitmapShader() 143 | } 144 | 145 | // 不能在onLayout()调用invalidate(),否则导致绘制异常。(setupBitmapShader()中调用了invalidate()) 146 | override fun onLayout( 147 | changed: Boolean, left: Int, top: Int, right: Int, 148 | bottom: Int 149 | ) { 150 | super.onLayout(changed, left, top, right, bottom) 151 | // initRect(); 152 | // setupBitmapShader(); 153 | } 154 | 155 | private fun setupBitmapShader() { 156 | // super(context, attrs, defStyle)调用setImageDrawable时,成员变量还未被正确初始化 157 | if (mBitmapPaint == null) { 158 | return 159 | } 160 | if (mBitmap == null) { 161 | invalidate() 162 | return 163 | } 164 | mBitmapShader = BitmapShader(mBitmap!!, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) 165 | mBitmapPaint.shader = mBitmapShader 166 | 167 | // 固定为CENTER_CROP,使图片在view中居中并裁剪 168 | mShaderMatrix.set(null) 169 | // 缩放到高或宽 与view的高或宽 匹配 170 | val scale = Math.max(width * 1f / mBitmap!!.width, height * 1f / mBitmap!!.height) 171 | // 由于BitmapShader默认是从画布的左上角开始绘制,所以把其平移到画布中间,即居中 172 | val dx = (width - mBitmap!!.width * scale) / 2 173 | val dy = (height - mBitmap!!.height * scale) / 2 174 | mShaderMatrix.setScale(scale, scale) 175 | mShaderMatrix.postTranslate(dx, dy) 176 | mBitmapShader!!.setLocalMatrix(mShaderMatrix) 177 | invalidate() 178 | } 179 | 180 | // 设置图片的绘制区域 181 | private fun initRect() { 182 | 183 | mViewRect.top = 0f 184 | mViewRect.left = 0f 185 | mViewRect.right = width.toFloat() // 宽度 186 | mViewRect.bottom = height.toFloat() // 高度 187 | 188 | // 边框的矩形区域不能等于ImageView的矩形区域,否则边框的宽度只显示了一半 189 | mBorderRect.top = borderSize / 2 190 | mBorderRect.left = borderSize / 2 191 | mBorderRect.right = width - borderSize / 2 192 | mBorderRect.bottom = height - borderSize / 2 193 | } 194 | 195 | 196 | 197 | companion object { 198 | 199 | var SHAPE_REC = 1 // 矩形 200 | var SHAPE_CIRCLE = 2 // 圆形 201 | var SHAPE_OVAL = 3 // 椭圆 202 | } 203 | } 204 | 205 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/activity/OneMvpActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.activity 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.common.activity.OneActivity 5 | import cn.onestravel.library.common.view.LoadingDialog 6 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 7 | import cn.onestravel.library.mvp.view.OneMvpView 8 | 9 | /** 10 | * @name OneMvpActivity 11 | * @description 所有Mvp架构的 Activity 的基类 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneMvpActivity> : OneActivity(), OneMvpView { 17 | protected val mPresenter: P by lazy { createPresenter() } 18 | protected var mLoadingDialog: LoadingDialog? = null 19 | protected abstract fun createPresenter(): P 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | if (mPresenter == null) { 24 | throw NullPointerException("Presenter is null! Do you return null in createPresenter()?") 25 | } 26 | mPresenter.onMvpAttachView(this as V, savedInstanceState) 27 | } 28 | 29 | 30 | override fun onStart() { 31 | super.onStart() 32 | mPresenter?.let { 33 | it.onMvpStart() 34 | } 35 | } 36 | 37 | override fun onResume() { 38 | super.onResume() 39 | mPresenter?.let { 40 | it.onMvpResume() 41 | } 42 | } 43 | 44 | override fun onPause() { 45 | mPresenter?.let { 46 | it.onMvpPause() 47 | } 48 | super.onPause() 49 | } 50 | 51 | override fun onStop() { 52 | mPresenter?.let { 53 | it.onMvpStop() 54 | } 55 | super.onStop() 56 | } 57 | 58 | 59 | override fun onSaveInstanceState(outState: Bundle) { 60 | super.onSaveInstanceState(outState) 61 | mPresenter?.let { 62 | it.onMvpSaveInstanceState(outState) 63 | } 64 | } 65 | 66 | override fun onDestroy() { 67 | mPresenter?.let { 68 | it.onMvpDetachView(false) 69 | it.onMvpDestroy() 70 | } 71 | mLoadingDialog?.let { 72 | it.destroy() 73 | mLoadingDialog = null 74 | } 75 | super.onDestroy() 76 | } 77 | 78 | override fun showLoading(content: String?) { 79 | if (mLoadingDialog == null) { 80 | mLoadingDialog = LoadingDialog.getInstance(this) 81 | mLoadingDialog!!.title = content ?: "正在加载..." 82 | if (!mLoadingDialog!!.isShowing) { 83 | mLoadingDialog!!.show() 84 | } 85 | } 86 | } 87 | 88 | override fun hideLoading() { 89 | mLoadingDialog?.let { 90 | mLoadingDialog!!.dismiss() 91 | } 92 | } 93 | 94 | override fun onResponseError(msg: String?) { 95 | msg?.let { 96 | showToast(msg) 97 | } 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/activity/OneMvpListActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.activity 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.common.activity.OneListActivity 5 | import cn.onestravel.library.common.view.LoadingDialog 6 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 7 | import cn.onestravel.library.mvp.view.OneMvpView 8 | 9 | /** 10 | * @name OneMvpListActivity 11 | * @description 所有Mvp架构的 默认含有RecyclerView的可下拉刷新,上拉加载(可隐藏)Activity基类 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneMvpListActivity> : OneListActivity(), OneMvpView { 17 | protected val mPresenter by lazy { createPresenter() } 18 | protected var mLoadingDialog: LoadingDialog? = null 19 | protected abstract fun createPresenter(): P 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | if (mPresenter == null) { 24 | throw NullPointerException("Presenter is null! Do you return null in createPresenter()?") 25 | } 26 | mPresenter.onMvpAttachView(this as V, savedInstanceState) 27 | } 28 | 29 | 30 | override fun onStart() { 31 | super.onStart() 32 | mPresenter.let { 33 | it.onMvpStart() 34 | } 35 | } 36 | 37 | override fun onResume() { 38 | super.onResume() 39 | mPresenter.let { 40 | it.onMvpResume() 41 | } 42 | } 43 | 44 | override fun onPause() { 45 | mPresenter.let { 46 | it.onMvpPause() 47 | } 48 | super.onPause() 49 | } 50 | 51 | override fun onStop() { 52 | mPresenter.let { 53 | it.onMvpStop() 54 | } 55 | super.onStop() 56 | } 57 | 58 | 59 | override fun onSaveInstanceState(outState: Bundle) { 60 | super.onSaveInstanceState(outState) 61 | mPresenter?.let { 62 | it.onMvpSaveInstanceState(outState) 63 | } 64 | } 65 | 66 | override fun onDestroy() { 67 | mPresenter?.let { 68 | it.onMvpDetachView(false) 69 | it.onMvpDestroy() 70 | } 71 | mLoadingDialog?.let { 72 | it.destroy() 73 | mLoadingDialog = null 74 | } 75 | super.onDestroy() 76 | } 77 | 78 | override fun showLoading(content: String?) { 79 | if (mLoadingDialog == null) { 80 | mLoadingDialog = LoadingDialog.getInstance(this) 81 | mLoadingDialog!!.title = content?:"正在加载..." 82 | if (!mLoadingDialog!!.isShowing) { 83 | mLoadingDialog!!.show() 84 | } 85 | } 86 | } 87 | 88 | override fun hideLoading() { 89 | mLoadingDialog?.let { 90 | mLoadingDialog!!.dismiss() 91 | } 92 | } 93 | 94 | override fun onResponseError(msg: String?) { 95 | msg?.let { 96 | showToast(msg) 97 | } 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/activity/OneRxMvpActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.activity 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 5 | import cn.onestravel.library.mvp.view.OneMvpView 6 | import cn.onestravel.library.common.view.LoadingDialog 7 | import cn.onestravel.library.rxrequest.activity.OneRxActivity 8 | 9 | /** 10 | * @name OneMvpActivity 11 | * @description 所有Mvp架构的 采用RxJava+Retrofit 请求的Activity 的基类 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneRxMvpActivity> : OneRxActivity(), OneMvpView { 17 | protected val mPresenter by lazy { createPresenter() } 18 | protected var mLoadingDialog: LoadingDialog? = null 19 | protected abstract fun createPresenter(): P 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | if (mPresenter == null) { 24 | throw NullPointerException("Presenter is null! Do you return null in createPresenter()?") 25 | } 26 | mPresenter.onMvpAttachView(this as V, savedInstanceState) 27 | } 28 | 29 | 30 | override fun onStart() { 31 | super.onStart() 32 | mPresenter.let { 33 | it.onMvpStart() 34 | } 35 | } 36 | 37 | override fun onResume() { 38 | super.onResume() 39 | mPresenter.let { 40 | it.onMvpResume() 41 | } 42 | } 43 | 44 | override fun onPause() { 45 | super.onPause() 46 | mPresenter.let { 47 | it.onMvpPause() 48 | } 49 | } 50 | 51 | override fun onStop() { 52 | super.onStop() 53 | mPresenter.let { 54 | it.onMvpStop() 55 | } 56 | } 57 | 58 | 59 | override fun onSaveInstanceState(outState: Bundle) { 60 | super.onSaveInstanceState(outState) 61 | mPresenter.let { 62 | it.onMvpSaveInstanceState(outState) 63 | } 64 | } 65 | 66 | override fun onDestroy() { 67 | mLoadingDialog?.let { 68 | it.destroy() 69 | mLoadingDialog = null 70 | } 71 | mPresenter.let { 72 | it.onMvpDetachView(false) 73 | it.onMvpDestroy() 74 | } 75 | super.onDestroy() 76 | 77 | } 78 | 79 | override fun showLoading(content: String?) { 80 | if (mLoadingDialog == null) { 81 | mLoadingDialog = LoadingDialog.getInstance(this) 82 | mLoadingDialog!!.title = content ?: "正在加载..." 83 | if (!mLoadingDialog!!.isShowing) { 84 | mLoadingDialog!!.show() 85 | } 86 | } 87 | 88 | } 89 | 90 | override fun hideLoading() { 91 | mLoadingDialog?.let { 92 | mLoadingDialog!!.dismiss() 93 | } 94 | } 95 | 96 | override fun onResponseError(msg: String?) { 97 | msg?.let { 98 | showToast(msg) 99 | } 100 | } 101 | 102 | 103 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/activity/OneRxMvpListActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.activity 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 5 | import cn.onestravel.library.mvp.view.OneMvpView 6 | import cn.onestravel.library.common.view.LoadingDialog 7 | import cn.onestravel.library.rxrequest.activity.OneRxListActivity 8 | 9 | /** 10 | * @name OneMvpActivity 11 | * @description 所有Mvp架构的默认含有RecyclerView的可下拉刷新,上拉加载(可隐藏)Activity基类; 处理RXJava的生命周期的ListActivity 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneRxMvpListActivity> : OneRxListActivity(), OneMvpView { 17 | protected val mPresenter by lazy { createPresenter() } 18 | protected var mLoadingDialog: LoadingDialog? = null 19 | protected abstract fun createPresenter(): P 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | if (mPresenter == null) { 24 | throw NullPointerException("Presenter is null! Do you return null in createPresenter()?") 25 | } 26 | mPresenter.onMvpAttachView(this as V, savedInstanceState) 27 | } 28 | 29 | 30 | override fun onStart() { 31 | super.onStart() 32 | mPresenter.let { 33 | it.onMvpStart() 34 | } 35 | } 36 | 37 | override fun onResume() { 38 | super.onResume() 39 | mPresenter.let { 40 | it.onMvpResume() 41 | } 42 | } 43 | 44 | override fun onPause() { 45 | super.onPause() 46 | mPresenter.let { 47 | it.onMvpPause() 48 | } 49 | } 50 | 51 | override fun onStop() { 52 | super.onStop() 53 | mPresenter.let { 54 | it.onMvpStop() 55 | } 56 | } 57 | 58 | 59 | override fun onSaveInstanceState(outState: Bundle) { 60 | super.onSaveInstanceState(outState) 61 | mPresenter.let { 62 | it.onMvpSaveInstanceState(outState) 63 | } 64 | } 65 | 66 | override fun onDestroy() { 67 | 68 | mLoadingDialog?.let { 69 | it.destroy() 70 | mLoadingDialog = null 71 | } 72 | mPresenter.let { 73 | it.onMvpDetachView(false) 74 | it.onMvpDestroy() 75 | } 76 | super.onDestroy() 77 | 78 | } 79 | 80 | override fun showLoading(content: String?) { 81 | if (mLoadingDialog == null) { 82 | mLoadingDialog = LoadingDialog.getInstance(this) 83 | mLoadingDialog!!.title = content ?: "正在加载..." 84 | if (!mLoadingDialog!!.isShowing) { 85 | mLoadingDialog!!.show() 86 | } 87 | } 88 | 89 | } 90 | 91 | override fun hideLoading() { 92 | mLoadingDialog?.let { 93 | mLoadingDialog!!.dismiss() 94 | } 95 | } 96 | 97 | override fun onResponseError(msg: String?) { 98 | msg?.let { 99 | showToast(msg) 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/fragment/OneMvpFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.fragment 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.common.fragment.OneFragment 5 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 6 | import cn.onestravel.library.mvp.view.OneMvpView 7 | import cn.onestravel.library.common.view.LoadingDialog 8 | 9 | /** 10 | * @name OneMvpActivity 11 | * @description 所有Mvp架构的Fragment的基类 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneMvpFragment> : OneFragment(), OneMvpView { 17 | protected val mPresenter by lazy { createPresenter() } 18 | protected var mLoadingDialog: LoadingDialog? = null 19 | protected abstract fun createPresenter(): P 20 | 21 | override fun onActivityCreated(savedInstanceState: Bundle?) { 22 | super.onActivityCreated(savedInstanceState) 23 | if (mPresenter == null) { 24 | throw NullPointerException("Presenter is null! Do you return null in createPresenter()?") 25 | } 26 | mPresenter.onMvpAttachView(this as V, savedInstanceState) 27 | } 28 | 29 | 30 | 31 | 32 | override fun onStart() { 33 | super.onStart() 34 | mPresenter.let { 35 | it.onMvpStart() 36 | } 37 | } 38 | 39 | override fun onResume() { 40 | super.onResume() 41 | mPresenter.let { 42 | it.onMvpResume() 43 | } 44 | } 45 | 46 | override fun onPause() { 47 | super.onPause() 48 | mPresenter.let { 49 | it.onMvpPause() 50 | } 51 | } 52 | 53 | override fun onStop() { 54 | super.onStop() 55 | mPresenter.let { 56 | it.onMvpStop() 57 | } 58 | } 59 | 60 | override fun onSaveInstanceState(outState: Bundle) { 61 | super.onSaveInstanceState(outState) 62 | mPresenter.let { 63 | it.onMvpSaveInstanceState(outState) 64 | } 65 | } 66 | 67 | override fun onDestroy() { 68 | 69 | mLoadingDialog?.let { 70 | it.destroy() 71 | mLoadingDialog = null 72 | } 73 | mPresenter.let { 74 | it.onMvpDetachView(false) 75 | it.onMvpDestroy() 76 | } 77 | super.onDestroy() 78 | 79 | } 80 | 81 | override fun showLoading(content: String?) { 82 | if (mLoadingDialog == null) { 83 | mLoadingDialog = LoadingDialog.getInstance(context!!) 84 | mLoadingDialog!!.title = content ?: "正在加载..." 85 | if (!mLoadingDialog!!.isShowing) { 86 | mLoadingDialog!!.show() 87 | } 88 | } 89 | 90 | } 91 | 92 | override fun hideLoading() { 93 | mLoadingDialog?.let { 94 | mLoadingDialog!!.dismiss() 95 | } 96 | } 97 | 98 | override fun onResponseError(msg: String?) { 99 | msg?.let { 100 | showToast(msg) 101 | } 102 | } 103 | 104 | 105 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/fragment/OneMvpListFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.fragment 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.common.fragment.OneListFragment 5 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 6 | import cn.onestravel.library.mvp.view.OneMvpView 7 | import cn.onestravel.library.common.view.LoadingDialog 8 | 9 | /** 10 | * @name OneMvpActivity 11 | * @description 所有Mvp架构的Fragment的基类 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneMvpListFragment> : OneListFragment(), OneMvpView { 17 | protected val mPresenter by lazy { createPresenter() } 18 | protected var mLoadingDialog: LoadingDialog? = null 19 | protected abstract fun createPresenter(): P 20 | 21 | override fun onActivityCreated(savedInstanceState: Bundle?) { 22 | super.onActivityCreated(savedInstanceState) 23 | if (mPresenter == null) { 24 | throw NullPointerException("Presenter is null! Do you return null in createPresenter()?") 25 | } 26 | mPresenter.onMvpAttachView(this as V, savedInstanceState) 27 | } 28 | 29 | 30 | 31 | 32 | override fun onStart() { 33 | super.onStart() 34 | mPresenter.let { 35 | it.onMvpStart() 36 | } 37 | } 38 | 39 | override fun onResume() { 40 | super.onResume() 41 | mPresenter.let { 42 | it.onMvpResume() 43 | } 44 | } 45 | 46 | override fun onPause() { 47 | super.onPause() 48 | mPresenter.let { 49 | it.onMvpPause() 50 | } 51 | } 52 | 53 | override fun onStop() { 54 | super.onStop() 55 | mPresenter.let { 56 | it.onMvpStop() 57 | } 58 | } 59 | 60 | override fun onSaveInstanceState(outState: Bundle) { 61 | super.onSaveInstanceState(outState) 62 | mPresenter.let { 63 | it.onMvpSaveInstanceState(outState) 64 | } 65 | } 66 | 67 | override fun onDestroy() { 68 | mLoadingDialog?.let { 69 | it.destroy() 70 | mLoadingDialog = null 71 | } 72 | mPresenter.let { 73 | it.onMvpDetachView(false) 74 | it.onMvpDestroy() 75 | } 76 | super.onDestroy() 77 | 78 | } 79 | 80 | override fun showLoading(content: String?) { 81 | if (mLoadingDialog == null) { 82 | mLoadingDialog = LoadingDialog.getInstance(context!!) 83 | mLoadingDialog!!.title = content ?: "正在加载..." 84 | if (!mLoadingDialog!!.isShowing) { 85 | mLoadingDialog!!.show() 86 | } 87 | } 88 | 89 | } 90 | 91 | override fun hideLoading() { 92 | mLoadingDialog?.let { 93 | mLoadingDialog!!.dismiss() 94 | } 95 | } 96 | 97 | override fun onResponseError(msg: String?) { 98 | msg?.let { 99 | showToast(msg) 100 | } 101 | } 102 | 103 | 104 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/fragment/OneRxMvpFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.fragment 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 5 | import cn.onestravel.library.mvp.view.OneMvpView 6 | import cn.onestravel.library.common.view.LoadingDialog 7 | import cn.onestravel.library.rxrequest.fragment.OneRxFragment 8 | 9 | /** 10 | * @name OneMvpActivity 11 | * @description 所有Mvp架构的Fragment的基类 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneRxMvpFragment> : OneRxFragment(), OneMvpView { 17 | protected val mPresenter by lazy { createPresenter() } 18 | protected var mLoadingDialog: LoadingDialog? = null 19 | protected abstract fun createPresenter(): P 20 | 21 | override fun onActivityCreated(savedInstanceState: Bundle?) { 22 | super.onActivityCreated(savedInstanceState) 23 | if (mPresenter == null) { 24 | throw NullPointerException("Presenter is null! Do you return null in createPresenter()?") 25 | } 26 | mPresenter.onMvpAttachView(this as V, savedInstanceState) 27 | } 28 | 29 | 30 | 31 | 32 | override fun onStart() { 33 | super.onStart() 34 | mPresenter.let { 35 | it.onMvpStart() 36 | } 37 | } 38 | 39 | override fun onResume() { 40 | super.onResume() 41 | mPresenter.let { 42 | it.onMvpResume() 43 | } 44 | } 45 | 46 | override fun onPause() { 47 | super.onPause() 48 | mPresenter.let { 49 | it.onMvpPause() 50 | } 51 | } 52 | 53 | override fun onStop() { 54 | super.onStop() 55 | mPresenter.let { 56 | it.onMvpStop() 57 | } 58 | } 59 | 60 | override fun onSaveInstanceState(outState: Bundle) { 61 | super.onSaveInstanceState(outState) 62 | mPresenter.let { 63 | it.onMvpSaveInstanceState(outState) 64 | } 65 | } 66 | 67 | override fun onDestroy() { 68 | mLoadingDialog?.let { 69 | it.destroy() 70 | mLoadingDialog = null 71 | } 72 | mPresenter.let { 73 | it.onMvpDetachView(false) 74 | it.onMvpDestroy() 75 | } 76 | super.onDestroy() 77 | 78 | } 79 | 80 | override fun showLoading(content: String?) { 81 | if (mLoadingDialog == null) { 82 | mLoadingDialog = LoadingDialog.getInstance(context!!) 83 | mLoadingDialog!!.title = content ?: "正在加载..." 84 | if (!mLoadingDialog!!.isShowing) { 85 | mLoadingDialog!!.show() 86 | } 87 | } 88 | 89 | } 90 | 91 | override fun hideLoading() { 92 | mLoadingDialog?.let { 93 | mLoadingDialog!!.dismiss() 94 | } 95 | } 96 | 97 | override fun onResponseError(msg: String?) { 98 | msg?.let { 99 | showToast(msg) 100 | } 101 | } 102 | 103 | 104 | 105 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/fragment/OneRxMvpListFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.fragment 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 5 | import cn.onestravel.library.mvp.view.OneMvpView 6 | import cn.onestravel.library.common.view.LoadingDialog 7 | import cn.onestravel.library.rxrequest.fragment.OneRxListFragment 8 | 9 | /** 10 | * @name OneMvpActivity 11 | * @description 所有Mvp架构的Fragment的基类 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneRxMvpListFragment> : OneRxListFragment(), OneMvpView { 17 | protected val mPresenter by lazy { createPresenter() } 18 | protected var mLoadingDialog: LoadingDialog? = null 19 | protected abstract fun createPresenter(): P 20 | 21 | override fun onActivityCreated(savedInstanceState: Bundle?) { 22 | super.onActivityCreated(savedInstanceState) 23 | if (mPresenter == null) { 24 | throw NullPointerException("Presenter is null! Do you return null in createPresenter()?") 25 | } 26 | mPresenter.onMvpAttachView(this as V, savedInstanceState) 27 | } 28 | 29 | 30 | 31 | 32 | override fun onStart() { 33 | super.onStart() 34 | mPresenter.let { 35 | it.onMvpStart() 36 | } 37 | } 38 | 39 | override fun onResume() { 40 | super.onResume() 41 | mPresenter.let { 42 | it.onMvpResume() 43 | } 44 | } 45 | 46 | override fun onPause() { 47 | super.onPause() 48 | mPresenter.let { 49 | it.onMvpPause() 50 | } 51 | } 52 | 53 | override fun onStop() { 54 | super.onStop() 55 | mPresenter.let { 56 | it.onMvpStop() 57 | } 58 | } 59 | 60 | override fun onSaveInstanceState(outState: Bundle) { 61 | super.onSaveInstanceState(outState) 62 | mPresenter.let { 63 | it.onMvpSaveInstanceState(outState) 64 | } 65 | } 66 | 67 | override fun onDestroy() { 68 | mLoadingDialog?.let { 69 | it.destroy() 70 | mLoadingDialog = null 71 | } 72 | mPresenter.let { 73 | it.onMvpDetachView(false) 74 | it.onMvpDestroy() 75 | } 76 | super.onDestroy() 77 | 78 | } 79 | 80 | override fun showLoading(content: String?) { 81 | if (mLoadingDialog == null) { 82 | mLoadingDialog = LoadingDialog.getInstance(context!!) 83 | mLoadingDialog!!.title = content ?: "正在加载..." 84 | if (!mLoadingDialog!!.isShowing) { 85 | mLoadingDialog!!.show() 86 | } 87 | } 88 | 89 | } 90 | 91 | override fun hideLoading() { 92 | mLoadingDialog?.let { 93 | mLoadingDialog!!.dismiss() 94 | } 95 | } 96 | 97 | override fun onResponseError(msg: String?) { 98 | msg?.let { 99 | showToast(msg) 100 | } 101 | } 102 | 103 | 104 | 105 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/model/OneMvpModel.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.model 2 | 3 | /** 4 | * @name OneMvpModel 5 | * @description //TODO 6 | * @createTime 2018/12/26 17:17 7 | * @author onestravel 8 | * @version 1.0.0 9 | */ 10 | interface OneMvpModel { 11 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/presenter/OneMvpPresenter.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.presenter 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.mvp.view.OneMvpView 5 | 6 | /** 7 | * @name OneMvpPresenterImpl 8 | * @description 所有界面presenter的接口类 9 | * @createTime 2018/12/12 16:27 10 | * @author onestravel 11 | * @version 1.0.0 12 | */ 13 | 14 | interface OneMvpPresenter { 15 | fun onMvpAttachView(view: V, savedInstanceState: Bundle?) 16 | 17 | fun onMvpStart() 18 | 19 | fun onMvpResume() 20 | 21 | fun onMvpPause() 22 | 23 | fun onMvpStop() 24 | 25 | fun onMvpSaveInstanceState(savedInstanceState: Bundle?) 26 | 27 | fun onMvpDetachView(retainInstance: Boolean) 28 | 29 | fun onMvpDestroy() 30 | 31 | fun init() 32 | 33 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/presenter/impl/OneMvpPresenterImpl.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.presenter.impl 2 | 3 | import android.os.Bundle 4 | import cn.onestravel.library.mvp.model.OneMvpModel 5 | import cn.onestravel.library.mvp.presenter.OneMvpPresenter 6 | import cn.onestravel.library.mvp.view.OneMvpView 7 | 8 | /** 9 | * @name OneMvpPresenterImpl 10 | * @description 所有Mvp 的Presenter 的基类,对生命周期进行处理 11 | * @createTime 2018/12/12 16:52 12 | * @author onestravel 13 | * @version 1.0.0 14 | */ 15 | open abstract class OneMvpPresenterImpl : OneMvpPresenter { 16 | 17 | protected val mModel: M? by lazy { createModel() } 18 | protected var mView: V? = null 19 | 20 | abstract fun createModel(): M? 21 | 22 | protected fun getView(): V? { 23 | return mView 24 | } 25 | 26 | protected fun isViewAttached(): Boolean { 27 | return mView != null 28 | } 29 | 30 | 31 | private fun attach(view: V, savedInstanceState: Bundle?) { 32 | mView = view 33 | } 34 | 35 | override fun onMvpAttachView(view: V, savedInstanceState: Bundle?) { 36 | attach(view, savedInstanceState) 37 | init() 38 | } 39 | 40 | override fun onMvpStart() { 41 | } 42 | 43 | override fun onMvpResume() { 44 | } 45 | 46 | override fun onMvpPause() { 47 | } 48 | 49 | override fun onMvpStop() { 50 | } 51 | 52 | override fun onMvpSaveInstanceState(savedInstanceState: Bundle?) { 53 | } 54 | 55 | override fun onMvpDetachView(retainInstance: Boolean) { 56 | detach(retainInstance) 57 | } 58 | 59 | override fun onMvpDestroy() { 60 | detach(true) 61 | } 62 | 63 | private fun detach(retainInstance: Boolean) { 64 | mView?.let { 65 | mView = null 66 | } 67 | } 68 | 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvp/view/OneMvpView.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvp.view 2 | 3 | /** 4 | * @name OneMvpView 5 | * @description //TODO 6 | * @createTime 2018/12/12 16:28 7 | * @author onestravel 8 | * @version 1.0.0 9 | */ 10 | interface OneMvpView { 11 | fun showLoading(content:String?="正在加载...") 12 | fun hideLoading() 13 | fun onResponseError(msg: String?) 14 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvvm/activity/OneMvvmActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvvm.activity 2 | 3 | import android.util.Log 4 | import android.view.View 5 | import androidx.lifecycle.Observer 6 | import androidx.lifecycle.ViewModelProvider 7 | import cn.onestravel.library.common.activity.OneActivity 8 | import cn.onestravel.library.mvvm.viewmodel.OneMvvmViewModel 9 | import java.lang.reflect.ParameterizedType 10 | 11 | /** 12 | * @name OneMvvmActivity 13 | * @description //TODO 14 | * @createTime 2018/12/26 17:13 15 | * @author onestravel 16 | * @version 1.0.0 17 | */ 18 | abstract class OneMvvmActivity : OneActivity() { 19 | private val lastClickTime: Long = 0 20 | protected var mViewModel: T? = null 21 | protected val TAG: String = this.javaClass.simpleName 22 | 23 | 24 | override fun initView() { 25 | try { 26 | mViewModel = getTClass()?.let { ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(it) } 27 | mViewModel!!.getToastResId()!!.observe(this, ToastResObserver()) 28 | mViewModel!!.getToast()!!.observe(this, ToastObserver()) 29 | } catch (e: java.lang.Exception) { 30 | Log.e( 31 | this.javaClass.name, 32 | "Activity must specify the type of the BaseViewModel subclass", 33 | e 34 | ) 35 | } 36 | super.initView() 37 | } 38 | 39 | 40 | protected open fun setToolBarTitle(title: String?) { 41 | try { // ((TextView) findViewById(R.id.toolbar_title)).setText(title); 42 | } catch (e: Exception) { 43 | } 44 | } 45 | 46 | 47 | protected open fun onBack() { 48 | finish() 49 | } 50 | 51 | 52 | private fun getTClass(): Class? { 53 | return (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class 54 | } 55 | 56 | 57 | protected open fun clickablePostDelay(view: View) { 58 | view.isClickable = false 59 | view.postDelayed({ view.isClickable = true }, 1000) 60 | } 61 | 62 | override fun onDestroy() { 63 | try { 64 | if (mViewModel != null) { 65 | mViewModel = null 66 | } 67 | } catch (e: Exception) { 68 | e.printStackTrace() 69 | } 70 | super.onDestroy() 71 | } 72 | 73 | inner class ToastResObserver : Observer { 74 | override fun onChanged(resId: Int) { 75 | showToast(resId) 76 | } 77 | 78 | 79 | } 80 | 81 | inner class ToastObserver : Observer { 82 | override fun onChanged(msg: String?) { 83 | msg?.let { 84 | showToast(msg) 85 | } 86 | 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvvm/fragment/OneMvvmFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvvm.fragment 2 | 3 | import android.util.Log 4 | import android.view.View 5 | import androidx.lifecycle.Observer 6 | import androidx.lifecycle.ViewModelProvider 7 | import cn.onestravel.library.common.fragment.OneFragment 8 | import cn.onestravel.library.mvvm.viewmodel.OneMvvmViewModel 9 | import com.trello.rxlifecycle3.LifecycleProvider 10 | import com.trello.rxlifecycle3.android.FragmentEvent 11 | 12 | import java.lang.reflect.ParameterizedType 13 | 14 | /** 15 | * @name .OneMvvmActivity 16 | * @description //TODO 17 | * @createTime 2018/12/26 17:13 18 | * @author onestravel 19 | * @version 1.0.0 20 | */ 21 | abstract class OneMvvmFragment : OneFragment(), 22 | LifecycleProvider { 23 | protected val TAG: String = this.javaClass.simpleName 24 | protected var viewModel:T? = null 25 | 26 | override fun initView(contentView: View) { 27 | try { 28 | viewModel = getTClass()?.let { ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(activity!!.application)).get(it) }; 29 | viewModel!!.getToastResId().observe(this, ToastResObserver()); 30 | viewModel!!.getToast().observe(this, ToastObserver()); 31 | } catch ( e:Exception) { 32 | Log.e(this.javaClass.name, "Fragment must specify the type of the BaseViewModel subclass", e); 33 | } 34 | super.initView(contentView) 35 | } 36 | 37 | open fun getTClass(): Class? { 38 | return (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class 39 | } 40 | 41 | 42 | 43 | 44 | protected open fun clickablePostDelay(view: View) { 45 | view.isClickable = false 46 | view.postDelayed({ view.isClickable = true }, 1000) 47 | } 48 | 49 | inner class ToastResObserver : Observer { 50 | override fun onChanged(resId: Int) { 51 | showToast(resId) 52 | } 53 | 54 | } 55 | 56 | inner class ToastObserver : Observer { 57 | override fun onChanged(msg: String) { 58 | showToast(msg) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvvm/model/OneMvvmModel.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvvm.model 2 | 3 | /** 4 | * @name OneMvvmModel 5 | * @description //TODO 6 | * @createTime 2018/12/26 17:16 7 | * @author onestravel 8 | * @version 1.0.0 9 | */ 10 | class OneMvvmModel { 11 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/mvvm/viewmodel/OneMvvmViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.mvvm.viewmodel 2 | 3 | import androidx.annotation.StringRes 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | 7 | /** 8 | * @name OneMvvmViewModel 9 | * @description //TODO 10 | * @createTime 2018/12/26 17:16 11 | * @author onestravel 12 | * @version 1.0.0 13 | */ 14 | class OneMvvmViewModel: ViewModel() { 15 | val TAG = this.javaClass.simpleName 16 | private val toastResId = MutableLiveData() 17 | private val toast = MutableLiveData() 18 | 19 | fun showToast(@StringRes resId: Int) { 20 | toastResId.postValue(resId) 21 | } 22 | 23 | fun getToastResId(): MutableLiveData { 24 | return toastResId 25 | } 26 | 27 | 28 | fun showToast(msg: String) { 29 | toast.postValue(msg) 30 | } 31 | 32 | fun getToast(): MutableLiveData { 33 | return toast 34 | } 35 | 36 | override fun onCleared() { 37 | super.onCleared() 38 | } 39 | 40 | 41 | 42 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/activity/OneRxActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.activity 2 | 3 | import android.os.Bundle 4 | import androidx.annotation.CallSuper 5 | import androidx.annotation.CheckResult 6 | import cn.onestravel.library.common.activity.OneActivity 7 | import com.trello.rxlifecycle3.LifecycleProvider 8 | import com.trello.rxlifecycle3.LifecycleTransformer 9 | import com.trello.rxlifecycle3.RxLifecycle 10 | import com.trello.rxlifecycle3.android.ActivityEvent 11 | import com.trello.rxlifecycle3.android.RxLifecycleAndroid 12 | import io.reactivex.Observable 13 | import io.reactivex.subjects.BehaviorSubject 14 | 15 | /** 16 | * @name OneRxActivity 17 | * @description 处理RXJava的生命周期的Activity 18 | * @createTime 2018/12/12 17:00 19 | * @author onestravel 20 | * @version 1.0.0 21 | */ 22 | abstract class OneRxActivity : OneActivity(), LifecycleProvider { 23 | private val lifecycleSubject:BehaviorSubject = BehaviorSubject.create() 24 | 25 | @CheckResult 26 | override fun lifecycle(): Observable { 27 | return lifecycleSubject.hide() 28 | } 29 | 30 | @CheckResult 31 | override fun bindUntilEvent(event: ActivityEvent): LifecycleTransformer { 32 | return RxLifecycle.bindUntilEvent(lifecycleSubject, event) 33 | } 34 | 35 | @CheckResult 36 | override fun bindToLifecycle(): LifecycleTransformer { 37 | return RxLifecycleAndroid.bindActivity(lifecycleSubject) 38 | } 39 | 40 | @CallSuper 41 | override fun onCreate(savedInstanceState: Bundle?) { 42 | super.onCreate(savedInstanceState) 43 | lifecycleSubject.onNext(ActivityEvent.CREATE) 44 | } 45 | 46 | @CallSuper 47 | override fun onStart() { 48 | super.onStart() 49 | lifecycleSubject.onNext(ActivityEvent.START) 50 | } 51 | 52 | @CallSuper 53 | override fun onResume() { 54 | super.onResume() 55 | lifecycleSubject.onNext(ActivityEvent.RESUME) 56 | } 57 | 58 | @CallSuper 59 | override fun onPause() { 60 | lifecycleSubject.onNext(ActivityEvent.PAUSE) 61 | super.onPause() 62 | } 63 | 64 | @CallSuper 65 | override fun onStop() { 66 | lifecycleSubject.onNext(ActivityEvent.STOP) 67 | super.onStop() 68 | } 69 | 70 | @CallSuper 71 | override fun onDestroy() { 72 | lifecycleSubject.onNext(ActivityEvent.DESTROY) 73 | super.onDestroy() 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/activity/OneRxListActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.activity 2 | 3 | import android.os.Bundle 4 | import androidx.annotation.CallSuper 5 | import androidx.annotation.CheckResult 6 | import cn.onestravel.library.common.activity.OneListActivity 7 | import com.trello.rxlifecycle3.LifecycleProvider 8 | import com.trello.rxlifecycle3.LifecycleTransformer 9 | import com.trello.rxlifecycle3.RxLifecycle 10 | import com.trello.rxlifecycle3.android.ActivityEvent 11 | import com.trello.rxlifecycle3.android.RxLifecycleAndroid 12 | import io.reactivex.Observable 13 | import io.reactivex.subjects.BehaviorSubject 14 | 15 | /** 16 | * @name OneRxListActivity 17 | * @description 处理RXJava的生命周期的ListActivity 18 | * @createTime 2018/12/12 17:00 19 | * @author onestravel 20 | * @version 1.0.0 21 | */ 22 | abstract class OneRxListActivity : OneListActivity(), LifecycleProvider { 23 | private val lifecycleSubject:BehaviorSubject = BehaviorSubject.create() 24 | 25 | @CheckResult 26 | override fun lifecycle(): Observable { 27 | return lifecycleSubject.hide() 28 | } 29 | 30 | @CheckResult 31 | override fun bindUntilEvent(event: ActivityEvent): LifecycleTransformer { 32 | return RxLifecycle.bindUntilEvent(lifecycleSubject, event) 33 | } 34 | 35 | @CheckResult 36 | override fun bindToLifecycle(): LifecycleTransformer { 37 | return RxLifecycleAndroid.bindActivity(lifecycleSubject) 38 | } 39 | 40 | @CallSuper 41 | override fun onCreate(savedInstanceState: Bundle?) { 42 | super.onCreate(savedInstanceState) 43 | lifecycleSubject.onNext(ActivityEvent.CREATE) 44 | } 45 | 46 | @CallSuper 47 | override fun onStart() { 48 | super.onStart() 49 | lifecycleSubject.onNext(ActivityEvent.START) 50 | } 51 | 52 | @CallSuper 53 | override fun onResume() { 54 | super.onResume() 55 | lifecycleSubject.onNext(ActivityEvent.RESUME) 56 | } 57 | 58 | @CallSuper 59 | override fun onPause() { 60 | lifecycleSubject.onNext(ActivityEvent.PAUSE) 61 | super.onPause() 62 | } 63 | 64 | @CallSuper 65 | override fun onStop() { 66 | lifecycleSubject.onNext(ActivityEvent.STOP) 67 | super.onStop() 68 | } 69 | 70 | @CallSuper 71 | override fun onDestroy() { 72 | lifecycleSubject.onNext(ActivityEvent.DESTROY) 73 | super.onDestroy() 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/HttpCommonInterceptor.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import android.text.TextUtils 4 | import okhttp3.* 5 | 6 | import java.io.IOException 7 | import java.util.HashMap 8 | 9 | /** 10 | * @name cn.onestravel.library.kotlin.rxrequest.common.HttpCommonInterceptor 11 | * @description 添加公共参数请求拦截器 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | class HttpCommonInterceptor private constructor(private val mHeaderParamsMap: Map?) : Interceptor { 17 | private val TAG = "request" 18 | 19 | @Throws(IOException::class) 20 | override fun intercept(chain: Interceptor.Chain): Response { 21 | val builder = FormBody.Builder() 22 | val oldRequest = chain.request() 23 | val mBuilder = oldRequest.url().newBuilder() 24 | //添加公共参数 25 | if (mHeaderParamsMap != null && mHeaderParamsMap!!.isNotEmpty()) { 26 | for (entry in mHeaderParamsMap!!.entries) { 27 | if (TextUtils.isEmpty(entry.value)) { 28 | builder.add(entry.key, "") 29 | } else { 30 | builder.add(entry.key, entry.value) 31 | } 32 | } 33 | } 34 | //将本次请求的参数添加进去 35 | if (oldRequest.body() is FormBody) { 36 | val body = oldRequest.body() as FormBody? 37 | for (i in 0 until body!!.size()) { 38 | if (TextUtils.isEmpty(body.encodedValue(i))) { 39 | builder.add(body.encodedName(i), "") 40 | } else { 41 | builder.add(body.encodedName(i), body.encodedValue(i)) 42 | } 43 | } 44 | } 45 | //生成新的请求 46 | val request = oldRequest.newBuilder().url(mBuilder.build()).post(builder.build()).build() 47 | //打印请求参数相关代码开始 48 | val sb = StringBuilder() 49 | val body = request.body() as FormBody? 50 | var method_code = "" 51 | for (i in 0 until body!!.size()) { 52 | if ("method_code" == body.encodedName(i)) { 53 | method_code = body.encodedValue(i) 54 | } 55 | sb.append(body.encodedName(i) + "=" + body.encodedValue(i) + "&") 56 | } 57 | sb.delete(sb.length - 1, sb.length) 58 | println("接口【 " + method_code + "】RequestParams==== " + request.url() + "?" + sb.toString()) 59 | //打印请求参数相关代码结束 60 | return chain.proceed(request) 61 | } 62 | 63 | 64 | class Builder { 65 | private val mHeaderParamsMap: MutableMap 66 | init { 67 | mHeaderParamsMap = HashMap() 68 | } 69 | 70 | fun addParams(key: String, value: String): Builder { 71 | mHeaderParamsMap[key] = value 72 | return this 73 | } 74 | 75 | fun build(): HttpCommonInterceptor { 76 | return HttpCommonInterceptor(mHeaderParamsMap) 77 | } 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/ObserverResult.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import io.reactivex.disposables.Disposable 4 | 5 | /** 6 | * @name cn.onestravel.library.kotlin.rxrequest.common.ObserverResult 7 | * @description //TODO 8 | * @createTime 2018/12/13 12:11 9 | * @author onestravel 10 | * @version 1.0.0 11 | */ 12 | interface ObserverResult { 13 | 14 | /** 15 | * 请求开始 处理基本的loading框的显示等 16 | * @param d 17 | */ 18 | fun onStart(d: Disposable) 19 | 20 | /** 21 | * 此方法必须实现 22 | * @param result 请求成功的结果 23 | */ 24 | fun onSuccess(result: R) 25 | 26 | /** 27 | * 请求失败 28 | * @param code 错误码 29 | * @param msg 错误提示语 30 | */ 31 | fun onFailure(code: String, msg: String?) 32 | 33 | /** 34 | * 请求都完成时之行此方法 35 | */ 36 | fun onFinish() 37 | 38 | companion object { 39 | private val TAG = "request" 40 | } 41 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/OneObserver.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import android.util.Log 4 | import com.alibaba.fastjson.JSON 5 | import io.reactivex.Observer 6 | import io.reactivex.disposables.Disposable 7 | import retrofit2.HttpException 8 | 9 | /** 10 | * @name cn.onestravel.library.kotlin.rxrequest.common.OneObserver 11 | * @description 请求返回结果,返回json数据必须符合 {"code":"0000","msg":""} 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneObserver : Observer,ObserverResult { 17 | 18 | /** 19 | * 请求开始 处理基本的loading框的显示等 20 | * 21 | * @param d 22 | */ 23 | override fun onStart(d: Disposable) { 24 | Log.e( 25 | TAG, 26 | "===========单个接口请求开始 ==========" 27 | ) 28 | } 29 | 30 | /** 31 | * 此方法必须实现 32 | * 33 | * @param result 请求成功的结果 34 | */ 35 | abstract override fun onSuccess(result: T) 36 | 37 | /** 38 | * 请求失败 39 | * 40 | * @param code 错误码 41 | * @param msg 错误提示语 42 | */ 43 | override fun onFailure(code: String, msg: String?) { 44 | Log.e( 45 | TAG, 46 | "接口请求失败============code = " + code + "errorMsg =" + msg 47 | ) 48 | } 49 | 50 | /** 51 | * 请求都完成时之行此方法 52 | */ 53 | override fun onFinish() { 54 | 55 | } 56 | 57 | override fun onSubscribe(d: Disposable) { 58 | onStart(d) 59 | } 60 | 61 | override fun onNext(result: T) { 62 | if (OneResponse.REQUEST_OK == result.code) { 63 | onSuccess(result) 64 | Log.i(TAG, "请求成功responseBody====" + JSON.toJSONString(result)) 65 | } else { 66 | onFailure(result.code, result.msg) 67 | } 68 | 69 | } 70 | 71 | override fun onError(e: Throwable) { 72 | var errorMsg = "" 73 | var errorCode = 0 74 | if (e is HttpException) { 75 | val httpException = e as HttpException 76 | errorCode = httpException.response().code() 77 | if (404 == errorCode || 500 == errorCode) { 78 | errorMsg = "请求异常,请稍候重试!" 79 | } else { 80 | 81 | } 82 | 83 | } else { 84 | //todo 设置固定的错误码及错误提示 85 | } 86 | onFailure(errorCode.toString(), errorMsg) 87 | } 88 | 89 | override fun onComplete() { 90 | onFinish() 91 | } 92 | 93 | companion object { 94 | private val TAG = "OneObserver" 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/OneObserver1.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import android.util.Log 4 | import com.alibaba.fastjson.JSON 5 | import io.reactivex.Observer 6 | import io.reactivex.disposables.Disposable 7 | import retrofit2.HttpException 8 | import java.io.Serializable 9 | 10 | /** 11 | * @name cn.onestravel.library.kotlin.rxrequest.common.OneObserver 12 | * @description 请求返回结果,返回json数据必须符合 {"code":"0000","msg":"","data":{},"datas":[]},data 和 datas 的数据 bean 相同 13 | * @createTime 2018/12/12 17:00 14 | * @author onestravel 15 | * @version 1.0.0 16 | */ 17 | abstract class OneObserver1 : Observer>,ObserverResult> { 18 | 19 | /** 20 | * 请求开始 处理基本的loading框的显示等 21 | * 22 | * @param d 23 | */ 24 | override fun onStart(d: Disposable) { 25 | Log.e( 26 | TAG, 27 | "===========单个接口请求开始 ==========" 28 | ) 29 | } 30 | 31 | /** 32 | * 此方法必须实现 33 | * 34 | * @param result 请求成功的结果 35 | */ 36 | abstract override fun onSuccess(result: ResponseResult1) 37 | 38 | /** 39 | * 请求失败 40 | * 41 | * @param code 错误码 42 | * @param msg 错误提示语 43 | */ 44 | override fun onFailure(code: String, msg: String?) { 45 | Log.e( 46 | TAG, 47 | "接口请求失败============code = " + code + "errorMsg =" + msg ) 48 | } 49 | 50 | /** 51 | * 请求都完成时之行此方法 52 | */ 53 | override fun onFinish() { 54 | 55 | } 56 | 57 | override fun onSubscribe(d: Disposable) { 58 | onStart(d) 59 | } 60 | 61 | override fun onNext(result: ResponseResult1) { 62 | if (OneResponse.REQUEST_OK == result.code) { 63 | onSuccess(result) 64 | Log.i(TAG, "请求成功responseBody====" + JSON.toJSONString(result)) 65 | } else { 66 | onFailure(result.code, result.msg) 67 | } 68 | 69 | } 70 | 71 | override fun onError(e: Throwable) { 72 | var errorMsg = "" 73 | var errorCode = 0 74 | if (e is HttpException) { 75 | val httpException = e as HttpException 76 | errorCode = httpException.response().code() 77 | if (404 == errorCode || 500 == errorCode) { 78 | errorMsg = "请求异常,请稍候重试!" 79 | } else { 80 | 81 | } 82 | 83 | } else { 84 | //todo 设置固定的错误码及错误提示 85 | } 86 | onFailure(errorCode.toString(), errorMsg) 87 | } 88 | 89 | override fun onComplete() { 90 | onFinish() 91 | } 92 | 93 | companion object { 94 | private val TAG = "OneObserver1" 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/OneObserver2.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import android.util.Log 4 | import io.reactivex.Observer 5 | import io.reactivex.disposables.Disposable 6 | import retrofit2.HttpException 7 | import java.io.Serializable 8 | 9 | /** 10 | * @name cn.onestravel.library.kotlin.rxrequest.common.OneObserver2 11 | * @description 请求返回结果,返回json数据必须符合 {"code":"0000","msg":"","data":{},"datas":[]},data 和 datas 的数据 bean 可以不相同 12 | * @createTime 2018/12/12 17:00 13 | * @author onestravel 14 | * @version 1.0.0 15 | */ 16 | abstract class OneObserver2 : Observer>, ObserverResult> { 17 | /** 18 | * 请求开始 处理基本的loading框的显示等 19 | * 20 | * @param d 21 | */ 22 | override fun onStart(d: Disposable) { 23 | Log.e( 24 | OneObserver2.TAG, 25 | "===========单个接口请求开始 ==========" 26 | ) 27 | } 28 | 29 | /** 30 | * 此方法必须实现 31 | * 32 | * @param result 请求成功的结果 33 | */ 34 | abstract override fun onSuccess(result: ResponseResult2) 35 | 36 | /** 37 | * 请求失败 38 | * 39 | * @param code 错误码 40 | * @param msg 错误提示语 41 | */ 42 | override fun onFailure(code: String, msg: String?) { 43 | Log.e( 44 | OneObserver2.TAG, 45 | "接口请求失败============code = " + code + "errorMsg =" + msg ) 46 | } 47 | 48 | /** 49 | * 请求都完成时之行此方法 50 | */ 51 | override fun onFinish() { 52 | 53 | } 54 | 55 | override fun onSubscribe(d: Disposable) { 56 | onStart(d) 57 | } 58 | override fun onNext(baseObject: ResponseResult2) { 59 | // Log.i("responseBody====",) 60 | if (OneResponse.REQUEST_OK == baseObject.code) { 61 | onSuccess(baseObject) 62 | } else { 63 | onFailure(baseObject.code, baseObject.msg) 64 | } 65 | } 66 | 67 | /** 68 | * 69 | */ 70 | override fun onError(e: Throwable) { 71 | var errorMsg = "" 72 | var errorCode = 0 73 | if (e is HttpException) { 74 | val httpException = e as HttpException 75 | errorCode = httpException.response().code() 76 | if (404 == errorCode || 500 == errorCode) { 77 | errorMsg = "请求异常,请稍候重试!" 78 | } else { 79 | 80 | } 81 | 82 | } else { 83 | //todo 设置固定的错误码及错误提示 84 | } 85 | onFailure(errorCode.toString(), errorMsg) 86 | } 87 | 88 | override fun onComplete() { 89 | onFinish() 90 | } 91 | 92 | companion object { 93 | private val TAG = "OneObserver2" 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/OneResponse.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * @name cn.onestravel.library.kotlin.rxrequest.common.OneResponse 7 | * @description 请求返回结果数据基类 8 | * @createTime 2018/12/12 17:00 9 | * @author onestravel 10 | * @version 1.0.0 11 | */ 12 | open class OneResponse(val code: String = "0000", val msg: String = ""): Serializable { 13 | companion object { 14 | val REQUEST_OK = "0000" //请求成功的code码 15 | val REQUEST_ERROR = "-1" //请求失败的code码 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/ResponseResult.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * @name cn.onestravel.library.kotlin.rxrequest.common.ResponseResult 7 | * @description 请求返回结果数据 符合 {"code":"0000","msg":"","data":{},"datas":[]} 的基类 8 | * @createTime 2018/12/12 17:00 9 | * @author onestravel 10 | * @version 1.0.0 11 | */ 12 | class ResponseResult :OneResponse(), Serializable 13 | 14 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/ResponseResult1.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * @name cn.onestravel.library.kotlin.rxrequest.common.ResponseResult 7 | * @description 请求返回结果数据 符合 {"code":"0000","msg":"","data":{},"datas":[]} 的基类 8 | * @createTime 2018/12/12 17:00 9 | * @author onestravel 10 | * @version 1.0.0 11 | */ 12 | class ResponseResult1( 13 | val data: DATA?, 14 | val datas: MutableList? = ArrayList() 15 | ) :OneResponse(), Serializable 16 | 17 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/ResponseResult2.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * @name cn.onestravel.library.kotlin.rxrequest.common.ResponseResult 7 | * @description 请求返回结果数据 符合 {"code":"0000","msg":"","data":{},"datas":[]} 的基类 8 | * @createTime 2018/12/12 17:00 9 | * @author onestravel 10 | * @version 1.0.0 11 | */ 12 | class ResponseResult2( 13 | val data: DATA?, 14 | val datas: MutableList? = ArrayList() 15 | ) :OneResponse(), Serializable 16 | 17 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/common/RetryInterceptor.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.common 2 | 3 | import okhttp3.Interceptor 4 | import okhttp3.Response 5 | 6 | import java.io.IOException 7 | 8 | /** 9 | * @name cn.onestravel.library.kotlin.rxrequest.common.RetryInterceptor 10 | * @description 请求失败重试拦截器 11 | * @createTime 2018/12/12 17:00 12 | * @author onestravel 13 | * @version 1.0.0 14 | */ 15 | class RetryInterceptor( 16 | var maxRetry: Int//最大重试次数 17 | ) : Interceptor { 18 | private var retryNum = 0//假如设置为3次重试的话,则最大可能请求4次(默认1次+3次重试) 19 | 20 | 21 | @Throws(IOException::class) 22 | override fun intercept(chain: Interceptor.Chain): Response { 23 | val request = chain.request() 24 | println("retryNum=$retryNum") 25 | var response = chain.proceed(request) 26 | while (!response.isSuccessful() && retryNum < maxRetry) { 27 | retryNum++ 28 | println("retryNum=$retryNum") 29 | response = chain.proceed(request) 30 | } 31 | return response 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/fragment/OneRxFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.fragment 2 | 3 | import android.os.Bundle 4 | import androidx.annotation.CallSuper 5 | import androidx.annotation.CheckResult 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import cn.onestravel.library.common.fragment.OneFragment 10 | import com.trello.rxlifecycle3.LifecycleProvider 11 | import com.trello.rxlifecycle3.LifecycleTransformer 12 | import com.trello.rxlifecycle3.RxLifecycle 13 | import com.trello.rxlifecycle3.android.FragmentEvent 14 | import com.trello.rxlifecycle3.android.RxLifecycleAndroid 15 | import io.reactivex.Observable 16 | import io.reactivex.subjects.BehaviorSubject 17 | 18 | /** 19 | * @name OneRxFragment 20 | * @description 处理RXJava的生命周期的 Fragment 21 | * @createTime 2018/12/12 17:00 22 | * @author onestravel 23 | * @version 1.0.0 24 | */ 25 | abstract class OneRxFragment : OneFragment(), LifecycleProvider { 26 | private val lifecycleSubject:BehaviorSubject = BehaviorSubject.create() 27 | 28 | override fun lifecycle(): Observable { 29 | return lifecycleSubject.hide() 30 | } 31 | 32 | @CheckResult 33 | override fun bindUntilEvent(event: FragmentEvent): LifecycleTransformer { 34 | return RxLifecycle.bindUntilEvent(lifecycleSubject, event) 35 | } 36 | 37 | @CheckResult 38 | override fun bindToLifecycle(): LifecycleTransformer { 39 | return RxLifecycleAndroid.bindFragment(lifecycleSubject) 40 | } 41 | 42 | @CallSuper 43 | override fun onCreate(savedInstanceState: Bundle?) { 44 | super.onCreate(savedInstanceState) 45 | lifecycleSubject.onNext(FragmentEvent.CREATE) 46 | } 47 | 48 | 49 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 50 | lifecycleSubject.onNext(FragmentEvent.CREATE_VIEW) 51 | return super.onCreateView(inflater, container, savedInstanceState) 52 | } 53 | 54 | 55 | @CallSuper 56 | override fun onStart() { 57 | super.onStart() 58 | lifecycleSubject.onNext(FragmentEvent.START) 59 | } 60 | 61 | @CallSuper 62 | override fun onResume() { 63 | super.onResume() 64 | lifecycleSubject.onNext(FragmentEvent.RESUME) 65 | } 66 | 67 | @CallSuper 68 | override fun onPause() { 69 | lifecycleSubject.onNext(FragmentEvent.PAUSE) 70 | super.onPause() 71 | } 72 | 73 | @CallSuper 74 | override fun onStop() { 75 | lifecycleSubject.onNext(FragmentEvent.STOP) 76 | super.onStop() 77 | } 78 | 79 | override fun onDestroyView() { 80 | lifecycleSubject.onNext(FragmentEvent.DESTROY_VIEW) 81 | super.onDestroyView() 82 | } 83 | 84 | @CallSuper 85 | override fun onDestroy() { 86 | lifecycleSubject.onNext(FragmentEvent.DESTROY) 87 | super.onDestroy() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/fragment/OneRxListFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.fragment 2 | 3 | import android.os.Bundle 4 | import androidx.annotation.CallSuper 5 | import androidx.annotation.CheckResult 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import cn.onestravel.library.common.fragment.OneListFragment 10 | import com.trello.rxlifecycle3.LifecycleProvider 11 | import com.trello.rxlifecycle3.LifecycleTransformer 12 | import com.trello.rxlifecycle3.RxLifecycle 13 | import com.trello.rxlifecycle3.android.FragmentEvent 14 | import com.trello.rxlifecycle3.android.RxLifecycleAndroid 15 | import io.reactivex.Observable 16 | import io.reactivex.subjects.BehaviorSubject 17 | 18 | /** 19 | * @name OneRxListFragment 20 | * @description 处理RXJava的生命周期的 ListFragment 21 | * @createTime 2018/12/12 17:00 22 | * @author onestravel 23 | * @version 1.0.0 24 | */ 25 | abstract class OneRxListFragment : OneListFragment(), LifecycleProvider { 26 | private val lifecycleSubject:BehaviorSubject = BehaviorSubject.create() 27 | 28 | override fun lifecycle(): Observable { 29 | return lifecycleSubject.hide() 30 | } 31 | 32 | @CheckResult 33 | override fun bindUntilEvent(event: FragmentEvent): LifecycleTransformer { 34 | return RxLifecycle.bindUntilEvent(lifecycleSubject, event) 35 | } 36 | 37 | @CheckResult 38 | override fun bindToLifecycle(): LifecycleTransformer { 39 | return RxLifecycleAndroid.bindFragment(lifecycleSubject) 40 | } 41 | 42 | @CallSuper 43 | override fun onCreate(savedInstanceState: Bundle?) { 44 | super.onCreate(savedInstanceState) 45 | lifecycleSubject.onNext(FragmentEvent.CREATE) 46 | } 47 | 48 | 49 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 50 | lifecycleSubject.onNext(FragmentEvent.CREATE_VIEW) 51 | return super.onCreateView(inflater, container, savedInstanceState) 52 | } 53 | 54 | 55 | @CallSuper 56 | override fun onStart() { 57 | super.onStart() 58 | lifecycleSubject.onNext(FragmentEvent.START) 59 | } 60 | 61 | @CallSuper 62 | override fun onResume() { 63 | super.onResume() 64 | lifecycleSubject.onNext(FragmentEvent.RESUME) 65 | } 66 | 67 | @CallSuper 68 | override fun onPause() { 69 | lifecycleSubject.onNext(FragmentEvent.PAUSE) 70 | super.onPause() 71 | } 72 | 73 | @CallSuper 74 | override fun onStop() { 75 | lifecycleSubject.onNext(FragmentEvent.STOP) 76 | super.onStop() 77 | } 78 | 79 | override fun onDestroyView() { 80 | lifecycleSubject.onNext(FragmentEvent.DESTROY_VIEW) 81 | super.onDestroyView() 82 | } 83 | 84 | @CallSuper 85 | override fun onDestroy() { 86 | lifecycleSubject.onNext(FragmentEvent.DESTROY) 87 | super.onDestroy() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/loader/OneLoader.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.loader 2 | 3 | 4 | import cn.onestravel.library.rxrequest.service.OneService 5 | import cn.onestravel.library.rxrequest.service.RetrofitServiceManager 6 | import io.reactivex.Observable 7 | import io.reactivex.android.schedulers.AndroidSchedulers 8 | import io.reactivex.schedulers.Schedulers 9 | 10 | /** 11 | * @name OneLoader 12 | * @description 封装公共loader进行线程切换 13 | * @createTime 2018/12/12 17:00 14 | * @author onestravel 15 | * @version 1.0.0 16 | */ 17 | abstract class OneLoader { 18 | protected val mServiceManager: RetrofitServiceManager by lazy { createServiceManager() } 19 | protected val mService: S by lazy { createService() } 20 | 21 | /** 22 | * 创建 ServiceManager 实例 23 | */ 24 | abstract fun createServiceManager(): RetrofitServiceManager 25 | 26 | /** 27 | * 创建 Service 实例 28 | */ 29 | abstract fun createService(): S 30 | 31 | /** 32 | * 设置Observable的工作线程 33 | * @param observable 34 | * @param 35 | * @return 36 | */ 37 | fun observe(observable: Observable): Observable { 38 | return observable.subscribeOn(Schedulers.io()) 39 | .unsubscribeOn(Schedulers.io()) 40 | .observeOn(AndroidSchedulers.mainThread()) 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/service/OneService.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.service 2 | 3 | /** 4 | * @name cn.onestravel.library.kotlin.rxrequest.service.OneService 5 | * @description 所有 Retrofit 请求的 Service 的基类 6 | * @createTime 2018/12/13 11:12 7 | * @author onestravel 8 | * @version 1.0.0 9 | */ 10 | interface OneService { 11 | } -------------------------------------------------------------------------------- /kotlinbase/src/main/java/cn/onestravel/library/rxrequest/service/RetrofitServiceManager.kt: -------------------------------------------------------------------------------- 1 | package cn.onestravel.library.rxrequest.service 2 | 3 | import cn.onestravel.library.rxrequest.common.HttpCommonInterceptor 4 | import cn.onestravel.library.rxrequest.common.RetryInterceptor 5 | import okhttp3.OkHttpClient 6 | import retrofit2.Retrofit 7 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory 8 | import retrofit2.converter.gson.GsonConverterFactory 9 | 10 | import java.util.concurrent.TimeUnit 11 | 12 | 13 | /** 14 | * @name cn.onestravel.library.kotlin.rxrequest.service.RetrofitServiceManager 15 | * @description 生成接口实例的管理类 16 | * @createTime 2018/12/12 17:00 17 | * @author onestravel 18 | * @version 1.0.0 19 | */ 20 | abstract class RetrofitServiceManager() { 21 | protected val mRetrofit: Retrofit 22 | 23 | init { 24 | val interceptorBuild = HttpCommonInterceptor.Builder() 25 | val okHttpClientBuild = OkHttpClient.Builder() 26 | okHttpClientBuild.connectTimeout(CONNECTION_TIMEOUT.toLong(), TimeUnit.SECONDS) 27 | .readTimeout(READ_TIMEOUT.toLong(), TimeUnit.SECONDS) 28 | .writeTimeout(WRITE_TIMEOUT.toLong(), TimeUnit.SECONDS) 29 | .addInterceptor(interceptorBuild.build())//拦截器添加公共请求参数 30 | .addInterceptor(RetryInterceptor(2))//重试三次的拦截 31 | 32 | //初始化Retrofit 33 | mRetrofit = Retrofit.Builder() 34 | .baseUrl(getBaseUrl()) 35 | .addConverterFactory(GsonConverterFactory.create()) 36 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 37 | .client(okHttpClientBuild.build()) 38 | .build() 39 | 40 | } 41 | abstract fun getBaseUrl(): String 42 | 43 | 44 | /** 45 | * 生成对应接口的实例 46 | * 47 | * @param service 48 | * @param 49 | * @return 50 | */ 51 | fun create(service: Class): T { 52 | return mRetrofit.create(service) 53 | 54 | } 55 | 56 | companion object { 57 | private const val CONNECTION_TIMEOUT = 5 58 | private const val READ_TIMEOUT = 20 59 | private const val WRITE_TIMEOUT = 10 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/bg_round_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/circle_text_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/empty_no_data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/empty_no_data.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/ic_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/ic_loading.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/load_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/load_error.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 9 | 11 | 12 | 13 | 15 | 16 | 17 | 19 | 20 | 21 | 23 | 24 | 25 | 27 | 28 | 29 | 31 | 32 | 33 | 35 | 36 | 37 | 39 | 40 | 41 | 43 | 44 | 45 | 47 | 48 | 49 | 51 | 52 | -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_0.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_1.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_10.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_11.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_12.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_2.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_3.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_4.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_5.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_6.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_7.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_8.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_9.png -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /kotlinbase/src/main/res/drawable/loading_gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onestravel/kotlin-common/d294e4a2d1e93e269d6a9f14844bd8a30776b1dd/kotlinbase/src/main/res/drawable/loading_gif.gif -------------------------------------------------------------------------------- /kotlinbase/src/main/res/layout/dialog_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 20 | 28 | 29 | 39 | 40 | -------------------------------------------------------------------------------- /kotlinbase/src/main/res/layout/layout_base_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /kotlinbase/src/main/res/layout/layout_tab_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 9 | 14 | 26 | 27 | 32 | 33 | -------------------------------------------------------------------------------- /kotlinbase/src/main/res/layout/view_empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 23 | 24 | 34 | 35 | 36 | 37 | 38 | 44 | 45 | 55 | 56 | 66 | 67 |