: BaseFragment(), IView {
16 | override fun getCtx() = context
17 |
18 | override fun onActivityCreated(savedInstanceState: Bundle?) {
19 | super.onActivityCreated(savedInstanceState)
20 | inited()
21 | }
22 | override fun finish(resultCode: Int) {
23 | }
24 | override fun showToast(message: String) {
25 | toast(message)
26 | }
27 | override fun showToast(srtResId: Int) {
28 | showToast(resources.getString(srtResId))
29 | }
30 | override fun showLoading(msg: String) {
31 | showProgressDialog(msg)
32 | }
33 |
34 | override fun showLoading(srtResId: Int) {
35 | showProgressDialog(resources.getString(srtResId))
36 | }
37 |
38 | override fun dismissLoading() {
39 | dismissProgressDialog()
40 | }
41 | }
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/mvp/BaseMvpActivity.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.mvp
2 |
3 | import android.os.Bundle
4 | import com.exmple.baselib.base.BaseActivity
5 | import com.exmple.baselib.http.toast
6 |
7 | /**
8 | * @FileName: BaseMvpActivity.java
9 | * @author: villa_mou
10 | * @date: 06-15:48
11 | * @version V1.0 <描述当前版本功能>
12 | * @desc
13 | */
14 | abstract class BaseMvpActivity : BaseActivity(), IView {
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | super.onCreate(savedInstanceState)
17 | inited()
18 | }
19 | override fun getCtx() = this
20 | override fun showLoading(msg: String) {
21 | progressDialog?.showProgressDialogWithText(msg)
22 | }
23 |
24 | override fun finish(resultCode: Int) {
25 | finish()
26 | }
27 |
28 | override fun showLoading(srtResId: Int) {
29 | progressDialog?.showProgressDialogWithText(resources.getString(srtResId))
30 | }
31 |
32 | override fun dismissLoading() {
33 | progressDialog?.dismissProgressDialog()
34 | }
35 |
36 | override fun showToast(message: String) {
37 | toast(message)
38 | }
39 |
40 | override fun showToast(srtResId: Int) {
41 | showToast(resources.getString(srtResId))
42 | }
43 | }
--------------------------------------------------------------------------------
/baselib/src/main/res/layout/dialog_netwrok.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
21 |
22 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/exmple/baseprojectmvp/mvp/view/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baseprojectmvp.mvp.view
2 |
3 | import com.exmple.baseprojectmvp.R
4 | import com.exmple.baseprojectmvp.mvp.adapter.DemoAdapter
5 | import com.exmple.baseprojectmvp.mvp.contract.IMainContact
6 | import com.exmple.baseprojectmvp.mvp.presenter.MainPresenter
7 | import com.exmple.baselib.mvp.BaseMvpListActivity
8 |
9 |
10 | class MainActivity : BaseMvpListActivity(), IMainContact.View {
11 |
12 | override var mPresenter: IMainContact.Presenter = MainPresenter()
13 | override val setRefreshEnable = true
14 | override val setRecyclerViewBgColor = R.color.white
15 | override fun initData() {
16 | super.initData()
17 | val data = ArrayList()
18 | data.add("")
19 | data.add("")
20 | data.add("")
21 | val demoAdapter = DemoAdapter(data = data)
22 | mRecyclerView.adapter = demoAdapter
23 | demoAdapter.setOnLoadMoreListener({ demoAdapter.loadMoreEnd() }, mRecyclerView)
24 | }
25 |
26 | override fun onRetry() {
27 |
28 | }
29 |
30 | override fun onRefresh() {
31 | mRefreshLayout.finishRefresh(false)
32 | }
33 |
34 | override fun loadMoreFail(isRefresh: Boolean) {
35 |
36 | }
37 |
38 |
39 | override fun getDataSuccess() {
40 |
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/mvp/BaseMvpListFragment.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.mvp
2 |
3 | import android.support.v4.content.ContextCompat
4 | import android.support.v7.widget.RecyclerView
5 | import com.exmple.baselib.R
6 | import com.exmple.baselib.state.IStateView
7 | import com.scwang.smartrefresh.layout.SmartRefreshLayout
8 | import kotlinx.android.synthetic.main.layout_list.*
9 |
10 | /**
11 | * Created by mou on 2018/5/6
12 | */
13 | abstract class BaseMvpListFragment : BaseMvpFragment(), IListView {
14 | override fun getContentView() = R.layout.layout_list
15 | override val mStateView: IStateView by lazy { list_sv }
16 | override val mRecyclerView: RecyclerView by lazy { list_rv }
17 | override val mRefreshLayout: SmartRefreshLayout by lazy { refreshLayout }
18 | override fun initData() {
19 | //设置背景色
20 | context?.let { list_rv.setBackgroundColor(ContextCompat.getColor(it, setRecyclerViewBgColor)) }
21 | //重试
22 | list_sv.onRetry = { onRetry() }
23 | //刷新
24 | refreshLayout.setOnRefreshListener { onRefresh() }
25 | //设置下拉刷新是否可用
26 | refreshLayout.isEnabled = setRefreshEnable
27 | }
28 |
29 | abstract fun onRefresh()
30 | abstract fun onRetry()
31 | open val setRecyclerViewBgColor = R.color.white
32 | open val setRefreshEnable = true
33 | }
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/utils/RxTimerUtil.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.utils
2 |
3 | import io.reactivex.Observable
4 | import io.reactivex.android.schedulers.AndroidSchedulers
5 | import io.reactivex.disposables.Disposable
6 | import java.util.concurrent.TimeUnit
7 |
8 | object RxTimerUtil {
9 | private var mDisPosable: Disposable? = null
10 | /**
11 | * milliseconds毫秒后执行next操作
12 | */
13 | fun postDelay(milliseconds: Long, task: ((Long) -> Unit)? = null) {
14 | mDisPosable = Observable.timer(milliseconds, TimeUnit.MILLISECONDS)
15 | .observeOn(AndroidSchedulers.mainThread())
16 | .subscribe { number ->
17 | task?.invoke(number)
18 | //取消订阅
19 | cancel()
20 | }
21 | }
22 |
23 | /**
24 | * 每隔milliseconds毫秒后执行next操作
25 | */
26 | fun interval(milliseconds: Long, task: ((Long) -> Unit)? = null) {
27 | mDisPosable = Observable.interval(milliseconds, TimeUnit.MILLISECONDS)
28 | .observeOn(AndroidSchedulers.mainThread())
29 | .subscribe { number ->
30 | task?.invoke(number)
31 | }
32 | }
33 |
34 | /**
35 | * 取消订阅
36 | */
37 | fun cancel() {
38 | mDisPosable?.let {
39 | if (!it.isDisposed) {
40 | it.dispose()
41 | }
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/baselib/src/main/res/layout/layout_empty_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
24 |
34 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/mvp/BaseMvpListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.mvp
2 |
3 | import android.support.v4.content.ContextCompat
4 | import android.support.v7.widget.RecyclerView
5 | import com.exmple.baselib.R
6 | import com.exmple.baselib.state.IStateView
7 | import com.scwang.smartrefresh.layout.SmartRefreshLayout
8 | import kotlinx.android.synthetic.main.layout_list.*
9 |
10 | /**
11 | * @FileName: {NAME}.java
12 | * @author: villa_mou
13 | * @date: {MONTH}-{HOUR}:01
14 | * @version V1.0 <描述当前版本功能>
15 | * @desc
16 | */
17 | abstract class BaseMvpListActivity : BaseMvpActivity(), IListView {
18 | override fun getContentView() = R.layout.layout_list
19 | override val mStateView: IStateView by lazy { list_sv }
20 | override val mRecyclerView: RecyclerView by lazy { list_rv }
21 | override val mRefreshLayout: SmartRefreshLayout by lazy { refreshLayout }
22 |
23 | override fun initView() {
24 | //设置列表背景色
25 | list_rv.setBackgroundColor(ContextCompat.getColor(this, setRecyclerViewBgColor))
26 | //重试
27 | list_sv.onRetry = { onRetry() }
28 | //刷新
29 | refreshLayout.setOnRefreshListener { onRefresh() }
30 | //设置下拉刷新是否可用
31 | refreshLayout.isEnabled = setRefreshEnable
32 | }
33 |
34 | abstract fun onRefresh()
35 | abstract fun onRetry()
36 | open val setRecyclerViewBgColor = R.color.white
37 | open val setRefreshEnable = true
38 | }
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/utils/CleanLeakUtils.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.utils
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import android.view.inputmethod.InputMethodManager
6 | import java.lang.reflect.Field
7 |
8 | object CleanLeakUtils {
9 |
10 | fun fixInputMethodManagerLeak(destContext: Context?) {
11 | if (destContext == null) {
12 | return
13 | }
14 | val inputMethodManager = destContext.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
15 |
16 | val viewArray = arrayOf("mCurRootView", "mServedView", "mNextServedView")
17 | var filed: Field
18 | var filedObject: Any?
19 |
20 | for (view in viewArray) {
21 | try {
22 | filed = inputMethodManager.javaClass.getDeclaredField(view)
23 | if (!filed.isAccessible) {
24 | filed.isAccessible = true
25 | }
26 | filedObject = filed.get(inputMethodManager)
27 | if (filedObject != null && filedObject is View) {
28 | val fileView = filedObject as View?
29 | if (fileView!!.context === destContext) { // 被InputMethodManager持有引用的context是想要目标销毁的
30 | filed.set(inputMethodManager, null) // 置空,破坏掉path to gc节点
31 | } else {
32 | break// 不是想要目标销毁的,即为又进了另一层界面了,不要处理,避免影响原逻辑,也就不用继续for循环了
33 | }
34 | }
35 | } catch (t: Throwable) {
36 | t.printStackTrace()
37 | }
38 |
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/mvp/BaseMvpTitleListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.sihaiwanlian.baselib.mvp
2 |
3 | import android.support.v4.content.ContextCompat
4 | import android.support.v7.widget.RecyclerView
5 | import com.exmple.baselib.R
6 | import com.exmple.baselib.mvp.IListView
7 | import com.exmple.baselib.mvp.ITopPresenter
8 | import com.exmple.baselib.mvp.ITopView
9 | import com.exmple.baselib.state.IStateView
10 | import com.scwang.smartrefresh.layout.SmartRefreshLayout
11 | import kotlinx.android.synthetic.main.layout_list.*
12 |
13 | /**
14 | * @FileName: {NAME}.java
15 | * @author: villa_mou
16 | * @date: {MONTH}-{HOUR}:03
17 | * @version V1.0 <描述当前版本功能>
18 | * @desc
19 | */
20 | abstract class BaseMvpTitleListActivity : BaseMvpTitleActivity(), IListView {
21 | override fun childView()= R.layout.layout_list
22 | override val mStateView: IStateView by lazy { list_sv }
23 | override val mRecyclerView: RecyclerView by lazy { list_rv }
24 | override val mRefreshLayout: SmartRefreshLayout by lazy { refreshLayout }
25 | override fun initView() {
26 | super.initView()
27 | //设置背景色
28 | list_rv.setBackgroundColor(ContextCompat.getColor(this, setRecyclerViewBgColor))
29 | //重试
30 | list_sv.onRetry = { onRetry() }
31 | //刷新
32 | refreshLayout.setOnRefreshListener { onRefresh() }
33 | //设置下拉刷新是否可用
34 | refreshLayout.isEnabled = setRefreshEnable
35 | }
36 | abstract fun onRefresh()
37 | abstract fun onRetry()
38 | open val setRecyclerViewBgColor = R.color.white
39 | open val setRefreshEnable = true
40 | }
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/scheduler/BaseScheduler.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.scheduler
2 |
3 | import io.reactivex.*
4 | import org.reactivestreams.Publisher
5 |
6 | /**
7 | * Created by xuhao on 2017/11/17.
8 | * desc:RxJava2.x 5中基础相应类型
9 | */
10 |
11 |
12 |
13 | abstract class BaseScheduler protected constructor(private val subscribeOnScheduler: Scheduler,
14 | private val observeOnScheduler: Scheduler) : ObservableTransformer,
15 | SingleTransformer,
16 | MaybeTransformer,
17 | CompletableTransformer,
18 | FlowableTransformer {
19 |
20 | override fun apply(upstream: Completable): CompletableSource {
21 | return upstream.retry(2).subscribeOn(subscribeOnScheduler)
22 | .observeOn(observeOnScheduler)
23 | }
24 |
25 | override fun apply(upstream: Flowable): Publisher {
26 | return upstream.retry(2).subscribeOn(subscribeOnScheduler)
27 | .observeOn(observeOnScheduler)
28 | }
29 |
30 | override fun apply(upstream: Maybe): MaybeSource {
31 | return upstream.retry(2).subscribeOn(subscribeOnScheduler)
32 | .observeOn(observeOnScheduler)
33 | }
34 |
35 | override fun apply(upstream: Observable): ObservableSource {
36 | return upstream.retry(2).subscribeOn(subscribeOnScheduler)
37 | .observeOn(observeOnScheduler)
38 | }
39 |
40 | override fun apply(upstream: Single): SingleSource {
41 | return upstream.retry(2).subscribeOn(subscribeOnScheduler)
42 | .observeOn(observeOnScheduler)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # KotlinMvpExample
2 | 一个kotlin+mvp+retrofit+Rxjava的开发基础lib
3 | ## 项目介绍
4 |
5 | * 最近对项目进行了优化,之前写的代码有点小low,网络方面也进行了优化,并且上传到了jcenter库,可以直接添加依赖进行使用了,具体的介绍请移步博客查看,当然优化的内容博客里面并没有介绍
6 |
7 | * 博客地址[https://blog.csdn.net/villa_mou/article/details/81185903](https://blog.csdn.net/villa_mou/article/details/81185903)
8 |
9 | **具体使用:**
10 |
11 | implementation 'com.mou:mvp:1.0.0'
12 |
13 | ps:如果直接添加依赖下载不下来,可以先添加仓库 : ` maven { url 'https://dl.bintray.com/mouxuefei/maven' }`
14 |
15 |
16 | ## 优化内容
17 |
18 | > 1,网络请求方面进行了优化处理
19 |
20 | 具体使用如下:
21 |
22 | mModel?.getMainData()
23 | ?.bindDialogAndDisposable(mView, mModel)
24 | ?.onResult {
25 |
26 | }
27 |
28 | 或者
29 |
30 | mModel?.getMainData()
31 | ?.bindDialog(mView)
32 | ?.bindDisposable(mModel)
33 | ?.onResult {
34 |
35 | }
36 | 或者
37 |
38 | mModel?.getMainData()?.mSubscribe(mView,mModel){
39 |
40 | }
41 |
42 | 都是可行的,只是进行了拆分
43 |
44 | 其中`bindDisposable`是肯定需要的,解决内存泄漏问题,当然有的人喜欢有autodispose也是很方便的,bindDialog代表有弹窗,不写表示没有弹窗,具体看自己的情况
45 |
46 | > 2,网络配置方面进行了优化
47 | 具体如下:
48 |
49 | object MainRetrofit : RetrofitFactory() {
50 | override fun getBaseUrl()= "http://www.baidu.com"
51 |
52 | override fun getHeader(builder: Request.Builder): Request.Builder {
53 | builder.addHeader("token","XXXXXXXXXXXXXXXXXXXXX")
54 | return builder
55 | }
56 |
57 | override fun getApiService(): Class {
58 | return MainApi::class.java
59 | }
60 |
61 | }
62 |
63 |
64 | 可以配置header和baseurl
65 |
66 | > 3,另外写了一个移除model的库,项目地址:[https://github.com/mouxuefei/KotlinVpExample](https://github.com/mouxuefei/KotlinVpExample)
--------------------------------------------------------------------------------
/baselib/src/main/res/values/styles_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
26 |
27 |
31 |
32 |
36 |
37 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/base/LibApplication.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.base
2 |
3 | import android.app.Application
4 | import android.content.Context
5 | import android.os.Handler
6 | import com.exmple.baselib.utils.LogCatStrategy
7 | import com.orhanobut.logger.AndroidLogAdapter
8 | import com.orhanobut.logger.Logger
9 | import com.orhanobut.logger.PrettyFormatStrategy
10 | import kotlin.properties.Delegates
11 |
12 | /**
13 | * FileName: com.sihaiwanlian.baselib.base.LibApplication.java
14 | * Author: mouxuefei
15 | * date: 2018/3/5
16 | * version: V1.0
17 | * desc:
18 | */
19 | open class LibApplication : Application() {
20 | companion object {
21 | var mContext: Context by Delegates.notNull()
22 | private set
23 | var appHandler: Handler?=null
24 | }
25 |
26 | override fun onCreate() {
27 | super.onCreate()
28 | mContext = applicationContext
29 | //初始化生命周期
30 | appHandler = Handler()
31 | initLogger()
32 | }
33 |
34 | private fun initLogger() {
35 | val formatStrategy = PrettyFormatStrategy.newBuilder()
36 | .logStrategy(LogCatStrategy())
37 | .showThreadInfo(false) // (Optional) Whether to show thread info or not. Default true
38 | .methodCount(0) // (Optional) How many method line to show. Default 2
39 | .methodOffset(7) // (Optional) Hides internal method calls up to offset. Default 5
40 | .tag("villa") // (Optional) Global tag for every log. Default PRETTY_LOGGER
41 | .build()
42 | Logger.addLogAdapter(object : AndroidLogAdapter(formatStrategy) {
43 | override fun isLoggable(priority: Int, tag: String?): Boolean {
44 | return true
45 | }
46 | })
47 | }
48 | }
--------------------------------------------------------------------------------
/baselib/src/main/res/layout/activtiy_base_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
20 |
21 |
29 |
30 |
31 |
32 |
33 |
39 |
40 |
45 |
--------------------------------------------------------------------------------
/baselib/src/main/res/layout/layout_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
21 |
22 |
25 |
26 |
31 |
32 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/baselib/src/main/res/values/styles_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
16 |
17 |
23 |
29 |
35 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/baselib/src/main/res/layout/layout_error_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
24 |
25 |
33 |
34 |
42 |
43 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
24 |
25 |
40 |
41 |
54 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/http/retrofit/RetrofitFactory.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.http.retrofit
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.GsonBuilder
5 | import com.orhanobut.logger.Logger
6 | import okhttp3.OkHttpClient
7 | import okhttp3.Request
8 | import okhttp3.logging.HttpLoggingInterceptor
9 | import retrofit2.Retrofit
10 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
11 | import retrofit2.converter.gson.GsonConverterFactory
12 | import java.util.concurrent.TimeUnit
13 |
14 | /**
15 | * FileName: com.mou.demo.http.retrofit.RetrofitFactory.java
16 | * Author: mouxuefei
17 | * date: 2017/12/22
18 | * version: V1.0
19 | * desc:
20 | */
21 | abstract class RetrofitFactory {
22 | private val time_out: Long = 15//超时时间
23 | var apiService: T
24 |
25 | init {
26 | val httpClient = OkHttpClient.Builder()
27 | .addInterceptor { chain ->
28 | var builder = chain.request().newBuilder()
29 | builder.addHeader("Cache-Control", "max-age=0")
30 | builder.addHeader("Upgrade-Insecure-Requests", "1")
31 | builder= getHeader(builder)
32 | val build = builder.build()
33 | chain.proceed(build)
34 | }
35 | .addInterceptor(HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { message ->
36 | Logger.i("${message}")
37 | }).setLevel(HttpLoggingInterceptor.Level.BODY))//设置打印得日志内容
38 | .connectTimeout(time_out, TimeUnit.SECONDS)
39 | .readTimeout(time_out, TimeUnit.SECONDS)
40 | .build()
41 |
42 | apiService = Retrofit.Builder()
43 | .baseUrl(getBaseUrl())
44 | .addConverterFactory(GsonConverterFactory.create(buildGson())) // 添加Gson转换器
45 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 添加Retrofit到RxJava的转换器
46 | .client(httpClient)
47 | .build()
48 | .create(getApiService())
49 | }
50 |
51 | abstract fun getHeader(builder:Request.Builder): Request.Builder
52 |
53 | abstract fun getApiService(): Class
54 | private fun buildGson(): Gson {
55 | return GsonBuilder()
56 | .setDateFormat("yyyy-MM-dd HH:mm:ss")
57 | .create()
58 | }
59 |
60 | fun getService(): T {
61 | return apiService
62 | }
63 | abstract fun getBaseUrl(): String
64 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/utils/DisplayManager.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.utils
2 |
3 | import android.content.Context
4 | import android.util.DisplayMetrics
5 |
6 | /**
7 | * Created by xuhao on 2017/11/27.
8 | * desc:
9 | */
10 |
11 | object DisplayManager {
12 | init {
13 |
14 | }
15 |
16 | private var displayMetrics: DisplayMetrics? = null
17 |
18 | private var screenWidth: Int? = null
19 |
20 | private var screenHeight: Int? = null
21 |
22 | private var screenDpi: Int? = null
23 |
24 | fun init(context: Context) {
25 | displayMetrics = context.resources.displayMetrics
26 | screenWidth = displayMetrics?.widthPixels
27 | screenHeight = displayMetrics?.heightPixels
28 | screenDpi = displayMetrics?.densityDpi
29 | }
30 |
31 |
32 | //UI图的大小
33 | private val STANDARD_WIDTH = 1080
34 | private val STANDARD_HEIGHT = 1920
35 |
36 |
37 | fun getScreenWidth(): Int? {
38 | return screenWidth
39 | }
40 |
41 | fun getScreenHeight(): Int? {
42 | return screenHeight
43 | }
44 |
45 |
46 | /**
47 | * 传入UI图中问题的高度,单位像素
48 | * @param size
49 | * @return
50 | */
51 | fun getPaintSize(size: Int): Int? {
52 | return getRealHeight(size)
53 | }
54 |
55 | /**
56 | * 输入UI图的尺寸,输出实际的px
57 | *
58 | * @param px ui图中的大小
59 | * @return
60 | */
61 | fun getRealWidth(px: Int): Int? {
62 | //ui图的宽度
63 | return getRealWidth(px, STANDARD_WIDTH.toFloat())
64 | }
65 |
66 | /**
67 | * 输入UI图的尺寸,输出实际的px,第二个参数是父布局
68 | *
69 | * @param px ui图中的大小
70 | * @param parentWidth 父view在ui图中的高度
71 | * @return
72 | */
73 | fun getRealWidth(px: Int, parentWidth: Float): Int? {
74 | return (px / parentWidth * getScreenWidth()!!).toInt()
75 | }
76 |
77 | /**
78 | * 输入UI图的尺寸,输出实际的px
79 | *
80 | * @param px ui图中的大小
81 | * @return
82 | */
83 | fun getRealHeight(px: Int): Int? {
84 | //ui图的宽度
85 | return getRealHeight(px, STANDARD_HEIGHT.toFloat())
86 | }
87 |
88 | /**
89 | * 输入UI图的尺寸,输出实际的px,第二个参数是父布局
90 | *
91 | * @param px ui图中的大小
92 | * @param parentHeight 父view在ui图中的高度
93 | * @return
94 | */
95 | fun getRealHeight(px: Int, parentHeight: Float): Int? {
96 | return (px / parentHeight * getScreenHeight()!!).toInt()
97 | }
98 |
99 | /**
100 | * dip转px
101 | * @param dipValue
102 | * @return int
103 | */
104 | fun dip2px(dipValue: Float): Int? {
105 | val scale = displayMetrics?.density
106 | return (dipValue * scale!! + 0.5f).toInt()
107 | }
108 | }
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/base/BaseFragment.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.base
2 |
3 | import android.content.Context
4 | import android.os.Bundle
5 | import android.support.annotation.LayoutRes
6 | import android.support.v4.app.Fragment
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import com.exmple.baselib.R
11 | import com.exmple.baselib.utils.ProgressDialogUtils
12 | import com.exmple.baselib.utils.register
13 | import com.exmple.baselib.utils.unregister
14 |
15 | /**
16 | * @FileName: com.mou.demo.basekotlin.BaseFragment.java
17 | * @author: mouxuefei
18 | * @date: 2017-12-19 15:48
19 | * @version V1.0 <描述当前版本功能>
20 | * @desc
21 | */
22 | abstract class BaseFragment : Fragment() {
23 | private var isViewPrepare = false
24 | private var hasLoadData = false
25 | open var mContext: Context? = null
26 | private var progressDialog: ProgressDialogUtils? = null
27 | protected abstract fun lazyLoad()
28 | open val useEventBus: Boolean = false
29 | @LayoutRes
30 | protected abstract fun getContentView(): Int
31 |
32 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
33 | val layout = getContentView()
34 | val rootView = inflater.inflate(layout, container, false)
35 | this.mContext = context
36 | if (useEventBus) {
37 | register(this)
38 | }
39 | return rootView
40 | }
41 |
42 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
43 | super.onViewCreated(view, savedInstanceState)
44 | isViewPrepare = true
45 | initView(view)
46 | progressDialog = ProgressDialogUtils(context, R.style.dialog_transparent_style)
47 | savedStanceState(savedInstanceState)
48 | initData()
49 | lazyLoadDataIfPrepared()
50 | }
51 |
52 | protected abstract fun initView(view: View)
53 | open fun savedStanceState(savedInstanceState: Bundle?) {}
54 | open fun initData() {}
55 | override fun setUserVisibleHint(isVisibleToUser: Boolean) {
56 | super.setUserVisibleHint(isVisibleToUser)
57 | if (isVisibleToUser) {
58 | lazyLoadDataIfPrepared()
59 | }
60 | }
61 |
62 | private fun lazyLoadDataIfPrepared() {
63 | if (userVisibleHint && isViewPrepare && !hasLoadData) {
64 | lazyLoad()
65 | hasLoadData = true
66 | }
67 | }
68 |
69 | fun showProgressDialog(text: String) {
70 | progressDialog?.showProgressDialogWithText(text)
71 | }
72 |
73 | fun dismissProgressDialog() {
74 | progressDialog?.dismissProgressDialog()
75 | }
76 |
77 | override fun onDestroy() {
78 | super.onDestroy()
79 | if (useEventBus) {
80 | unregister(this)
81 | }
82 | }
83 | }
84 |
85 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/utils/ActivityUtils.kt:
--------------------------------------------------------------------------------
1 |
2 | package com.exmple.baselib.utils
3 |
4 | import android.app.Activity
5 | import android.util.Log
6 | import java.util.*
7 |
8 | /**
9 | * @FileName: com.exmple.baselib.utils.ActivityUtils.java
10 | * @author: mouxuefei
11 | * @date: 2017-12-21 16:08
12 | * @version V1.0 <描述当前版本功能>
13 | * @desc
14 | */
15 | object ActivityUtils {
16 | private val TAG = "ActivityUtils"
17 | private val activityStack: Stack = Stack()
18 |
19 | /**
20 | * <获取当前栈顶Activity>
21 | */
22 | fun currentActivity(): Activity? {
23 | return if (activityStack.size == 0) {
24 | null
25 | } else activityStack.lastElement()
26 | }
27 |
28 |
29 | /**
30 | * <获取当前栈顶Activity>
31 | * <功能详细描述>
32 | * @see [类、类.方法、类.成员]
33 | */
34 | fun popCurrentActivity() {
35 | popActivity(currentActivity())
36 | }
37 |
38 |
39 | /**
40 | * <将Activity入栈>
41 | * <功能详细描述>
42 | *
43 | * @param activity
44 | * @see [类、类.方法、类.成员]
45 | 功能详细描述>将Activity入栈> */
46 | fun pushActivity(activity: Activity) {
47 | activityStack.add(activity)
48 | }
49 |
50 | /**
51 | * <退出栈顶Activity>
52 | * <功能详细描述>
53 | * @see [类、类.方法、类.成员]
54 | */
55 | fun popActivity(activity: Activity?) {
56 | if (activity != null) {
57 | activity.finish()
58 | Log.e(TAG, "remove current activity:" + activity.javaClass.simpleName)
59 | activityStack.remove(activity)
60 | }
61 | }
62 |
63 |
64 | /**
65 | * 将制定activity从栈中移除
66 | */
67 | fun removeActivity(activity: Activity?) {
68 | if (activity != null) {
69 | activityStack.remove(activity)
70 | }
71 | }
72 |
73 |
74 | /**
75 | * <退出栈中所有Activity>退出栈中所有Activity>,当前的activity除外>
76 | * <功能详细描述>
77 | *
78 | * @param cls
79 | * @see [类、类.方法、类.成员]
80 | 功能详细描述> */
81 | fun popAllActivityExceptMain(cls: Class<*>) {
82 | while (true) {
83 | val activity = currentActivity() ?: break
84 | if (activity.javaClass == cls) {
85 | break
86 | }
87 | popActivity(activity)
88 | }
89 | }
90 |
91 |
92 | fun popAllActivity() {
93 | while (true) {
94 | val activity = currentActivity() ?: break
95 | popActivity(activity)
96 | }
97 | }
98 |
99 | /**
100 | * 如果栈顶是这个 class 就finish掉
101 | */
102 | fun popActivity(activityClass: Class) {
103 | val activity = currentActivity()
104 | if (activity != null && activity.javaClass.name == activityClass.name) {
105 | popActivity(activity)
106 | }
107 | }
108 |
109 | fun getSize(): Int {
110 | return activityStack.size
111 | }
112 | }
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/mvp/MVPInterface.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.mvp
2 |
3 | /**
4 | * Description :
5 | * @date 2018/7/5 11:45
6 | */
7 | import android.app.Activity
8 | import android.arch.lifecycle.Lifecycle
9 | import android.arch.lifecycle.LifecycleObserver
10 | import android.arch.lifecycle.LifecycleOwner
11 | import android.arch.lifecycle.OnLifecycleEvent
12 | import android.content.Context
13 | import android.support.annotation.StringRes
14 | import android.support.v7.widget.RecyclerView
15 | import com.exmple.baselib.state.IStateView
16 | import com.orhanobut.logger.Logger
17 | import com.scwang.smartrefresh.layout.SmartRefreshLayout
18 | import io.reactivex.disposables.CompositeDisposable
19 | import io.reactivex.disposables.Disposable
20 | import org.jetbrains.annotations.NotNull
21 |
22 | interface ITopView : LifecycleOwner {
23 | fun getCtx(): Context?
24 | fun inited()
25 | fun finish(resultCode: Int = Activity.RESULT_CANCELED)
26 | fun showLoading(@NotNull msg: String)
27 | fun showLoading(@StringRes srtResId: Int)
28 | fun dismissLoading()
29 | fun showToast(@StringRes srtResId: Int)
30 | fun showToast(@NotNull message: String)
31 | }
32 |
33 | interface ITopPresenter : LifecycleObserver {
34 | fun attachView(view: ITopView)
35 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
36 | fun detachView()
37 | }
38 |
39 |
40 | interface ITopModel {
41 | fun onDetach()
42 | }
43 |
44 |
45 | interface IView : ITopView {
46 | var mPresenter: P
47 | override fun inited() {
48 | mPresenter.attachView(this)
49 | }
50 | }
51 |
52 | interface IPresenter : ITopPresenter {
53 | var mView: V?
54 | var mModel: M?
55 | fun getContext() = mView?.getCtx()
56 |
57 | @Suppress("UNCHECKED_CAST")
58 | override fun attachView(view: ITopView) {
59 | mView = view as V
60 | mView?.lifecycle?.addObserver(this)
61 | }
62 |
63 | override fun detachView() {
64 | mModel?.onDetach()
65 | mModel = null
66 | mView = null
67 | }
68 |
69 | //判断是否初始化View
70 | private val isViewAttached: Boolean
71 | get() = mView != null
72 |
73 | fun checkViewAttached() {
74 | if (!isViewAttached) throw MvpViewNotAttachedException()
75 | }
76 | private class MvpViewNotAttachedException internal constructor() : RuntimeException("Please call IPresenter.attachView(IBaseView) before" + " requesting data to the IPresenter")
77 |
78 | }
79 |
80 | interface IModel : ITopModel {
81 | val mDisposablePool: CompositeDisposable
82 |
83 | fun addDisposable(disposable: Disposable) {
84 | mDisposablePool.add(disposable)
85 | }
86 |
87 | override fun onDetach() {
88 | Logger.e("走了吗")
89 | if (!mDisposablePool.isDisposed) {
90 | mDisposablePool.clear()
91 | }
92 | }
93 | }
94 |
95 | interface IListView :IView
{
96 | val mRecyclerView: RecyclerView?
97 | val mStateView: IStateView?
98 | val mRefreshLayout:SmartRefreshLayout
99 | fun loadMoreFail(isRefresh: Boolean)
100 | }
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/mvp/BaseMvpTitleActivity.kt:
--------------------------------------------------------------------------------
1 | package com.sihaiwanlian.baselib.mvp
2 |
3 | import android.support.annotation.ColorRes
4 | import android.support.annotation.DrawableRes
5 | import android.support.annotation.LayoutRes
6 | import android.support.annotation.StringRes
7 | import android.support.v4.content.ContextCompat
8 | import android.support.v7.widget.Toolbar
9 | import android.view.Menu
10 | import android.view.MenuItem
11 | import android.widget.FrameLayout
12 | import android.widget.TextView
13 | import com.exmple.baselib.R
14 | import com.exmple.baselib.mvp.BaseMvpActivity
15 | import com.exmple.baselib.mvp.ITopPresenter
16 | import com.exmple.baselib.mvp.ITopView
17 |
18 |
19 | /**
20 | * 所有标题的activity的父类
21 | * 在这里主要统一处理标题
22 | * Created by mou on 2016/7/13.
23 | */
24 | abstract class BaseMvpTitleActivity : BaseMvpActivity() {
25 | private var rightMenuTexts: String? = null
26 | private var rightMenuIcons: Int? = null
27 | private var titleTv: TextView? = null
28 | @LayoutRes
29 | protected abstract fun childView(): Int
30 |
31 | override fun getContentView() = R.layout.activtiy_base_title
32 | override fun initView() {
33 | val container = this.findViewById(R.id.base_container)
34 | container.addView(layoutInflater.inflate(childView(), null))
35 | val toolbar = this.findViewById(R.id.base_toolbar)
36 | titleTv = this.findViewById(R.id.base_title_tv)
37 | toolbar.title = ""
38 | setSupportActionBar(toolbar)
39 | if (hasBackIcon()) {
40 | toolbar.setNavigationIcon(R.drawable.return_icon)
41 | toolbar.setNavigationOnClickListener { finish() }
42 | }
43 | }
44 |
45 | open fun hasBackIcon() = true
46 | override fun onCreateOptionsMenu(menu: Menu): Boolean {
47 | rightMenuIcons?.let {
48 | val item = menu.add(0, 0, 0, "")
49 | item.icon = ContextCompat.getDrawable(this, it)
50 | item.setShowAsAction(Menu.FLAG_ALWAYS_PERFORM_CLOSE)
51 | }
52 | rightMenuTexts?.let {
53 | val item = menu.add(0, 0, 0, "")
54 | item.title = it
55 | item.setShowAsAction(Menu.FLAG_ALWAYS_PERFORM_CLOSE)
56 | }
57 | return true
58 | }
59 |
60 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
61 | onRightMenuClick(item.itemId)
62 | return false
63 | }
64 |
65 | /**
66 | * 设置toolbar右边的文字
67 | */
68 | fun setRightMenuTexts(rightMenuText: String) {
69 | this.rightMenuTexts = rightMenuText
70 | }
71 |
72 | /**
73 | * 设置toolbar右边的icon
74 | */
75 | fun setRightMenuIcons(@DrawableRes rightIconResId: Int) {
76 | this.rightMenuIcons = rightIconResId
77 | }
78 |
79 | /**
80 | * 当toolbar右边的icon,被点击,数据0,1,2,3
81 | */
82 | open fun onRightMenuClick(itemId: Int) {
83 | }
84 |
85 | /**
86 | * 设置中间的title
87 | */
88 | protected fun setActivityTitle(@StringRes strResId: Int) {
89 | titleTv?.setText(strResId)
90 | }
91 |
92 | protected fun setActivityTitle(text: String) {
93 | titleTv?.text = text
94 | }
95 |
96 | /**
97 | * 设置中间title的颜色
98 | */
99 | fun setActivityTitleColor(@ColorRes colorId: Int) {
100 | titleTv?.setTextColor(resources.getColor(colorId))
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/exmple/baselib/state/StateView.kt:
--------------------------------------------------------------------------------
1 | package com.exmple.baselib.state
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.widget.Button
8 | import android.widget.FrameLayout
9 | import com.exmple.baselib.R
10 | import kotlinx.android.synthetic.main.layout_empty_view.view.*
11 | import kotlinx.android.synthetic.main.layout_error_view.view.*
12 | import kotlinx.android.synthetic.main.view_state_layout.view.*
13 |
14 | /**
15 | *
16 | * @author XQ Yang
17 | * @date 5/6/2018 12:23 PM
18 | */
19 | class StateView(context: Context, attrs: AttributeSet? = null) : FrameLayout(context, attrs), IStateView {
20 | override var emptyMsg: String = "這里什么也没有噢!ヾ(・ω・`。)"
21 | override var errorMsg: String = "怎么回事,出错了!(⊙_⊙)?"
22 | override var onStateChanged: ((Int) -> Unit)? = null
23 | override var curState: Int = STATE_EMPTY
24 | var bindViewId = 0//绑定的id
25 |
26 | override var onRetry: (() -> Unit)? = null
27 | //绑定的view
28 | override var bindView: View? = null
29 |
30 | private val emptyLayout: View by lazy {
31 | val view = vs_empty.inflate()
32 | tv_empty.text = emptyMsg
33 | view
34 | }
35 |
36 | private val errorLayout: View by lazy {
37 | val view = vs_error.inflate()
38 | tv_error.text = errorMsg
39 | view
40 | }
41 |
42 | private val loadingLayout: View by lazy {
43 | val view = vs_loading.inflate()
44 | view
45 | }
46 |
47 | override fun showSuccess() {
48 | hideAll()
49 | bindView?.visibility = View.VISIBLE
50 | curState = STATE_SUCCESS
51 | onStateChanged?.invoke(STATE_SUCCESS)
52 | }
53 |
54 | override fun showError(msg: String?) {
55 | hideAll()
56 | msg?.let {
57 | tv_error.text = it
58 | }
59 | errorLayout.visibility = View.VISIBLE
60 | errorLayout.findViewById