2016-07-20 25 views
2

考慮下面的代碼段,其提取一個RSS饋送,然後顯示圖像內作爲其循環永遠幻燈片:如何控制QML中HTTP資源的緩存?

import QtQuick 2.2 
import QtQuick.XmlListModel 2.0 

Rectangle { 
    id: window 
    color: "black" 
    width: 800 
    height: 480 

    PathView { 
     anchors.fill: parent 

     highlightRangeMode: PathView.StrictlyEnforceRange 
     preferredHighlightBegin: 0.5 
     preferredHighlightEnd: 0.5 
     highlightMoveDuration: 500 
     snapMode: PathView.SnapOneItem 
     pathItemCount: 3 // only show previous, current, next 

     path: Path { // horizontal 
      startX: -width; startY: height/2 
      PathLine{x: width*2; y: height/2} 
     } 


     model: XmlListModel { 
      source: "http://feeds.bbci.co.uk/news/business/rss.xml" 
      query: "/rss/channel/item" 
      namespaceDeclarations: "declare namespace media = 'http://search.yahoo.com/mrss/';" 
      XmlRole { name: "image"; query: "media:thumbnail/@url/string()" } 
     } 


     delegate: Image { 
      width: PathView.view.width 
      height: PathView.view.height 
      source: image 
      fillMode: Image.PreserveAspectCrop 
     } 


     Timer { // automatically loop through the images 
      interval: 1000; running: true; repeat: true; 
      onTriggered: { 
       parent.incrementCurrentIndex() 
      } 
     } 


     Timer { 
      interval: 600000; running: true; repeat: true; 
      onTriggered: parent.model.reload() 
     } 

    } 
} 

此代碼從網絡加載的圖像,因爲它需要它們。但是,一旦圖像不再顯示,它會丟棄數據。下一次,圖像周圍的幻燈片循環將從網上重新加載。因此,只要代碼正在運行,代碼就會每秒鐘點擊一次遠程圖像服務器,每次下載50-300KB。

該代碼在內存不足的嵌入式系統上運行,因此通過在代理不在路徑上時保留解碼圖像數據不是一種選擇。

取而代之的是緩存應該在HTTP級別完成,存儲原始下載的文件。因此它應該服從HTTP緩存控制頭。

緩存應該只在內存中完成,因爲系統只有一個小的閃存盤。

我該如何在Qt中實現這個功能?我認爲它會涉及C++代碼,這很好。

+1

我會通過'QQuickImageProvider'來做到這一點。假設你註冊你的提供者名字爲myprovider。所以圖像源將是:'source:「image:// myprovider /」+ image'。提供者獲取路徑,加載圖像並返回圖像對象本身。並根據需要緩存它。 – folibis

+0

順便說一句,'圖片'項目有[緩存](http://doc.qt.io/qt-5/qml-qtquick-image.html#cache-prop)屬性。另外[this](http://doc.qt.io/qt-5/qquickimageprovider.html#image-caching)鏈接可能會有用。 – folibis

+0

@folibis您提到的任何內容都不適用於HTTP資源。 –

回答

1

要控制QML獲取網絡資源時的緩存行爲,您可以繼承QQmlNetworkAccessManagerFactory的子類並使其創建帶有附加緩存的QNetworkAccessManagers。然後,你的工廠連接到您的QQmlEngine

class MyNAMFactory : public QQmlNetworkAccessManagerFactory 
{ 
public: 
    virtual QNetworkAccessManager *create(QObject *parent); 
}; 

QNetworkAccessManager *MyNAMFactory::create(QObject *parent) 
{ 
    QNetworkAccessManager *nam = new QNetworkAccessManager(parent); 
    nam->setCache(new QNetworkDiskCache(parent)); 
    return nam; 
} 

int main(int argc, char **argv) 
{ 
    QGuiApplication app(argc, argv); 
    QQuickView view; 
    view.engine()->setNetworkAccessManagerFactory(new MyNAMFactory); 
    view.setSource(QUrl("qrc:///main.qml")); 
    view.show(); 

    return app.exec(); 
} 

緩存必須實現QAbstractNetworkCache接口。 Qt有一個內置的緩存類型,QNetworkDiskCache,顧名思義,它將緩存保存到磁盤。沒有用於內存緩存的內置類,但通過使用QHash來存儲URL,數據和元數據將很容易實現。

+0

這不適用於使用WebView的Qt 5.9+ – madduci