- 本文為 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名稱了,除非有廣告費,哈哈哈~)
思路很簡單,就是用 JS 的地圖替換了原生的地圖。因為我分析了一下地圖在這個 App 的功能佔比,其實算是一個比較弱的功能,使用者要想看到地圖頁面,必須經歷以下的流程。
如上圖所示,這個頁面的層級比較深,而且根據前面幾個版本的頁面統計資料來看,確實很少有使用者點到這個介面來。但是又不能沒有這個功能,所以最終採取了這樣折中的辦法。效能怎麼樣呢?再來個圖給大家看下吧。
我覺得效能還是可以接受的,雖然不如原生載入的快,但是我很滿意了,因為我把安裝包縮小了(用到的導航功能是跳轉外部地圖)終於可以交差了,而且產品經理和老闆都沒有看出和之前地圖的差別來,只是覺得這個小夥子還挺屌的,真的給搞到只剩下3M了(嘿嘿~)。
四、程式碼實現
相比整合原生地圖,整合 JS 地圖簡直就是不能再更簡單了!! 不用下載煩人的 jar 包,不用考慮 so 檔案的相容。而且我覺得 JS 地圖只有效能上不如原生,在功能上貌似還要更豐富一點。當然這裡只是用於簡單的地圖展示和新增一個 Marker,更多功能可以自行探索。
但是最開始整合的時候我還是遇到了坑,剛開始使用的是百度的 JS 地圖,但是發現在通過 Native 程式碼呼叫 JS 程式碼設定 Marker 的時候,百度總設定失敗。網上查了很久,總覺得步驟方法都沒有錯,但是就是不行,正當我打算放棄這個念頭的時候,想起來不是還有高德地圖的麼,於是試了一下果然就行了。
先大概說一下步驟:
- 到開發者平臺申請 JS 地圖的祕鑰
- 在 assets 目錄下建立一個離線的 html 頁面
- 在 WebView 中載入該離線頁面
- 通過 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 ,就送你入群“邀請碼”。你想啥呢?我這是正經邀請碼哈!