1. 程式人生 > >Android Webkit 派生資源載入流程

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渲染