技术干货手机移动程序开发

Kotlin 50行代码实现清除Android项目中不用的图片和

2017-05-27  本文已影响0人  Kingty

前言

Google 在I/O大会上宣布了官方支持kotlin作为android的开发语言。因此kotlin一下子进入了android开发同学们的实现,其实我很早就知道这门语言,也看了别人使用这门语言做android开发,但是由于懒,从来也没有看过。正好借此机会,大家都在趁热乎劲学习,我也翻开了官方文档看了看,因为我学习一门语言的方法就是简单浏览一下语法,然后直接开始写一个简单的程序,这样子在实现想要的功能的同时也就简单熟悉了一些常用的语法,于是就有了第一个练习的程序,也就有了这个分享。

Kotlin优点

Kotlin 的语法优点还是很多的。跟scala其实挺像的。如果写过scala,写这个会觉得挺顺手的。

fun fileToString(fn: File) = fn.readLines().filter { l -> !l.trim().startsWith("//") }.asSequence().joinToString("\n")

不必像Java一样还得写好些输入输出流,读取再筛选再拼接。虽然Java经过封装也可以做到,但是Kotlin直接就可以做这些操作非常的简单直观。这就是上面两个优点

val drawables = sequenceOf("png", "jpg", "xml")
fun allFiles(f: File, extensions: Sequence<String>): Sequence<File> {
    val files = ArrayList<File>()
    if (f.isDirectory) {
        f.listFiles().map { f -> files.addAll(allFiles(f, extensions)) }
    } else if (extensions.any { ex -> f.name.endsWith("." + ex) }) {
        files.add(f)
    }
    return files.asSequence()
}

我体验到的大概就是这么多吧。其实也算不上什么新的优点吧,毕竟很多其他语言也是这样的,可能对于平时写java的同学来说确实感觉一下子清新了很多,因为java确实有很多繁杂的代码。像我这样的也只能有一点语法层面的感觉,毕竟我也是刚刚看了一会kotlin这个语言,没有更多细致的了解。

实现

下面简单讲一下如何实现这个功能的,虽然As貌似有这个功能。但是我只是为了练习一下kotlin,也分享一下。
流程很简单:

fun getFileName(f: File): String {
    return f.name.replace(".9.png", "").replace(".png", "").replace(".jpg", "").replace(".xml", "")
}
val drawables = sequenceOf("png", "jpg", "xml")
val resDirs = sequenceOf("-hdpi", "-mdpi", "-xhdpi", "-xxhdpi", "-xxxhdpi").map { s -> "app/src/main/res/mipmap$s" }.asSequence()
fun reses(): Sequence<File> = resDirs.map { str -> allFiles(File(str), drawables) }.flatten()
fun allNames() = reses().map { file -> getFileName(file) }.toSet()

这个功能实现很简单,就是扫描resDirs这几个文件夹通过allFiles()这个方法获取文件夹下面所有的以drawables这个集合中的字符结尾的文件。然后通过getFileName获取到文件的名字,放到Set中
为什么要名字?
因为我们在代码中都是写R.mipmap.xxx或者@mipmap/xxx这样的,我们要拿名字去和代码中用到的名字比较匹配。
通过上面的代码我们就拿到了项目中allNames

val pattern = """@mipmap\/[a-zA-Z0-9_]+[^a-zA-Z0-9_]|R\.mipmap\.[A-Za-z0-9_]+[^a-zA-Z0-9_]""".toPattern()
val codes = sequenceOf("kt", "java", "xml")
val projects = sequenceOf("app")
val usedNames = projects.map { p ->
    allFiles(File(p + "/src"), codes).map { f -> fileToString(f) }.map { str ->
        val names = ArrayList<String>()
        val m = pattern.matcher(str)
        while (m.find()) {
            names.add(m.toMatchResult().group().dropLast(1).replace("@mipmap/", "").replace("R.mipmap.", ""))
        }
        names.asSequence()
    }.flatten()
}.flatten().toSet()

如果你还有其他的module,可以加到projects集合里。这个逻辑也挺简单的。跟上面一样,首先通过allFiles()扫描src目录下面所有以codes集合中字符串结尾的文件,然后通过最上面提到的fileToString方法把每个文件转化成String,通过正则匹配找出其中用到R.mipmap.xxx或者@mipmap/xxx的地方,再取出名字放到Set里面。这样我们就拿到了项目中用到过的所有的资源的名字usedNames

val unusedNames = allNames().filter { d -> !usedNames.contains(d) }.toSet()
fun cleanDir(f: File) {
    if (f.isDirectory) {
        f.listFiles().forEach { f -> cleanDir(f) }
    } else {
        if (unusedNames.map { s -> getFileName(f) == s }.toSet().contains(true)) {
            f.delete()
        }
    }
}
fun clean() = resDirs.map { s -> File(s) }.forEach { f -> cleanDir(f) }

总结

短短50行代码,很适合练习的一个小程序,我花了大概几个小时,在没写过kotlin的情况下写出来的,过程中感受了kotlin语法,知道了一些大概的kotlin编程的方式,也用了这些语法糖。虽然我感觉还是没有scala简单,但是还是值得一试。希望给同样是新手的你一点小的参考。
新手,很多不正之处,还望指点。
所有代码的地址:https://github.com/kingty/kotlin-script-demo/blob/master/clear.kts

上一篇 下一篇

猜你喜欢

热点阅读