Modify: 添加扩展方法、添加自定义组件、添加工具类、基类调整
This commit is contained in:
@ -0,0 +1,30 @@
|
||||
package com.quyunshuo.base.handler
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/9/17
|
||||
* @Class: LifecycleHandler
|
||||
* @Remark: 自动在UI销毁时移除msg和任务的Handler,不会有内存泄露
|
||||
*/
|
||||
class LifecycleHandler(
|
||||
private val lifecycleOwner: LifecycleOwner,
|
||||
looper: Looper = Looper.getMainLooper()
|
||||
) : Handler(looper), LifecycleObserver {
|
||||
|
||||
init {
|
||||
lifecycleOwner.lifecycle.addObserver(this)
|
||||
}
|
||||
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
|
||||
fun onDestroy() {
|
||||
removeCallbacksAndMessages(null)
|
||||
lifecycleOwner.lifecycle.removeObserver(this)
|
||||
}
|
||||
}
|
||||
19
Lib_Base/src/main/java/com/quyunshuo/base/ktx/EditTextKtx.kt
Normal file
19
Lib_Base/src/main/java/com/quyunshuo/base/ktx/EditTextKtx.kt
Normal file
@ -0,0 +1,19 @@
|
||||
package com.quyunshuo.base.ktx
|
||||
|
||||
import android.text.InputFilter
|
||||
import android.widget.EditText
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/9/17
|
||||
* @Class: EditTextKtx
|
||||
* @Remark: EditText相关扩展方法
|
||||
*/
|
||||
|
||||
/**
|
||||
* 过滤掉空格和回车
|
||||
*/
|
||||
fun EditText.filterBlankAndCarriageReturn() {
|
||||
this.filters =
|
||||
arrayOf(InputFilter { source, _, _, _, _, _ -> if (source == " " || source == "\n") "" else null })
|
||||
}
|
||||
75
Lib_Base/src/main/java/com/quyunshuo/base/ktx/SizeUnitKtx.kt
Normal file
75
Lib_Base/src/main/java/com/quyunshuo/base/ktx/SizeUnitKtx.kt
Normal file
@ -0,0 +1,75 @@
|
||||
package com.quyunshuo.base.ktx
|
||||
|
||||
import android.content.Context
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/9/17
|
||||
* @Class: SizeUnitKtx
|
||||
* @Remark: 尺寸单位换算相关扩展属性
|
||||
*/
|
||||
|
||||
/**
|
||||
* dp 转 px
|
||||
*/
|
||||
fun Context.dp2px(dpValue: Float): Int {
|
||||
val scale = resources.displayMetrics.density
|
||||
return (dpValue * scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* px 转 dp
|
||||
*/
|
||||
fun Context.px2dp(pxValue: Float): Int {
|
||||
val scale = resources.displayMetrics.density
|
||||
return (pxValue / scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* sp 转 px
|
||||
*/
|
||||
fun Context.sp2px(spValue: Float): Int {
|
||||
val scale = resources.displayMetrics.scaledDensity
|
||||
return (spValue * scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* px 转 sp
|
||||
*/
|
||||
fun Context.px2sp(pxValue: Float): Int {
|
||||
val scale = resources.displayMetrics.scaledDensity
|
||||
return (pxValue / scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* dp 转 px
|
||||
*/
|
||||
fun Fragment.dp2px(dpValue: Float): Int {
|
||||
val scale = resources.displayMetrics.density
|
||||
return (dpValue * scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* px 转 dp
|
||||
*/
|
||||
fun Fragment.px2dp(pxValue: Float): Int {
|
||||
val scale = resources.displayMetrics.density
|
||||
return (pxValue / scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* sp 转 px
|
||||
*/
|
||||
fun Fragment.sp2px(spValue: Float): Int {
|
||||
val scale = resources.displayMetrics.scaledDensity
|
||||
return (spValue * scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* px 转 sp
|
||||
*/
|
||||
fun Fragment.px2sp(pxValue: Float): Int {
|
||||
val scale = resources.displayMetrics.scaledDensity
|
||||
return (pxValue / scale + 0.5f).toInt()
|
||||
}
|
||||
@ -4,12 +4,13 @@ import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/8/17
|
||||
* @Class: ContextKtx
|
||||
* @Remark: Context相关的扩展方法
|
||||
* @Time: 2020/9/17
|
||||
* @Class: ToastKtx
|
||||
* @Remark: Toast相关的扩展方法
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -49,33 +50,33 @@ fun Context.centerToast(@StringRes resId: Int, duration: Int = Toast.LENGTH_SHOR
|
||||
}
|
||||
|
||||
/**
|
||||
* dp 转 px
|
||||
* Toast
|
||||
* @param text CharSequence 类型文本
|
||||
*/
|
||||
fun Context.dp2px(dpValue: Float): Int {
|
||||
val scale = resources.displayMetrics.density
|
||||
return (dpValue * scale + 0.5f).toInt()
|
||||
fun Fragment.toast(text: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
|
||||
context?.toast(text, duration)
|
||||
}
|
||||
|
||||
/**
|
||||
* px 转 dp
|
||||
* Toast
|
||||
* @param resId String 类型资源id
|
||||
*/
|
||||
fun Context.px2dp(pxValue: Float): Int {
|
||||
val scale = resources.displayMetrics.density
|
||||
return (pxValue / scale + 0.5f).toInt()
|
||||
fun Fragment.toast(@StringRes resId: Int, duration: Int = Toast.LENGTH_SHORT) {
|
||||
context?.toast(resId, duration)
|
||||
}
|
||||
|
||||
/**
|
||||
* sp 转 px
|
||||
* 居中Toast
|
||||
* @param text CharSequence 类型文本
|
||||
*/
|
||||
fun Context.sp2px(spValue: Float): Int {
|
||||
val scale = resources.displayMetrics.scaledDensity
|
||||
return (spValue * scale + 0.5f).toInt()
|
||||
fun Fragment.centerToast(text: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
|
||||
context?.centerToast(text, duration)
|
||||
}
|
||||
|
||||
/**
|
||||
* px 转 sp
|
||||
* 居中Toast
|
||||
* @param resId String 类型资源id
|
||||
*/
|
||||
fun Context.px2sp(pxValue: Float): Int {
|
||||
val scale = resources.displayMetrics.scaledDensity
|
||||
return (pxValue / scale + 0.5f).toInt()
|
||||
fun Fragment.centerToast(@StringRes resId: Int, duration: Int = Toast.LENGTH_SHORT) {
|
||||
context?.centerToast(resId, duration)
|
||||
}
|
||||
@ -1,23 +1,242 @@
|
||||
package com.quyunshuo.base.ktx
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.IntEvaluator
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.quyunshuo.base.ktx.ViewClickDelay.SPACE_TIME
|
||||
import com.quyunshuo.base.ktx.ViewClickDelay.hash
|
||||
import com.quyunshuo.base.ktx.ViewClickDelay.lastClickTime
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/8/17
|
||||
* @Time: 2020/9/1
|
||||
* @Class: ViewKtx
|
||||
* @Remark: View相关的扩展方法
|
||||
*/
|
||||
|
||||
|
||||
/*************************************** View可见性相关 ********************************************/
|
||||
/**
|
||||
* 隐藏View
|
||||
*/
|
||||
fun View.gone() {
|
||||
visibility = View.GONE
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示View
|
||||
* @receiver View
|
||||
*/
|
||||
fun View.visible() {
|
||||
visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
* View不可见但存在原位置
|
||||
*/
|
||||
fun View.invisible() {
|
||||
visibility = View.INVISIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断View是不是[View.VISIBLE]状态
|
||||
*/
|
||||
val View.isVisible: Boolean
|
||||
get() {
|
||||
return visibility == View.VISIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断View是不是[View.INVISIBLE]状态
|
||||
*/
|
||||
val View.isInvisible: Boolean
|
||||
get() {
|
||||
return visibility == View.INVISIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断View是不是[View.GONE]状态
|
||||
*/
|
||||
val View.isGone: Boolean
|
||||
get() {
|
||||
return visibility == View.GONE
|
||||
}
|
||||
|
||||
/*************************************** View宽高相关 ********************************************/
|
||||
/**
|
||||
* 设置View的高度
|
||||
*/
|
||||
fun View.height(height: Int): View {
|
||||
val params = layoutParams ?: ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
params.height = height
|
||||
layoutParams = params
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置View的宽度
|
||||
*/
|
||||
fun View.width(width: Int): View {
|
||||
val params = layoutParams ?: ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
params.width = width
|
||||
layoutParams = params
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置View的宽度和高度
|
||||
* @param width 要设置的宽度
|
||||
* @param height 要设置的高度
|
||||
*/
|
||||
fun View.widthAndHeight(width: Int, height: Int): View {
|
||||
val params = layoutParams ?: ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
params.width = width
|
||||
params.height = height
|
||||
layoutParams = params
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置宽度,带有过渡动画
|
||||
* @param targetValue 目标宽度
|
||||
* @param duration 时长
|
||||
* @param action 可选行为
|
||||
* @return 动画
|
||||
*/
|
||||
fun View.animateWidth(
|
||||
targetValue: Int, duration: Long = 400, listener: Animator.AnimatorListener? = null,
|
||||
action: ((Float) -> Unit)? = null
|
||||
): ValueAnimator? {
|
||||
var animator: ValueAnimator? = null
|
||||
post {
|
||||
animator = ValueAnimator.ofInt(width, targetValue).apply {
|
||||
addUpdateListener {
|
||||
width(it.animatedValue as Int)
|
||||
action?.invoke((it.animatedFraction))
|
||||
}
|
||||
if (listener != null) addListener(listener)
|
||||
setDuration(duration)
|
||||
start()
|
||||
}
|
||||
}
|
||||
return animator
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置高度,带有过渡动画
|
||||
* @param targetValue 目标高度
|
||||
* @param duration 时长
|
||||
* @param action 可选行为
|
||||
* @return 动画
|
||||
*/
|
||||
fun View.animateHeight(
|
||||
targetValue: Int,
|
||||
duration: Long = 400,
|
||||
listener: Animator.AnimatorListener? = null,
|
||||
action: ((Float) -> Unit)? = null
|
||||
): ValueAnimator? {
|
||||
var animator: ValueAnimator? = null
|
||||
post {
|
||||
animator = ValueAnimator.ofInt(height, targetValue).apply {
|
||||
addUpdateListener {
|
||||
height(it.animatedValue as Int)
|
||||
action?.invoke((it.animatedFraction))
|
||||
}
|
||||
if (listener != null) addListener(listener)
|
||||
setDuration(duration)
|
||||
start()
|
||||
}
|
||||
}
|
||||
return animator
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置宽度和高度,带有过渡动画
|
||||
* @param targetWidth 目标宽度
|
||||
* @param targetHeight 目标高度
|
||||
* @param duration 时长
|
||||
* @param action 可选行为
|
||||
* @return 动画
|
||||
*/
|
||||
fun View.animateWidthAndHeight(
|
||||
targetWidth: Int,
|
||||
targetHeight: Int,
|
||||
duration: Long = 400,
|
||||
listener: Animator.AnimatorListener? = null,
|
||||
action: ((Float) -> Unit)? = null
|
||||
): ValueAnimator? {
|
||||
var animator: ValueAnimator? = null
|
||||
post {
|
||||
val startHeight = height
|
||||
val evaluator = IntEvaluator()
|
||||
animator = ValueAnimator.ofInt(width, targetWidth).apply {
|
||||
addUpdateListener {
|
||||
widthAndHeight(
|
||||
it.animatedValue as Int,
|
||||
evaluator.evaluate(it.animatedFraction, startHeight, targetHeight)
|
||||
)
|
||||
action?.invoke((it.animatedFraction))
|
||||
}
|
||||
if (listener != null) addListener(listener)
|
||||
setDuration(duration)
|
||||
start()
|
||||
}
|
||||
}
|
||||
return animator
|
||||
}
|
||||
|
||||
/*************************************** View其他 ********************************************/
|
||||
/**
|
||||
* 获取View id,如果没有id:SDK>17, 使用[View.generateViewId];否则使用[View.hashCode]
|
||||
*/
|
||||
@SuppressLint("ObsoleteSdkInt")
|
||||
fun View.getViewId(): Int {
|
||||
var id = id
|
||||
if (id == View.NO_ID) {
|
||||
id = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
View.generateViewId()
|
||||
} else {
|
||||
this.hashCode()
|
||||
}
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
object ViewClickDelay {
|
||||
var hash: Int = 0
|
||||
var lastClickTime: Long = 0
|
||||
var SPACE_TIME: Long = 2000 // 间隔时间
|
||||
}
|
||||
|
||||
/**
|
||||
* 防快速点击
|
||||
* @receiver View
|
||||
* @param clickAction 要响应的操作
|
||||
*/
|
||||
infix fun View.clickDelay(clickAction: () -> Unit) {
|
||||
this.setOnClickListener {
|
||||
if (this.hashCode() != hash) {
|
||||
hash = this.hashCode()
|
||||
lastClickTime = System.currentTimeMillis()
|
||||
clickAction()
|
||||
} else {
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (currentTime - lastClickTime > SPACE_TIME) {
|
||||
lastClickTime = System.currentTimeMillis()
|
||||
clickAction()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.quyunshuo.base.livedata
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/9/17
|
||||
* @Class: OnceLiveData
|
||||
* @Remark: 只执行一次的LiveData
|
||||
*/
|
||||
class OnceLiveData<T> : MutableLiveData<T>() {
|
||||
|
||||
private var isRead: AtomicBoolean = AtomicBoolean(false)
|
||||
|
||||
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
|
||||
super.observe(owner, Observer {
|
||||
if (isRead.compareAndSet(false, true)) {
|
||||
observer.onChanged(it)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun postValue(value: T) {
|
||||
isRead.set(false)
|
||||
super.postValue(value)
|
||||
}
|
||||
|
||||
override fun setValue(value: T) {
|
||||
isRead.set(false)
|
||||
super.setValue(value)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.quyunshuo.base.mvvm.v
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.quyunshuo.base.utils.EventBusRegister
|
||||
import com.quyunshuo.base.utils.EventBusUtils
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/9/10
|
||||
* @Class: BaseFrameNotMVVMActivity
|
||||
* @Remark: 不使用 MVVM 的 Activity 基类
|
||||
*/
|
||||
abstract class BaseFrameNotMVVMActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
|
||||
protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) { initViewBinding() }
|
||||
|
||||
protected abstract fun initViewBinding(): VB
|
||||
protected abstract fun initView()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(mBinding.root)
|
||||
// ARouter 依赖注入
|
||||
ARouter.getInstance().inject(this)
|
||||
// 注册EventBus
|
||||
if (javaClass.isAnnotationPresent(EventBusRegister::class.java)) EventBusUtils.register(this)
|
||||
initView()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (javaClass.isAnnotationPresent(EventBusRegister::class.java)) EventBusUtils.unRegister(
|
||||
this
|
||||
)
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.quyunshuo.base.mvvm.v
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.quyunshuo.base.utils.EventBusRegister
|
||||
import com.quyunshuo.base.utils.EventBusUtils
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/9/10
|
||||
* @Class: BaseFrameNotMVVMFragment
|
||||
* @Remark: 不使用 MVVM 的 Fragment 基类
|
||||
*/
|
||||
abstract class BaseFrameNotMVVMFragment<VB : ViewBinding> : Fragment() {
|
||||
|
||||
protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) { initViewBinding() }
|
||||
|
||||
protected abstract fun initViewBinding(): VB
|
||||
protected abstract fun initView()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return mBinding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
// ARouter 依赖注入
|
||||
ARouter.getInstance().inject(this)
|
||||
// 注册EventBus
|
||||
if (javaClass.isAnnotationPresent(EventBusRegister::class.java)) EventBusUtils.register(this)
|
||||
initView()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (javaClass.isAnnotationPresent(EventBusRegister::class.java)) EventBusUtils.unRegister(
|
||||
this
|
||||
)
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,9 @@ abstract class BaseViewModel<R : BaseRepository> : ViewModel() {
|
||||
// Loading 状态
|
||||
val isLoading = MutableLiveData(false)
|
||||
|
||||
// 请求异常
|
||||
val requestError = MutableLiveData<Throwable?>()
|
||||
|
||||
protected val mRepository: R by lazy { initRepository() }
|
||||
|
||||
protected abstract fun initRepository(): R
|
||||
|
||||
@ -0,0 +1,114 @@
|
||||
package com.quyunshuo.base.utils
|
||||
|
||||
import android.app.Activity
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/9/11
|
||||
* @Class: ActivityStackManager
|
||||
* @Remark: Activity 栈管理类
|
||||
*/
|
||||
object ActivityStackManager {
|
||||
|
||||
// 管理栈
|
||||
val activityStack by lazy { Stack<Activity>() }
|
||||
|
||||
/**
|
||||
* 添加 Activity 到管理栈
|
||||
* @param activity Activity
|
||||
*/
|
||||
fun addActivityToStack(activity: Activity) {
|
||||
activityStack.push(activity)
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出栈内指定Activity 不finish
|
||||
* @param activity Activity
|
||||
*/
|
||||
fun popActivityToStack(activity: Activity) {
|
||||
if (!activityStack.empty()) {
|
||||
activityStack.forEach {
|
||||
if (it == activity) {
|
||||
activityStack.remove(activity)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回到上一个 Activity 并结束当前 Activity
|
||||
*/
|
||||
fun backToPreviousActivity() {
|
||||
if (!activityStack.empty()) {
|
||||
val activity = activityStack.pop()
|
||||
if (!activity.isFinishing) activity.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类名 判断是否是当前的 Activity
|
||||
* @param cls Class<*> 类名
|
||||
* @return Boolean
|
||||
*/
|
||||
fun isCurrentActivity(cls: Class<*>): Boolean {
|
||||
val currentActivity = getCurrentActivity()
|
||||
return if (currentActivity != null) currentActivity.javaClass == cls else false
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的 Activity
|
||||
*/
|
||||
fun getCurrentActivity(): Activity? =
|
||||
if (!activityStack.empty()) activityStack.lastElement() else null
|
||||
|
||||
/**
|
||||
* 结束一个栈内指定类名的 Activity
|
||||
* @param cls Class<*>
|
||||
*/
|
||||
fun finishActivity(cls: Class<*>) {
|
||||
activityStack.forEach {
|
||||
if (it.javaClass == cls) {
|
||||
if (!it.isFinishing) it.finish()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出其他 Activity
|
||||
*/
|
||||
fun popOtherActivity() {
|
||||
val activityList = activityStack.toList()
|
||||
getCurrentActivity()?.run {
|
||||
activityList.forEach { activity ->
|
||||
if (this != activity) {
|
||||
activityStack.remove(activity)
|
||||
activity.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回到指定 Activity
|
||||
*/
|
||||
fun backToSpecifyActivity(activityClass: Class<*>) {
|
||||
val activityList = activityStack.toList()
|
||||
// 获取栈最上面的Activity
|
||||
val lastElement = activityStack.lastElement()
|
||||
activityList.forEach {
|
||||
// 如果栈内存在该Activity就进行下一步操作
|
||||
if (it.javaClass == activityClass) {
|
||||
// 判断最上面的Activity是不是指定的Activity 不是就finish
|
||||
if (lastElement.javaClass == activityClass) {
|
||||
return
|
||||
} else {
|
||||
activityStack.remove(lastElement)
|
||||
lastElement.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Lib_Base/src/main/java/com/quyunshuo/base/utils/DateUtils.kt
Normal file
35
Lib_Base/src/main/java/com/quyunshuo/base/utils/DateUtils.kt
Normal file
@ -0,0 +1,35 @@
|
||||
package com.quyunshuo.base.utils
|
||||
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @Author: QuYunShuo
|
||||
* @Time: 2020/9/8
|
||||
* @Class: DateUtils
|
||||
* @Remark: 时间工具类
|
||||
*/
|
||||
object DateUtils {
|
||||
/**
|
||||
* 获取时间格式化String
|
||||
* @param timestamp 时间戳
|
||||
* @param dateFormat 日期格式
|
||||
*/
|
||||
fun getDateFormatString(timestamp: Long, dateFormat: String): String =
|
||||
SimpleDateFormat(dateFormat, Locale.CHINESE).format(Date(timestamp))
|
||||
|
||||
/**
|
||||
* 将固定格式[dateFormat]的时间字符串[dateString]转换为时间值
|
||||
*/
|
||||
fun getDateStringToDate(dateString: String, dateFormat: String): Long {
|
||||
val simpleDateFormat = SimpleDateFormat(dateFormat, Locale.CHINESE)
|
||||
var date = Date()
|
||||
try {
|
||||
date = simpleDateFormat.parse(dateString)
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return date.time
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,15 @@
|
||||
package com.quyunshuo.base.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkInfo
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.quyunshuo.base.BaseApplication
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.InternalCoroutinesApi
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
@ -13,8 +20,11 @@ import kotlinx.coroutines.flow.flowOn
|
||||
* 以顶层函数存在的常用工具方法
|
||||
* startPolling() -> 开启一个轮询
|
||||
* sendEvent() -> 发送普通EventBus事件
|
||||
* toastShow() -> Toast
|
||||
* isNetworkAvailable() -> 检查是否连接网络
|
||||
* aRouterJump() -> 阿里路由不带参数跳转
|
||||
*/
|
||||
|
||||
/**************************************************************************************************/
|
||||
/**
|
||||
* 使用 Flow 做的简单的轮询
|
||||
* 请使用单独的协程来进行管理该 Flow
|
||||
@ -22,7 +32,6 @@ import kotlinx.coroutines.flow.flowOn
|
||||
* @param intervals 轮询间隔时间/毫秒
|
||||
* @param block 需要执行的代码块
|
||||
*/
|
||||
@InternalCoroutinesApi
|
||||
suspend fun startPolling(intervals: Long, block: () -> Unit) {
|
||||
flow {
|
||||
while (true) {
|
||||
@ -34,8 +43,62 @@ suspend fun startPolling(intervals: Long, block: () -> Unit) {
|
||||
.flowOn(Dispatchers.Main)
|
||||
.collect { block.invoke() }
|
||||
}
|
||||
/**************************************************************************************************/
|
||||
|
||||
/**
|
||||
* 发送普通EventBus事件
|
||||
*/
|
||||
fun sendEvent(event: Any) = EventBusUtils.postEvent(event)
|
||||
fun sendEvent(event: Any) = EventBusUtils.postEvent(event)
|
||||
|
||||
/**************************************************************************************************/
|
||||
private var mToast: Toast? = null
|
||||
|
||||
/**
|
||||
* Toast
|
||||
* Android 9.0之上 已做优化
|
||||
*/
|
||||
fun toastShow(text: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
Toast.makeText(BaseApplication.context, text, duration).show()
|
||||
} else {
|
||||
if (mToast != null) {
|
||||
mToast?.setText(text)
|
||||
mToast?.show()
|
||||
} else {
|
||||
mToast = Toast.makeText(BaseApplication.context, text, duration)
|
||||
mToast?.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************************************/
|
||||
/**
|
||||
* 判断是否连接网络
|
||||
*/
|
||||
@SuppressLint("MissingPermission")
|
||||
fun isNetworkAvailable(): Boolean {
|
||||
val connectivityManager: ConnectivityManager? =
|
||||
BaseApplication.context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
if (connectivityManager == null) {
|
||||
return false
|
||||
} else {
|
||||
val allNetworkInfo: Array<NetworkInfo>? = connectivityManager.allNetworkInfo
|
||||
if (allNetworkInfo != null && allNetworkInfo.isNotEmpty()) {
|
||||
allNetworkInfo.forEach {
|
||||
if (it.state == NetworkInfo.State.CONNECTED) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**************************************************************************************************/
|
||||
/**
|
||||
* 阿里路由不带参数跳转
|
||||
* @param routerUrl String 路由地址
|
||||
*/
|
||||
fun aRouterJump(routerUrl: String) {
|
||||
ARouter.getInstance().build(routerUrl).navigation()
|
||||
}
|
||||
Reference in New Issue
Block a user