美文网首页Android开发经验谈Android技术知识Android开发
用Kotlin开发了一个Android应用,我只用了8小时

用Kotlin开发了一个Android应用,我只用了8小时

作者: Android开发架构 | 来源:发表于2018-12-18 21:33 被阅读0次

    各位小伙伴早上好,上周老家有急事回去了一段时间,回来后赶着做落下的需求加班了一周,于是偷懒了一周没更新,今天继续为大家推送文章,话说年末将至,你们的放假时间定了么?回老家的车票买好了么?好吧,接下来分享来自xfhy同学的投稿文章,文章介绍了他用Kotlin开发了一款Android App,总共耗时8个钟(是的,8个钟,你没看错),当然除去开发时间,前期还花了很多时间去爬数据。

    本项目是开源的,需要代码学习的同学可以访问下方的Github地址:

    https://github.com/xfhy/DeepNight-in-kotlin

    项目简介

    这是一款纯看妹子的app,素材全部来源于正经图库,本app仅做学习交流使用,勿做商用。(请注意,全是正经图片,可别想歪了哦)由于开发时间非常紧急,于是没有用MVP,RxJava2,Retrofit这些都没用。直接用的anko的common库,很方便就可以异步操作和UI线程切换等,为了节约点时间,目前项目中有很多需要优化的地方,比如命名不规范,很多地方没有注释等。

    说到这里,直接先来几张效果图镇楼。

    效果1效果2

    效果3效果4

    用到的知识点

    整个App开发主要用到了以下的知识点:

    kotlin 语言

    - 数据类

    - 伴生对象

    - 单例

    - 扩展

    - 闭包

    - anko

    - jsoup 爬取网页数据的库

    - Material Design 风格

    - Recyclerview 瀑布流

    - CardView

    - Glide 加载图片

    - BaseQuickAdapter 以前自己搞的一个adapter,方便快速开发

    - DrawerLayout

    - NavigationView

    - Toolbar

    - 下拉刷新,上拉加载

    - fragment懒加载

    爬取数据

    网站非常规律,看看jsoup用法很容易就搞到手啦,下面是详细方法.

    首先,我们打开网站,查看网页源代码,可以看到各个分类的网址,待会儿我们可以根据用户选择的分类去爬对应分类的数据.

    然后再来看看,每个分类首页(第一页)其实是有一些图片,我们待会儿需要筛选出这些图片的详情页地址,并且这些图片地址我们可以用来展示到app的分类首页上.其实各分类是不止一页的,它们的规律是从第二页末尾就是index_x.shtml结尾,其中x为当前页索引.http://www.msgao.com/dqfl/om/index_2.shtml

    我们使用Jsoup开源库去爬取数据,关于Jsoup,其实使用起来非常简单,而且官方还非常人性化的有中文文档,地址.

    首先,我们是通过以下方式连接上url

       //连接

        val document: Document = Jsoup.connect(buildUrl).get()

    然后我们筛选那些有图片链接的

    //筛选首页全部的链接   暂时是第一页的

    val htmls: Elements = document.select("a[href$=.shtml]")

    //筛选是可以点击进去详情的url

    htmls.forEachReversedByIndex {

       val realUrl = it.getElementsByClass("div-img")

       //不正确的全部移除

       if (realUrl.size == 0) {

           htmls.remove(it)

       }

    }

    接着是获取图片地址和图片标题

    //外层列表的bean集合

    val outLists: ArrayList<DivListImgBean> = ArrayList()

    htmls.forEach {

       val divListImgBean = DivListImgBean("", "","")

       val linkElements = it.getElementsByClass("link")

       divListImgBean.detailsUrl = linkElements.attr("href")

       //获取图片地址

       val imgSrcs = it.select("img[src\$=.jpg]")

       imgSrcs.forEach {

           val src = it.attr("src")

           val alt = it.attr("alt")

           divListImgBean.src = src

           divListImgBean.text = alt

       }

       //添加bean到集合中

       outLists.add(divListImgBean)

    }

    加入用户点击了某个图片链接,我们就去抓取图片详情页,所有的图片链接,进行该美女的详情展示.在方法上和上面的方法大同小异.

    看代码吧,比我说的更清楚.结合jsoup 开发文档和网页源码一起看哟

    import com.xfhy.deeplibrary.common.LogUtil

    import com.xfhy.deepnight.bean.DivListImgBean

    import org.jetbrains.anko.collections.forEachReversedByIndex

    import org.jetbrains.anko.doAsync

    import org.jetbrains.anko.uiThread

    import org.jsoup.Jsoup

    import org.jsoup.nodes.Document

    import org.jsoup.select.Elements

    /**

    * @author xfhy

    * create at 2018/1/1 12:36

    * description:

    */

    object NetUtils {

       /**

        * 获取外部的列表页的list

        * @param url url

        * @param index 索引  从1开始

        * @param response 回调数据

        */

       fun reqOutList(url: String, index: Int, response: ZResponse) {

           doAsync {

               try {

                   //组装url

                   var buildUrl = "${url}index${if (index == 1) "" else "_$index"}.shtml"

                   LogUtil.e("buildUrl = $buildUrl")

                   //连接

                   val document: Document = Jsoup.connect(buildUrl).get()

                   //筛选首页全部的链接   暂时是第一页的

                   val htmls: Elements = document.select("a[href$=.shtml]")

                   //筛选是可以点击进去详情的url

                   htmls.forEachReversedByIndex {

                       val realUrl = it.getElementsByClass("div-img")

                       //不正确的全部移除

                       if (realUrl.size == 0) {

                           htmls.remove(it)

                       }

                   }

                   //外层列表的bean集合

                   val outLists: ArrayList<DivListImgBean> = ArrayList()

                   htmls.forEach {

                       val divListImgBean = DivListImgBean("", "","")

                       val linkElements = it.getElementsByClass("link")

                       divListImgBean.detailsUrl = linkElements.attr("href")

                       //获取图片地址

                       val imgSrcs = it.select("img[src\$=.jpg]")

                       imgSrcs.forEach {

                           val src = it.attr("src")

                           val alt = it.attr("alt")

                           divListImgBean.src = src

                           divListImgBean.text = alt

                       }

                       //添加bean到集合中

                       outLists.add(divListImgBean)

                   }

                   LogUtil.e(outLists.toString())

                   uiThread {

                       response.onSuccess(outLists)

                   }

               } catch (e: Exception) {

                   uiThread {

                       response.onError(e.message)

                   }

               }

           }

       }

       /**

        * 详情列表

        */

       fun reqDetails(url: String, response: ZResponse) {

           doAsync {

               try {

                   //连接

                   val document: Document = Jsoup.connect(url).ignoreContentType(true).get()

                   val girlPictureList = document.select("div.div-num")

                   val imageList: ArrayList<String> = ArrayList()

                   girlPictureList.forEach {

                       if (it.hasAttr("data-src")) {

                           var imgUrl = it.attr("data-src")

                           imgUrl = imgUrl.substring(0, imgUrl.indexOf("?"))

                           imageList.add(imgUrl)

                       }

                   }

                   LogUtil.e(imageList.toString())

                   uiThread {

                       response.onSuccess(imageList)

                   }

               } catch (e: Exception) {

                   uiThread {

                       response.onError(e.message)

                   }

               }

           }

       }

    }

    构建UI

    UI交互上,我是采用的侧滑风格的app,中间的数据全部采用fragment来填充的,fragment只有在显示后才加载数据(懒加载机制),不会浪费过多流量。素材取自阿里矢量图标库.阿里妈妈MUX倾力打造的矢量图标管理、交流平台。设计师将图标上传到Iconfont平台,用户可以自定义下载多种格式的icon,平台也可将图标转换为字体,便于前端工程师自由调整与调用。下载图标完全免费,而且还可以调整颜色和大小,更有SVG下载,简直爽翻天.对于我这种一点儿也不会制作图标的菜鸟级程序员来说,简直就是福利。

    总结

    其实,将一个没有防爬的网站撸成app还是比较简单的,基本上都是这个套路,大家也可以试试.比如内涵段子等,做成app,然后平时可以自己用,还可以给朋友用,还锻炼了自己所学的知识,何乐而不为呢。

    Kotlin开发起来真的很顺手,也很方便,就像平时说话一样,很顺畅.大家要学习Kotlin的话,建议多看看kotlin的官方文档。

    喜欢文章可以用点赞,私信我可获取更多有关安卓开发的资料!

    相关文章

      网友评论

        本文标题:用Kotlin开发了一个Android应用,我只用了8小时

        本文链接:https://www.haomeiwen.com/subject/qirrkqtx.html