Android快速实现地图功能(不仅快!而且小!)

  • 本文为 Marno 原创,转载必须保留出处!
  • 公众号【 aMarno 】,关注后回复 RN 加入交流群
  • React Native 优秀开源项目大全:www.marno.cn

一、前言

本文旨在提供一个解决思路,不仅适用于添加地图这一种场景。还有更多的场景可以用到,比如展示在线 PDF 文档等。

最近都在忙着讨论项目需求,忙着学习 React Native ,时间一久都快忘记我是一个搞 Andorid 开发的了。今天突然想到了自己在上个项目期间的一个经历。觉得可能会对一些人有帮助,于是就写出来和大家分享一下!

上个项目是一个 O2O 类型的项目,在更新了几个版本之后,老板打算进行推广,进行地铁广告,电梯广告,地推等等。让我把 Apk 大小优化一下,说现在的10M太大了。不利于用户下载。

二、穷途末路

其实我在写代码的时候已经很克制了。除了一些必备的三方库以外,基本也没有引入什么其他多余的东西。而且我已经做了以下优化工作:

  • 优化图片大小

    1.使用 tinyPNG 压缩图片大小
    2.有些图片换成 webP 格式,如背景图
    3.icon 图标仅保留一套,使用时将 ImageView 大小限制死。仅保留极个别不同分辨率的图标。
    4.部分icon 使用 svg 代替,少量

  • 优化布局

    1.优化层级,减少布局嵌套
    2.一个界面一个界面的消除过渡绘制
    3.多使用 include 标签,重用布局
    4.不必要的布局使用 ViewStub 延迟加载(用的很少)
    5.将可复用资源抽取到对应的 res 文件中,如字符串,样式等

  • 优化代码

    1.实体类去除没用到属性,并将属性设为 public ,去除 get / set 方法
    2.减少内部嵌套的实体类,尤其像 GsonFormat 这样的工具生成的实体类
    3.能服用的尽量复用。
    4.还剔除了一部分我自己常用的打包好的工具类中一些没调到的方法。
    5.不过,仅是减少几行代码,对 Apk 体积的优化成效甚微。

  • 优化三方库的使用

    1.Glide 还是 Picaso 纠结了好一阵子。Picaso 要小很多
    2.推送,统计,三方登录,微信支付,地图,这个没法删。但是优化了一下 so 适配CPU的数量。

经过了这些工作后(可能有遗漏,时间太久记不太清了),老板还让我优化 Apk 大小,我就实在是想不到其他办法了。而且我把网上能搜到的关于 Apk 优化的文章基本都看了,只要是能用的都会去试一下。但除了图片以外的优化都收效甚微。

三、灵光一闪

我把 Apk 传到 nimbledroid.com 上进行了分析,发现其中最占体积的就是【百度地图】了,足足占了 6M 多。但是我们作为 O2O 产品怎么可能没有地图呢?这是产品经理也不会同意的啊。于是我苦思冥想,采取了曲线救国的方式,干掉了百度地图,最终将那个版本的推广 Apk 包减小至仅有 3.34M。(由于已经离职,下图就不显示App名称了,除非有广告费,哈哈哈~)

《Android快速实现地图功能(不仅快!而且小!)》

思路很简单,就是用 JS 的地图替换了原生的地图。因为我分析了一下地图在这个 App 的功能占比,其实算是一个比较弱的功能,用户要想看到地图页面,必须经历以下的流程。

《Android快速实现地图功能(不仅快!而且小!)》
《Android快速实现地图功能(不仅快!而且小!)》 在App中的体验就是这样的↑↑↑

如上图所示,这个页面的层级比较深,而且根据前面几个版本的页面统计数据来看,确实很少有用户点到这个界面来。但是又不能没有这个功能,所以最终采取了这样折中的办法。性能怎么样呢?再来个图给大家看下吧。

《Android快速实现地图功能(不仅快!而且小!)》

我觉得性能还是可以接受的,虽然不如原生加载的快,但是我很满意了,因为我把安装包缩小了(用到的导航功能是跳转外部地图)终于可以交差了,而且产品经理和老板都没有看出和之前地图的差别来,只是觉得这个小伙子还挺屌的,真的给搞到只剩下3M了(嘿嘿~)。

四、代码实现

相比集成原生地图,集成 JS 地图简直就是不能再更简单了!! 不用下载烦人的 jar 包,不用考虑 so 文件的兼容。而且我觉得 JS 地图只有性能上不如原生,在功能上貌似还要更丰富一点。当然这里只是用于简单的地图展示和添加一个 Marker,更多功能可以自行探索。

但是最开始集成的时候我还是遇到了坑,刚开始使用的是百度的 JS 地图,但是发现在通过 Native 代码调用 JS 代码设置 Marker 的时候,百度总设置失败。网上查了很久,总觉得步骤方法都没有错,但是就是不行,正当我打算放弃这个念头的时候,想起来不是还有高德地图的么,于是试了一下果然就行了。

先大概说一下步骤:

  1. 到开发者平台申请 JS 地图的秘钥
  2. 在 assets 目录下创建一个离线的 html 页面
  3. 在 WebView 中加载该离线页面
  4. 通过 Native 调用 JS 方法,在地图上添加 Marker 图标

第一步就不用我说了吧,直接从第二步开始吧。【2】在 assets 目录下创建一个离线地图 html 网页【amap.html】,代码如下↓↓↓,注意看注释!!这里可能需要我们会一点 HTML 和 JS 的知识。速成就好了,只要明白一个 html 页面是如何搭建起来的就行。

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <title>基本地图展示</title>
    <link rel="stylesheet" href="http://cache.amap.com/lbs/static/main1119.css"/>

    <style type="text/css"> html,body{ width:100%; height:100%; } #container{height:600px;} </style>
    <!--<script src="http://cache.amap.com/lbs/static/es5.min.js"></script>-->
    <script src="http://webapi.amap.com/maps?v=1.3&key=这里填写你申请的 key"></script>
    <!--<script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script>-->
</head>
<body>
<div id="container"></div>

<script> var map = new AMap.Map('container', { resizeEnable: true, zoom:14, center: [104.065794,30.657483] }); //提供JS方法,让webview调用,添加marker function addMarker(lng,lat) { map.setZoomAndCenter(14, [lng, lat]); marker = new AMap.Marker({ //指定 Marker 的样式 icon: "http://webapi.amap.com/theme/v1.3/markers/n/mark_b.png", position: [lng, lat] }); marker.setMap(map); } </script>
</body>
</html>复制代码

【3】然后创建一个带 WebView 控件的 Activity 页面,在代码中将该 WebView 的 setJavaScriptEnabled() 方法设置为 true,然后通过 webview 加载 asstes 中编写好的离线地图 amap.html 文件。

mWebView.loadUrl("file:///android_asset/amap.html");复制代码

【4】最后在 JS 地图上设置 Marker 就行。这里涉及到了 Native 调用 JS 代码,不熟悉的可以搜索一下。

mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                //调用JS方法,将商家坐标设置到地图上
                mWebView.loadUrl("javascript:addMarker(" + shopLng + "," + shopLat + ")");
            }
        });复制代码

五、结语

这个 App 是一年多以前写的了,因为最近在学习 React Native,就突然回想起了那次通过 JS 解决问题的经历。 所以写出来和大家分享一下。其实还有很多业务可以通过这种思路去解决,但是通过 WebView 调用 JS 代码毕竟还是存在性能上的局限性,所以才会出现像 RN 这样的技术。恩…看来还是要早点把 RN 学好才行!哈哈~

看完点个关注呗!我有个 RN 群就缺你这样的人才。早点来吧~
公众号回复 RN ,就送你入群“邀请码”。你想啥呢?我这是正经邀请码哈!

文章看完了,欢迎关注我的公众号【aMarno】。近期主要分享 React Native 技术!(偶尔也会闲扯淡)

《Android快速实现地图功能(不仅快!而且小!)》

    原文作者:Android
    原文地址: https://juejin.im/post/58bf9b54da2f600056966c74
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞