Android Webkit 派生資源載入流程
以image為例解析image資源的載入過程:
1. HTMLImageElement被建立時在建構函式HTMLImageElement()中將HTMLImageElement物件傳遞給HTMLImageLoader創建出m_imageLoader
2. 第一次頁面初始化時或者image的src屬性發生改變時會呼叫HTMLImageElement的parseMappedAttribute方法
3. parseMappedAttribute判斷attrName ==srcAttr則呼叫m_imageLoader.updateFromElementIgnoringPreviousError();
4. 進而呼叫HTMLImageLoader基類ImageLoader中的updateFromElement方法
5. 在updateFromElement中用下面這句話向CachedResourceLoader申請CachedImage物件
newImage =document->cachedResourceLoader()->requestImage(sourceURI(attr));
CachedResourceLoader會更具快取的情況,從MemoryCache中找到之前的資源,如果沒有Cache可用則呼叫loadResource建立新的CachedResource物件。
6. loadResource並非只是建立CachedResource物件,並且呼叫CachedResource的load方法,並傳遞CachedResourceLoader物件,一個引數的load再呼叫4個引數load
1.resource->load(this); 2.virtual voidload(CachedResourceLoader* cachedResourceLoader) { load(cachedResourceLoader, false,DoSecurityCheck, true); } void load(CachedResourceLoader*, bool incremental, SecurityCheckPolicy,bool sendResourceLoadCallbacks); 3.void CachedResource::load(CachedResourceLoader*cachedResourceLoader, bool incremental, SecurityCheckPolicy securityCheck, boolsendResourceLoadCallbacks) { m_sendResourceLoadCallbacks =sendResourceLoadCallbacks; cachedResourceLoader->load(this,incremental, securityCheck, sendResourceLoadCallbacks); m_loading = true; } 又呼叫回CachedResourceLoader物件的load方法,這個CachedResourceLoader和建立CachedResource的是同一個物件, voidCachedResourceLoader::load(CachedResource* resource, bool incremental,SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks) { incrementRequestCount(resource); RefPtr<CachedResourceRequest> request= CachedResourceRequest::load(this, resource, incremental, securityCheck,sendResourceLoadCallbacks); if (request) m_requests.add(request); } 沒弄明白為什麼要這麼做。
7. CachedResourceLoader的load方法呼叫CachedResourceRequest的靜態方法load並將CachedResourceLoader物件傳入,建立CachedResourceRequest物件,
8. 呼叫ResourceLoaderScheduler::scheduleSubresourceLoad建立SubresourceLoader物件
9. 呼叫ResourceLoaderScheduler的scheduleLoad方法將SubresourceLoader加入清單列表中,並設定優先級別,如果優先順序足夠高就呼叫servePendingRequests開始下載
10. 呼叫 ResourceLoader::start
11. 呼叫 ResourceHandle::create建立ResourceHandle並呼叫ResourceHandle的start方法
12. 如果是android平臺呼叫的就是ResourceHandleAndroid.cpp中的ResourceHandle::start方法,再呼叫ResourceLoaderAndroid::start
13. WebUrlLoader::start 建立WebUrlLoader和WebUrlLoaderClient,在WebUrlLoaderClient中則會建立WebRequest
14. WebUrlLoaderClient的start方法,這裡會根據同步或非同步作不同的處理,非同步同步模式中都會建立NewRunnableMethod將WebRequest的start加入執行緒中執行,只是同步模式會等待完成後才退出函式
15 WebRequest的start會呼叫m_request的start方法,m_request是net::URLRequest物件,這個物件已經不是webkit中的物件,是chromium中的物件。
16. 從這裡開始就是chromium的流程了
17. Chromium接收到資料後呼叫ResourceLoader的didReceiveResponse
和didReceiveData,將資料交給SubresourceLoader CachedResourceRequest 處理。
18. 接收完資料後,回到ImageLoader的流程中,從CachedResourceLoader中申請到CachedImage物件後,
對比是否是新的物件,並做初始化處理,如下:
CachedImage* oldImage = m_image.get();
if (newImage != oldImage) {
if (!m_firedBeforeLoad)
beforeLoadEventSender().cancelEvent(this);
if (!m_firedLoad)
loadEventSender().cancelEvent(this);
m_image = newImage;
m_firedBeforeLoad = !newImage;
m_firedLoad = !newImage;
m_imageComplete = !newImage;
if (newImage) {
newImage->addClient(this);
if(!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER))
dispatchPendingBeforeLoadEvent();
else
beforeLoadEventSender().dispatchEventSoon(this);
}
if (oldImage)
oldImage->removeClient(this);
}
18. 最後一步呼叫renderImageResource渲染