2016-07-20 17 views
2

Betrachten Sie das folgende Stück Code, die einen RSS-Feed holt und zeigt dann die Bilder in Form einer Diashow, die für immer Schleifen:Wie kann das Caching von HTTP-Ressourcen in QML gesteuert werden?

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() 
     } 

    } 
} 

Dieser Code lädt die Bilder aus dem Internet, wie es sie braucht. Sobald ein Bild jedoch nicht mehr angezeigt wird, werden die Daten verworfen. Wenn die Diashow das nächste Mal wiederholt wird, wird das Bild erneut aus dem Internet geladen. Daher wird der Remote-Image-Server einmal pro Sekunde so lange mit dem Code infiziert, wie er ausgeführt wird, wobei jedes Mal 50 bis 300 KB heruntergeladen werden.

Der Code wird auf einem Embedded-System mit wenig RAM ausgeführt. Die decodierten Bilddaten zwischenzuspeichern, indem der Delegat beibehalten wird, wenn er sich nicht auf dem Pfad befindet, ist keine Option.

Stattdessen sollte das Caching auf HTTP-Ebene erfolgen und die ursprünglich heruntergeladenen Dateien speichern. Es sollte daher den HTTP-Cache-Steuerheadern folgen.

Die Zwischenspeicherung sollte nur im Speicher ausgeführt werden, da das System nur eine kleine Flash-Disk hat.

Wie kann ich dies in Qt implementieren? Ich nehme an, es wird C++ Code beinhalten, das ist in Ordnung.

+1

Ich würde das durch 'QQuickImageProvider' tun. Angenommen, Sie registrieren Ihren Provider mit dem Namen 'myprovider'. Die Bildquelle lautet also: source: image: // meinProvider/+ image. Der Anbieter erhält den Pfad, lädt ein Bild und gibt das Bildobjekt selbst zurück. Und so Cache wie benötigt. – folibis

+0

Btw, 'Image'-Objekt hat die Eigenschaft [Cache] (http://doc.qt.io/qt-5/qml-qtquick-image.html#cache-prop). Auch der Link [this] (http://doc.qt.io/qt-5/qquickimageprovider.html#image-caching) könnte nützlich sein. – folibis

+0

@folibis nichts, was Sie erwähnt haben, ist in irgendeiner Weise auf HTTP-Ressourcen anwendbar. –

Antwort

1

Um das Caching-Verhalten zu steuern, wenn QML eine Netzwerkressource abruft, würden Sie QQmlNetworkAccessManagerFactory ableiten und QNetworkAccessManagers mit einem angehängten Cache erstellen. Dann legen Sie die Fabrik zu Ihrem 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(); 
} 

Caches die QAbstractNetworkCache Schnittstelle implementieren müssen. Qt hat einen eingebauten Cachetyp, QNetworkDiskCache der, wie der Name schon sagt, den Cache auf Platte speichert. Es gibt keine integrierte Klasse für In-Memory-Caching, aber es wäre ziemlich einfach, eine zu implementieren, indem Sie eine QHash verwenden, um die URLs, Daten und Metadaten zu speichern.

+0

das funktioniert nicht mehr auf Qt 5.9+ mit WebView – madduci