Android快速实现地图功能(不仅快!而且小!)
导读
本文旨在提供一个解决思路,不仅适用于添加地图这一种场景。还有更多的场景可以用到,比如展示在线 PDF 文档等。
01 前言
最近都在忙着讨论项目需求,忙着学习 React Native ,时间一久都快忘记我是一个搞 Andorid 开发的了。今天突然想到了自己在上个项目期间的一个经历。觉得可能会对一些人有帮助,于是就写出来和大家分享一下!
上个项目是一个 O2O 类型的项目,在更新了几个版本之后,老板打算进行推广,进行地铁广告,电梯广告,地推等等。让我把 Apk 大小优化一下,说现在的10M太大了,不利于用户下载。
02 穷途末路
其实我在写代码的时候已经很克制了。除了一些必备的三方库以外,基本也没有引入什么其他多余的东西。而且我已经做了以下优化工作:
优化图片大小
-
使用 tinyPNG 压缩图片大小
-
有些图片换成 webP 格式,如背景图
-
icon 图标仅保留一套,使用时将 ImageView 大小限制死。仅保留极个别不同分辨率的图标。
-
部分icon 使用 svg 代替(少量)
优化布局
-
优化层级,减少布局嵌套
-
一个界面一个界面的消除过渡绘制
-
多使用 include 标签,重用布局
-
不必要的布局使用 ViewStub 延迟加载(用的很少)
-
将可复用资源抽取到对应的 res 文件中,如字符串,样式等
优化代码
-
实体类去除没用到属性,并将属性设为 public ,去除 get / set 方法
-
减少内部嵌套的实体类,尤其像 GsonFormat 这样的工具生成的实体类
-
能服用的尽量复用。
-
还剔除了一部分我自己常用的打包好的工具类中一些没调到的方法。
-
不过,仅是减少几行代码,对 Apk 体积的优化成效甚微。
优化三方库的使用
-
Glide 还是 Picaso 纠结了好一阵子。Picaso 要小很多
-
推送,统计,三方登录,微信支付,地图,这个没法删。但是优化了一下 so 适配CPU的数量。
经过了这些工作后(可能有遗漏,时间太久记不太清了),老板还让我优化 Apk 大小,我就实在是想不到其他办法了。而且我把网上能搜到的关于 Apk 优化的文章基本都看了,只要是能用的都会去试一下。但除了图片以外的优化都收效甚微。
03 灵光一闪
我把 Apk 传到 **https://nimbledroid.com **上进行了分析,发现其中最占体积的就是【百度地图】了,足足占了 6M 多。但是我们作为 O2O 产品怎么可能没有地图呢?这是产品经理也不会同意的啊。于是我苦思冥想,采取了曲线救国的方式,干掉了百度地图,最终将那个版本的推广 Apk 包减小至仅有 3.34M。(由于已经离职,下图就不显示App名称了,除非有广告费,哈哈哈~)
图片思路很简单,就是用 JS 的地图替换了原生的地图。因为我分析了一下地图在这个 App 的功能占比,其实算是一个比较弱的功能,用户要想看到地图页面,必须经历以下的流程。
图片 图片如上图所示,这个页面的层级比较深,而且根据前面几个版本的页面统计数据来看,确实很少有用户点到这个界面来。但是又不能没有这个功能,所以最终采取了这样折中的办法。性能怎么样呢?再来个图给大家看下吧。
图片我觉得性能还是可以接受的,虽然不如原生加载的快,但是我很满意了,因为我把安装包缩小了(用到的导航功能是跳转外部地图)终于可以交差了,而且产品经理和老板都没有看出和之前地图的差别来,只是觉得这个小伙子还挺屌的,真的给搞到只剩下3M了(嘿嘿~)。
04 代码实现
相比集成原生地图,集成 JS 地图简直就是不能再更简单了!! 不用下载烦人的 jar 包,不用考虑 so 文件的兼容。而且我觉得 JS 地图只有性能上不如原生,在功能上貌似还要更丰富一点。当然这里只是用于简单的地图展示和添加一个 Marker,更多功能可以自行探索。
但是最开始集成的时候我还是遇到了坑,刚开始使用的是百度的 JS 地图,但是发现在通过 Native 代码调用 JS 代码设置 Marker 的时候,百度总设置失败。网上查了很久,总觉得步骤方法都没有错,但是就是不行,正当我打算放弃这个念头的时候,想起来不是还有高德地图的么,于是试了一下果然就行了。
先大概说一下步骤:
-
到开发者平台申请 JS 地图的秘钥
-
在 assets 目录下创建一个离线的 html 页面
-
在 WebView 中加载该离线页面
-
通过 Native 调用 JS 方法,在地图上添加 Marker 图标
第一步就不用我说了吧,直接从第二步开始吧。【2】在 assets 目录下创建一个离线地图 html 网页【amap.html】,代码如下↓↓↓,注意看注释!!这里可能需要我们会一点 HTML 和 JS 的知识。速成就好了,只要明白一个 html 页面是如何搭建起来的就行。
图片放大看,源码点原文▼
图片【3】然后创建一个带 WebView 控件的 Activity 页面,在代码中将该 WebView 的 setJavaScriptEnabled() 方法设置为 true,然后通过 webview 加载 asstes 中编写好的离线地图 amap.html 文件。
图片【4】最后在 JS 地图上设置 Marker 就行。这里涉及到了 Native 调用 JS 代码,不熟悉的可以搜索一下。
图片05 结语
这个 App 是一年多以前写的了,因为最近在学习 React Native,就突然回想起了那次通过 JS 解决问题的经历。 所以写出来和大家分享一下。其实还有很多业务可以通过这种思路去解决,但是通过 WebView 调用 JS 代码毕竟还是存在性能上的局限性,所以才会出现像 RN 这样的技术。恩...看来还是要早点把 RN 学好才行!哈哈~