一系列简单、轻量、方便的Android开发工具集合(持续更新中),包括Android动态权限、SharedPreferences、反射、日志、Toast、Bundle、MVP、线程池、Html、图文混排、蒙层引导、拍照、图库选择等
在平时的开发过程中,我们经常会需要使用到一些基础功能组件,比如Toast,比如Log等。
而这些功能组件,在开发时需要使用到的功能点其实相当有限,所以这也意味着,我们对此类组件的要求是:简单、轻量、易用!相对应的,此类组件的封装库,也应该尽量实现得轻巧精练
EasyAndroid即是专门针对此种需求所设计的一款基础组件集成库
组件间独立存在,不相互依赖,且若只需要集成库中的部分组件。也可以很方便的
只copy对应的组件文件
进行使用
因为是组件集成库,所以要求每个组件的设计尽量精练、轻巧。避免因为一个小功能而引入大量无用代码.
每个组件的方法数均
不超过100
. 大部分组件方法数甚至不超过50
。
maven { url 'https://jitpack.io' }
implementation "com.github.yjfnypeu:EasyAndroid:$lastest_version"
在Application中调用初识化方法:
EasyAndroid.init(application)
然后即可直接使用
由于此为轻量组件集成库
, 所以框架中包含了多个独立
的应用组件提供使用。
但是有的时候,如果你只需要使用框架中的少数或者个别的组件
。可以直接copy对应的组件源码文件
到工程中去直接使用。
请注意:大部分组件均是完全独立存在的。直接copy源文件即可正常使用。
而部分组件会需要依赖EasyAndroid类。去获取可用的Application Context
实例进行使用。对于这部分的组件。
替换内部EasyAndroid.getApplicationContext()
为你们项目自身的application context即可。
img
标签的图片加载功能使用示例:
// 创建引导层示例,并为引导层添加指定配置
val item = GuideItem.newInstance(view, padding)
.setLayout(guideLayout)// 设置引导View
.setGravity(Gravity.LEFT)// 设置引导View位置
.setOffsetProvider(provider)// 设置用于进行引导View的位置调整
.setHighLightShape(GuideItem.SHAPE_RECT)// 设置高亮区域绘制模式
.setOnViewAttachedListener(listener)// 设置引导View被添加到蒙层布局中时的通知监听
.setOnDrawHighLightCallback(callback)// 这是自定义高亮块绘制回调
.setOnHighLightClickListener(listener)// 设置高亮点击回调监听
// 创建蒙层实例并绑定引导层,进行展示:
EasyGuideLayer.with(activity)
.setBackgroundColor(color)// 蒙层背景色
.setOnGuideShownListener(lambda)// 蒙层展示、消失监听
.addItem(item)// 绑定引导层实例
.setDismissOnClickOutside(false)// 设置点击到蒙层上的非点击区域时,是否自动让蒙层消失
.setDismissIfNoItems(true)// 设置当蒙层中一个引导层实例都没绑定时,自动让蒙层消失
.show()// 展示蒙层
placeholde
图片加载时占位图error
图片加载失败时的占位图用户实例:
// 提供html文本数据
private val html =
"""
<h5>asset图片加载示例</h5>
<img src="file:///android_asset/imagegetter/cat.png">
<h5>http图片加载示例</h5>
<img src="http://www.w3school.com.cn/i/eg_tulip.jpg">
""".trimIndent()
// 提供展示的TextView控件
private val textView:TextView = getTextView()
EasyImageGetter.create()
// 设置图片加载时的占位图
.setPlaceHolder(R.drawable.placeholder)
// 设置图片加载失败时的占位图
.setError(R.drawable.error)
// 指定加载的html与tv控件即可
.loadHtml(html, textView)
从图库或者使用相机拍照获取图片的组件。
贡献者:Vicent9920
用户实例:
val photo = EasyMedia()// 创建EasyMedia实例
// 是否需要进行裁剪
.setCrop(true|false)
// 指定创建的图片地址。
.setImgPath(imgPath:String)
// 通过设置回调,获取选择到的文件
photo.setCallback { file:File ->
// TODO 使用选择的文件进行操作
}
// 当然。不排除出现非预期的问题。所以也提供了错误回调
photo.setError { error:Exception ->
// TODO
}
// 跳转拍照并获取图片
photo.takePhoto(activity)
// 或者跳转图库进行图片选择
photo.selectPhoto(activity)
使用一个具体的实体类,进行SharedPreferences数据存取
key值硬编码
直接使用SharedPreferences进行赋值
,也能自动同步相关数据。用法示例:
// 以SharedPreferences文件名为user_info,存储数据为username, age, address为例
// 1. 创建映射实体类
@PreferenceRename("user_info")
class User:PreferenceSupport() {
var username:String
var age:Int
var address:String
}
// 2. 进行读取
val user = EasySharedPreferences.load(User::class.java)
// 3. 进行修改
// 直接使用load出来的user实例进行数值修改
user.age = 16
user.username = "haoge"
// 修改完毕后,apply更新修改到SharedPreferences文件。
user.apply()
用于灵活的进行设备尺寸单位转换
支持全尺寸数值转换。
用法示例
// 转换10dp到px
EasyDimension.withDIP(10).toPX()
// 转换30sp到MM
EasyDimension.withSP(30).toMM()
用于对任意类型数据,进行格式化输出排版,结合log打印组件使用,使log输出展示更清晰
Set/List/Map/JSON/POJO
数据进行格式化排版用法示例:
// 创建待格式化数据
val any:Any = create()
// 使用formatter实例进行格式化
val result:String = EasyFormatter.DEFAULT.format(any)
用于简单的进行日志打印输出,支持格式化输出、自定义打印格式。
用法示例:
val any:Any = create()// 创建待打印数据
EasyLog.DEFAULT.d(any)// 使用默认log实例进行数据打印. 以Log.d()的方式进行输出
用于进行Toast提示,可很简单的指定输出样式。
博客地址:https://juejin.im/post/5b0638336fb9a07aa9261ce6
用法示例:
val message:String = create()// 创建待提示数据
EasyToast.DEFAULT.show(message)// 使用系统样式进行输出
EasyToast.create(layoutID:Int, tvID:Int, duration:Int).show(message)// 使用自定义样式进行输出
对常规的反射操作进行封装。达到更便于使用反射的效果
博客地址:https://juejin.im/post/5b1de20c6fb9a01e701000cb
用法示例:
// 以类名Test为例
class Test private constructor(private val name:String) {
private fun wrap(name:String):String = "包裹后的数据$name"
}
// 创建Reflect实例:
var reflect = EasyReflect.create(Test::class.java).instance("默认参数")
// 为name字段赋值:
reflect.setField("name", "EasyReflect")
// 读取name字段的值:"EasyReflect"
val value = reflect.getValue("name")
// 调用方法wrap方法,并传入参数value
reflect.call("wrap", value)
// 调用wrap方法,并获取返回值: "包裹后的数据EasyReflect"
val result = reflect.callWithReturn("wrap", value).get<String>()
用于解决onActivityResult业务逻辑臃肿的问题
博客地址:https://juejin.im/post/5b21d019e51d4506d93701ba
用法示例:
EasyActivityResult.startActivity(activity, Intent(activity, DemoActivity::class.java),
{ resultCode:Int, data:Intent? ->
// 直接在此进行返回数据处理
})
进行6.0+的动态权限请求
博客地址:https://juejin.im/post/5b1a2a326fb9a01e5d32f208
用法示例:
EasyPermissions.create(// 指定待申请权限
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.WRITE_CALENDAR,
Manifest.permission.WRITE_CONTACTS
)
// 定制权限申请说明弹窗
.rational { permission, chain ->
AlertDialog.Builder(this)
.setTitle("权限申请说明")
.setMessage("应用需要此权限:\n$permission")
.setNegativeButton("拒绝", {_, _ -> chain.cancel() })
.setPositiveButton("同意", {_, _ -> chain.process() })
.show()
return@rational true
}
// 设置授权结果回调
.callback { grant ->
EasyToast.DEFAULT.show("权限申请${if (grant) "成功" else "失败"}")
}
// 当权限被默认拒绝时。调起弹窗提醒需要用户去主动开启权限
.alwaysDenyNotifier(object : PermissionAlwaysDenyNotifier() {
AlertDialog.Builder(activity)
.setTitle("权限申请提醒")
.setMessage("以下部分权限已被默认拒绝,请前往设置页将其打开:\n\n")
.setPositiveButton("确定", { _, _ -> goSetting(activity)})
.setNegativeButton("取消", {_,_ -> cancel(activity)})
.show()
})
// 发起请求
.request()
用于进行
安全
、高效
、便利
的线程池操作功能组件
用法示例
// 1. 第一步:创建示例
val executor =
// size为所需创建的线程池的大小。当size <= 0时。
// 表示需要使用newCachedThreadPool。
EasyExecutor.newBuilder(size)
.setName(name)// 默认的线程名
.setPriority(priority)// 线程池中创建线程的优先级
.onStart {threadName -> } // 默认任务启动时的回调
.onSuccess {threadName -> }// 默认任务执行完毕后的回调
.onError {threadName, throwable -> }// 默认任务执行出现异常时的回调
.setDeliver(deliver)// 默认的回调任务派发器。用于将信息派发到指定线程去。
.build()// 最后。执行创建
// 2. 第二步:启动任务
executor.execute(runnable:Runnable)// 启动普通任务
// 启动异步回调任务
executor.asyncResult(result:(T) -> Unit) // 先配置任务回调
.asyncTask(task:(Notifier) -> T)// 配置后台执行任务
executor.setDelay(delay).execute(runnable)// 延时启动任务
用于使Bundle数据存取操作变得
简单
、方便
、灵活
、强大
博客地址:https://juejin.im/post/5b2c65bde51d45587d2dd86f
用法示例:
// 1. 存储任意数据对象到bundle中去
EasyBundle.create(bundle)// 绑定bundle容器
.put(key, value)// 指定任意数据进行存储。包括非可序列化对象
// 2. 从bundle中读取并自动转换为具体对象数据
EasyBundle.create(bundle).get<User>("user")
// 3. 支持数据自动注入
class ExampleActivity:BaseActivity() {
// 从intent中读取name数据并注入到name字段中去
@BundleField
var name:String? = null
}
博客地址:https://juejin.im/post/5b4ee27ff265da0f98314f01
提供的一种简单的MVP分层架构实现。
用法示例
// 1. 创建页面通信协议接口:
interface CustomView:MVPView {
// 定义通信协议方法:P层将使用此方法驱动V层进行界面更新
fun updateUI()
}
// 2. 创建Presenter。并与对应的通信协议相绑定:
class CustomPresenter(view:CustomView):MVPPresenter(view) {
// 直接创建对应的启动方法,供V层进行启动调用
fun requestData() {
// TODO 进行数据业务处理。并在处理完成后,通过view通知到V层
}
}
// 3. 创建具体的V层(Activity or Fragment),并绑定Presenter进行使用:
class CustomActivity:BaseMVPActivity, CustomView {
// 创建presenter并绑定。可创建多个persenter使用
val persenter = CustomPresenter(this)
override fun createPresenters() = arrayOf(presenter)
override fun updateUI() {// TODO 进行界面更新}
fun initPage() {
// 通过绑定的Presenter发起任务
presenter?.requestData()
}
}
部分组件需要进行混淆配置。请注意别遗漏了:
# EasyBundle
-keepclasseswithmembernames class * {
@com.haoge.easyandroid.easy.BundleField <fields>;
}
# EasySharedPreferences
-keep class * implements com.haoge.easyandroid.easy.PreferenceSupport { *; }
或者手动加入QQ群: 108895031