Android快速實現地圖功能(不僅快!而且小!)

Marno發表於2017-03-20
  • 本文為 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快速實現地圖功能(不僅快!而且小!)

相關文章