这种形式就是业务开发知道Native的hotel有icon.png的静态资源,便直接Native读取了,但是后来我觉得这种方案不太好,谁知道哪次更新Native中就没有这个包了呢?那个时候岂不是代码就直接报错了,所以最后我们决定我们所有的静态资源一定要过http,因为:
很多业务最初开发的时候都是直接使用浏览器开发或者Native直连url开发,这种时候就能保证所有的静态资源的地址不会错
在正式上线后,我们可能有一部分公共资源内嵌,这个时候便需要一定机制让Native返回本地文件:
Native会拦截所有的Webview请求,如果发现某个资源请求本地也存在便直接返回
所以这里的症结点是Native如何过滤请求,首先,Native只拦截某些域名的请求,因为我们本地资源都一定会有一个规则,拿到请求后,我们会匹配这个规则,比如说,我们会将这个类型的请求映射到本地:
//===>> file ===> flight/static/hybrid/icon-search.png
Native会直接去flight目录寻找是否有这个文件,如果有就直接返回了,但是我们这里会有一个忧虑点:
这种拦截所有请求的方法再检查文件是否存在是否会很耗时
因为我并不能肯定,于是让Native同事做了一个实验,检查100个文件本地是否存在,耗时都在10ms以内。
关于读取Native缓存,我们也可以使用前端构建工具直接以频道为单位生成一个清单,然后Native就只对清单内的请求做处理,但是这里会多一步操作,出错的几率可能增大,考虑的全部拦截的耗损不是很大,于是我们采用了全部拦截的方案,这里简单说下Native的实现方案,具体各位在代码中去看吧:
实现方案这里IOS与Android实现大同小异,这里直接放出代码各位自己去研究吧:
PS:这里是测试时候的代码,最后实现请看git里面的
1 class DogHybirdURLProtocol: NSURLProtocol { func canInitWithRequest(request: NSURLRequest) -> Bool { 4 if let url = request.URL?.absoluteString { 5 if url.hasPrefix(webAppBaseUrl) { 6 let str = url.stringByReplacingOccurrencesOfString(webAppBaseUrl, withString: "") ) ) 9 if tempArray.count == 2 { 10 let path = MLWebView().LocalResources + tempArray[0] 11 let type = tempArray[1] 12 if let _ = NSBundle.mainBundle().pathForResource(path, ofType: type) { ) ) ) } 18 } 19 } 20 } } func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest { 25 return request 26 } func startLoading() { 29 dispatch_async(dispatch_get_main_queue()) { 30 if let url = self.request.URL?.absoluteString { 31 if url.hasPrefix(webAppBaseUrl) { 32 let str = url.stringByReplacingOccurrencesOfString(webAppBaseUrl, withString: "") ) ) 35 if tempArray.count == 2 { 36 let path = MLWebView().LocalResources + tempArray[0] 37 let type = tempArray[1] 38 let client: NSURLProtocolClient = self.client! 39 if let localUrl = NSBundle.mainBundle().pathForResource(path, ofType: type) { type { : : : : : : } 60 let fileData = NSData(contentsOfFile: localUrl) 61 let url = NSURL(fileURLWithPath: localUrl) ) 64 client.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed) 65 client.URLProtocol(self, didLoadData: fileData!) 66 client.URLProtocolDidFinishLoading(self) 67 } 68 else { ) 70 } 71 } 72 } 73 } 74 } 75 } func stopLoading() { 78 79 } 80 81 }
IOS其实这里优点已经非常明显,业务写代码的时候压根不需要考虑文件是否需要本地读取,Native也可以有一个开关轻易的配置哪些频道需要读取本地文件: