以前看到簡書
Android客戶端使用的編輯器,甚是喜歡,它的優雅以及高性能的特色讓我愛不釋手,很想本身也去作一個。
此前實現過一個在Android上的Markdown編輯器
可是界面以及所見即所得
的效果很是很差看,因此一直耿耿於懷。java
而後冒昧看了下簡書
的佈局系統,看見了幾個奇怪的類,包括相似XWalkContentView
,因而Google了下,就查到了CrossWalk
這個hybrid
框架了。第一眼並不以爲它有啥不同,覺得是一個Cordova
的輪子。後來細看,發現是自個兒編輯了整個Chrominum
,屌屌屌!git
運行個demo,wrapper了一個http://sf.gg 發現體驗真的是不錯啊,webview性能到這個水平心裏都寬慰了,可是爲什麼安裝速度那麼慢呢?一看apk大小,足足有40M+
,感受天都要塌了。SegmentFault for Android
客戶端才3.03M
,我要是包上這玩意,估計就沒多少人下了吧。。。而後又看看簡書
,整個apk大小才8M,在啓動編輯器的時候,提示須要下載編輯器,下載了一會,而後再打開。頓時就明白了,看來它的庫是從外部載入的,記得之前看到過從外部加載動態連接庫
想一想非常簡單,因而入坑了。github
好嘛,我把so文件先不放進apk中,讓apk裝好以後,放入/data/data/<app>/lib
目錄下,啓動app,直接crash。
看日誌入下:web
DavlikDexClassLoader Unsatisfied Link library['/xxxx/xxx.apk', '/vendor/lib', '/system/lib']app
一看這個路徑,淚奔了,原來library path
只有三個路徑下去檢查,算了,咱們不是有System.load
和System.loadLibrary
函數麼,直接調用唄,因而我就先暫時把絕對路徑給寫了下來,直接調用System.load
函數。框架
再次啓動,發現CrossWalk
報Shared Library should use SharedXWalkView
。可是使用SharedXWalkView
有許多的限制,好比須要安裝一個CrossWalk Runtime
的apk,奇怪了,它怎麼知道我是用Shared Library
的呢?並且簡書也沒有說要安裝apk啊。編輯器
因而我繼續研究,開始看CrossWalk
的源碼,找到ReflectionHelper
這個類裏面有一行代碼shouldUseLibrary()
,它會去調用System.loadLibrary()
若是沒有報異常,則返回false
,不然返回true
。函數
咱們知道System.loadLibrary
這個函數,會去java.library.path
這個環境變量的路徑下面尋找庫,而Android
是不容許咱們更改這個環境變量的值的,就致使CrossWalk
認爲並無加載它的runtime
而去開啓Shared
模式。佈局
OK,知道怎麼解決就方便了,首先,咱們要把so
文件放入到/data/data/<app>/
下的任意路徑,由於咱們的apk有這個權限在這裏放東西,而後使用System.load
加載這個so
庫,最後使用反射的方式欺騙CrossWalk
框架,告訴它咱們的類庫已經加載完畢。性能
咱們仔細研究下它的源碼,發現有幾個標誌位須要更改,具體代碼以下:
System.load(libPath); try { LibraryLoader loader = LibraryLoader.get(1); Class c = Class.forName("org.xwalk.core.internal.XWalkViewDelegate"); Field field = c.getDeclaredField("sLibraryLoaded"); field.setAccessible(true); field.setBoolean(null, true); field.setAccessible(false); field = LibraryLoader.class.getDeclaredField("mLoaded"); field.setAccessible(true); field.setBoolean(loader, true); field.setAccessible(false); PathUtils.setPrivateDataDirectorySuffix("xwalkcore"); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (ProcessInitException e) { e.printStackTrace(); }
只要把以上的類中的標誌位更改掉,那麼CrossWalk
就認爲庫已經加載成功了。