佛山微网站建设,外链生成工具,python采集更新wordpress,对新网站做seo大概需要多久简述: 由于个人原因#xff0c;已经有很长一段时间没有写过文章#xff0c;有句话是那么说的只要开始就不会太晚#xff0c;所以我们开始《用Kotlin撸一个图片压缩插件》系列文章最后一篇实战篇。实际上我已经把源码发布到了GitHub#xff0c;代码很简单。有了前两篇文章的…简述: 由于个人原因已经有很长一段时间没有写过文章有句话是那么说的只要开始就不会太晚所以我们开始《用Kotlin撸一个图片压缩插件》系列文章最后一篇实战篇。实际上我已经把源码发布到了GitHub代码很简单。有了前两篇文章的基础这篇文章将会使用Kotlin从零开始带你撸个图片压缩插件。 一、开发前期准备工作 1、访问TinyPng官网注册TinyPng开发者账号拿到TinyPng ApiKey,整个过程只需简单注册验证即可。 2、由于本项目图片压缩框架是基于TinyPng的图片压缩API来实现的所以需要在TinyPng官网提供了develop开发库可以找到相应Java的jar为了方便下载这里就直接贴出地址了:TinyPng依赖包下载 3、由于图片插件使用到GUI插件GUI采用的是Java中的Swing框架搭建具体可以去复习相关Swing的知识点当然只需要大概了解即可毕竟这个不是重点。 4、需要去掌握插件开发的基础知识由于本篇文章是实战篇就不去细讲插件基础知识具体详情可参照该系列的第二篇文章用Kotlin撸一个图片压缩插件-插件基础篇(二) 5、需要有Kotlin的基本开发知识比如Kotlin中扩展函数的封装Lambda表达式函数式APIIO流API的使用 二、图片压缩插件基本功能点 图片压缩插件主要支持如下两大功能: 1、支持指定图片源输入目录批量压缩到一个指定的输出目录。 2、支持在AndroidStudio项目中直接选中指定的一个或多个图片右键点击直接压缩。 三、实现思路分析 实现的整体思路首先我们需要找到实现关键点然后从关键点一步步向外扩展延伸那么实现图片压缩的插件的关键点在哪里肯定毫无疑问是图片压缩API也就是TinyPng API函数调用实现。 Tinify.fromFile(inputFile).toFile(inputFile)
复制代码通过以上的TinyPng API就可以找到关键点一个是输入文件另一个则是输出文件那么我们这个图片压缩插件的所有实现都是围绕着如何通过一个简单的方式指定一个输入文件或目录和一个输出文件或目录。 没错就是这么简单那么我们一起来分析下上面两大功能实现思路其实也很简单 功能点一: 就是通过Swing框架中的JFileChooser组件打开并指定一个图片输入文件或目录和一个图片压缩后的输出文件或目录即可。 功能点二: 通过Intellij Idea open api中的 DataKeys.VIRTUAL_FILE_ARRAY.getData(this)拿到当前选中的Virtual Files,也就是当前选中的文件把选中的文件当做输入文件然后图片压缩后文件直接输出到源文件中即可。 注意: 由于Tiny.fromFile().toFile()内部源码实际上通过OkHttp发送图片压缩的网络请求而且内部采用的方式是同步请求的但是在IDEA Plugin开发中主线程是不能执行耗时任务的所以需要将该API方法调用放在异步任务中 四、代码结构和实现 action包:主要定义插件中的两个action我们都知道在插件开发中Action是功能执行的入口ImageSlimmingAction是前面说到第一个功能点批量压缩指定输入和输出目录的RightSelectedAction是前面说过的第二个功能点在项目选中图中文件直接右键压缩的, 最后这两个Action都需要在plugin.xml中注册。 actionsaction classcom.mikyou.plugins.image.slimming.action.ImageSlimmingAction textImageSlimmingidcom.mikyou.plugins.image.slimming.action.ImageSlimmingActiondescriptioncompress picture plugin icon/img/icon_image_slimming.pngadd-to-group group-idMainToolBar anchorafter relative-to-actionAndroid.MainToolBarSdkGroup//actionaction idcom.mikyou.plugins.image.action.rightselectedactionclasscom.mikyou.plugins.image.slimming.action.RightSelectedAction textQuick Slim ImagesdescriptionQuick Slim Imagesadd-to-group group-idProjectViewPopupMenu anchorafter relative-to-actionReplaceInPath//action/actions
复制代码extension包: 主要是定义了Kotlin中的扩展函数一个是Boolean的扩展可以类似链式调用来替代if-else判断另一个则是Dialog使用的扩展//Boolean 扩展
sealed class BooleanExtout Tobject Otherwise : BooleanExtNothing()//Nothing是所有类的子类协变的类继承关系和泛型参数类型继承关系一致class TransferDataT(val data: T) : BooleanExtT()inline fun T Boolean.yes(block: () - T): BooleanExtT when {this - TransferData(block.invoke())else - Otherwise
}inline fun T Boolean.no(block: () - T): BooleanExtT when {this - Otherwiseelse - TransferData(block.invoke())
}inline fun T BooleanExtT.otherwise(block: () - T): T when (this) {is Otherwise -block()is TransferData -this.data
}//Dialog扩展
fun Dialog.showDialog(width: Int 550, height: Int 400, isInCenter: Boolean true, isResizable: Boolean false) {pack()this.isResizable isResizablesetSize(width, height)if (isInCenter) {setLocation(Toolkit.getDefaultToolkit().screenSize.width / 2 - width / 2, Toolkit.getDefaultToolkit().screenSize.height / 2 - height / 2)}isVisible true
}fun Project.showWarnDialog(icon: Icon UIUtil.getWarningIcon(), title: String, msg: String, positiveText: String 确定, negativeText: String 取消, positiveAction: (() - Unit)? null, negativeAction: (() - Unit)? null) {Messages.showDialog(this, msg, title, arrayOf(positiveText, negativeText), 0, icon, object : DialogWrapper.DoNotAskOption.Adapter() {override fun rememberChoice(p0: Boolean, p1: Int) {if (p1 0) {positiveAction?.invoke()} else if (p1 1) {negativeAction?.invoke()}}})
}
复制代码 helper包主要是用文件IO操作由于两个Action都存在图片压缩操作为了复用就直接把图片压缩API调用的实现操作抽出封装在ImageSlimmingHelper中。 ui包主要就是Swing框架中一些界面GUI的实现和交互。 四、实现的关键技术点 关键点一: 插件开发中如何执行一个异步任务IDEA Plugin开发和Android开发很类似一些耗时的任务是不能直接在主线程执行的需要在特定后台线程执行否则会阻塞主线程。在intellij open api中有个Task.Backgroundable抽象类就是处理异步任务的。Backgroundable继承了Task类以及实现了PerformInBackgroundOption接口。具体使用很简单传入两个参数一个是Project对象和一个执行异步中hint提示文本有四个回调函数分别为run(progress: ProgressIndicator)、onSuccess、onThrowable、onFinished.最后通过queue方法加入到异步任务队列中。为了方便调用将其封装成一个扩展函数来使用。 //创建后台异步任务的Project的扩展函数asyncTask
private fun Project.asyncTask(hintText: String,runAction: (ProgressIndicator) - Unit,successAction: (() - Unit)? null,failAction: ((Throwable) - Unit)? null,finishAction: (() - Unit)? null
) {object : Task.Backgroundable(this, hintText) {override fun run(p0: ProgressIndicator) {runAction.invoke(p0)}override fun onSuccess() {successAction?.invoke()}override fun onThrowable(error: Throwable) {failAction?.invoke(error)}override fun onFinished() {finishAction?.invoke()}}.queue()
}
//asyncTask的使用project?.asyncTask(hintText 正在压缩, runAction {//执行图片压缩操作outputSameFile.yes {//针对右键选定图片情况直接压缩当前目录选中图片输出目录包括文件也是原来的inputFiles.forEach { inputFile - Tinify.fromFile(inputFile.absolutePath).toFile(inputFile.absolutePath) }}.otherwise {inputFiles.forEach { inputFile - Tinify.fromFile(inputFile.absolutePath).toFile(getDestFilePath(model, inputFile.name)) }}}, successAction {successAction?.invoke()}, failAction {failAction?.invoke(TinyPng key存在异常请重新输入)})
复制代码关键点二: 插件开发中如何获取当前选中的文件或目录在插件开发中如何获得当前选中文件实际上open api提供了类似DataContext数据上下文环境我们需要去拿到文件集合对象就需要先找到文件管理的窗口对象还记得上篇博客中说到的AnActionEvent对象是插件与IDEA交互通信的一个媒介通过AnActionEvent内部的dataContext的getData方法传入对应的DataKey对象获得相应的窗口对象。在CommonDataKey中有一个DataKeyVirtualFile[]通过传入当前event中的dataContext对象即可获得当前选中的文件对象集合。 private fun DataContext.getSelectedFiles(): ArrayVirtualFile? {return DataKeys.VIRTUAL_FILE_ARRAY.getData(this)//右键获取选中多个文件,扩展函数}
复制代码关键点三: Swing中JFileChooser组件的使用关于JFileChooser组件的使用就比较简单了这里就不去详细介绍代码也很简单 private void openFileAndSetPath(JComboBoxString cBoxPath, int selectedMode, Boolean isSupportMultiSelect) {JFileChooser fileChooser new JFileChooser();fileChooser.setFileSelectionMode(selectedMode);fileChooser.setMultiSelectionEnabled(isSupportMultiSelect);//设置文件扩展过滤器if (selectedMode ! JFileChooser.DIRECTORIES_ONLY) {fileChooser.addChoosableFileFilter(new FileNameExtensionFilter(.png, png));fileChooser.addChoosableFileFilter(new FileNameExtensionFilter(.jpg, jpg));fileChooser.addChoosableFileFilter(new FileNameExtensionFilter(.jpeg, jpeg));}fileChooser.showOpenDialog(null);if (selectedMode JFileChooser.DIRECTORIES_ONLY) {//仅仅选择目录情况不存在多文件选中File selectedDir fileChooser.getSelectedFile();if (selectedDir ! null) {cBoxPath.insertItemAt(selectedDir.getAbsolutePath(), 0);cBoxPath.setSelectedIndex(0);}} else {//选择含有文件情况包括仅仅 选择文件 和 同时选择文件和目录File[] selectedFiles fileChooser.getSelectedFiles();if (selectedFiles ! null selectedFiles.length 0) {cBoxPath.insertItemAt(getSelectedFilePath(selectedFiles), 0);cBoxPath.setSelectedIndex(0);}}}
复制代码关键点四: api key的验证和图片压缩的实现在进行图片压缩前就是需要去验证一下TingPng ApiKey的合法性如果第一次验证合法就需要把该ApiKey存储在本地下次压缩就直接使用本地的key进行压缩一旦本地key失效后需要重新弹出TinyPng apikey 的验证提示框进行重新认证。当然需要注意的是验证api key的合法性也是进行一次同步的网络请求所以它也要放在异步任务执行。 fun checkApiKeyValid(project: Project?,apiKey: String,validAction: (() - Unit)? null,invalidAction: ((String) - Unit)? null
) {if (apiKey.isBlank()) {invalidAction?.invoke(TinyPng key为空请重新输入)}project?.asyncTask(hintText 正在检查key是否合法, runAction {try {Tinify.setKey(apiKey)Tinify.validate()} catch (exception: Exception) {throw exception}}, successAction {validAction?.invoke()}, failAction {println(验证Key失败!!${it.message})invalidAction?.invoke(TinyPng key验证失败请重新输入)})
}
复制代码然后就是利用异步任务进行图片压缩操作。 fun slimImage(project: Project?,inputFiles: ListFile,model: ImageSlimmingModel ImageSlimmingModel(, , , ),successAction: (() - Unit)? null,outputSameFile: Boolean false,failAction: ((String) - Unit)? null
) {project?.asyncTask(hintText 正在压缩, runAction {//执行图片压缩操作outputSameFile.yes {//针对右键选定图片情况直接压缩当前目录选中图片输出目录包括文件也是原来的inputFiles.forEach { inputFile - Tinify.fromFile(inputFile.absolutePath).toFile(inputFile.absolutePath) }}.otherwise {inputFiles.forEach { inputFile - Tinify.fromFile(inputFile.absolutePath).toFile(getDestFilePath(model, inputFile.name)) }}}, successAction {successAction?.invoke()}, failAction {failAction?.invoke(TinyPng key存在异常请重新输入)})
}
复制代码五、总结 到这里《用Kotlin撸一个图片压缩插件》系列文章就结束了其实实现起来挺简单的其中主要的关键点就是需要更加熟悉使用Intellij open api, 然后其他就是运用好Kotlin的一些语法特性其余的都很简单。而且个人觉得把图片压缩做成一个插件会变得很高效不然传统的模式得需要把图片拖到浏览器中然后一个一个下载下来还有的人问我不就是一个脚本能解决的吗脚本个人觉得不够灵活不能像插件一样任意在项目中选中一张或多张图片直接右键压缩。如有什么问题欢迎下方留言谢谢。 插件项目源码地址 欢迎关注Kotlin开发者联盟这里有最新Kotlin技术文章每周会不定期翻译一篇Kotlin国外技术文章。如果你也喜欢Kotlin欢迎加入我们~~~