PhoneGap/Cordova FileTransfer is blocking Enyo (1) surface

edited March 2012 in Packaging Apps
I've got a problem with Enyo 1 and PhoneGap. I could not find anything with google about that, any help would be appreciated.

I've got a kind which fetches data from the web and saves it to the local file system. The fetch method is called on deviceready and - as this data ist not required to display the home pane - the app is displayed at the same time. Although the app is visible, i am not able to navigate until all files have been loaded. PhoneGap seems to block any input until the file transfer has finished.

In this example below i've reduced the code to a minimum, in the real app more than 100 files are fetched (at least on the first app launch) so thats a really big problem for me:
enyo.kind({

	name: 'service.Whatever',
	kind: enyo.Component,

	url: 'http://example.com/path/to/the/files/',
	path: 'localfolder/',
	xmlFile: 'foobar.xml',
	previewFile: 'preview.jpg',

	fetch: function() {
		var that = this,
			fileTransfer = new FileTransfer();

		window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, that.fetchFailed);

		function gotFS(fileSystem) {
			fileSystem.root.getDirectory(that.path, {create: true}, gotLocalDir, that.fetchFailed);
		}

		function gotLocalDir(dirEntry) {
			// fetch xml file
			fileTransfer.download(
				that.url + that.xmlFile,
				dirEntry.fullPath + '/' + that.xmlFile,
				gotXml,
				that.fetchFailed
			);

			// fetch preview image
			fileTransfer.download(
				that.url + that.previewFile,
				dirEntry.fullPath + '/' + that.previewFile,
				null,
				that.fetchFailed
			);
		}

		function gotXml(file) {
			var reader = new FileReader();

			reader.onloadend = function(evt) {
				that.setupData(evt.target.result);
			};

			reader.readAsText(file);
		}
	},

	setupData: function(xml) {
		// parse xml var if its a string
		if (typeof xml === 'string') {
			var parser = new DOMParser();
			xml = parser.parseFromString(xml, 'text/xml');
		}

		// save data as javascript object
		this.owner.setData('somekey', Xml.getObject(xml));
	},

	fetchFailed: function(error) {
		enyo.warn(error);
	}

});
I thought the calls to the file system will be async and should not block anything. My first suggestion was the huge amount of files, but it's also blocking if i just fetch a few.

Any ideas about that?

Comments

  • On which platform are you running PhoneGap?
  • Oh sorry i forgot to mention that. This is currently running on iOS 5+ but should be portet to Android (and as soon as it is switched to Enyo 2 also on Windows Phone).
  • I don't know how big the data files you're grabbing are, but my first thought is that the DOMParser can be pretty slow to operate, as well as the memory allocations that could be happening with the this.owner.setData line. Perhaps using enyo.nextTick() or enyo.asyncMethod() to parse and store the data so it's not happening in the same system tick as everything else might help.

    My second thought, is how are you calling these functions? Another idea would be to make this a enyo.Service kind, as Service is designed to wrap async functions.
  • This actually was an Enyo service, but as i wanted to save the files to the local file system, i changed it to use the PhoneGap file API. The fetch method is only called once on the first launch as soon as the deviceready event is fired or on resume after a timeout of 7 days.

    I tried both, nextTick and asyncMethod, but that does not change anything. The setupData ist only called once as soon as the XML file is loaded, but the surface gets locked as long as files are fetched, not while the setupData runs.

    Most of the files are preview images used for something similar to a gallery.
  • OK, given the way PhoneGap works, the file calls are async, but not on a separate thread. They run after the event loop exits, but they block the WebKit instance from running until they're finished.

    You'll probably find better solutions for this over on the PhoneGap mailing list at http://groups.google.com/group/phonegap.
  • Ok, that makes sense, thank you for figuring that out. Obviously it has nothing to do with Enyo and can only be changed by changing the way PhoneGap handles the file requests.

    As a quick solution i will split loading and place a scrim in front of it, then i'll see what the PhoneGap folks has in mind about this.
  • I am running into the same issue. Did you ever contact the PhoneGap folks? If so, what did they have to say about it and is a fix on the way?
  • Sorry, i was off over easter.

    No, unfortunately i did not. I could not find a forum or contact email, only those ugly Google Group (sorry i don't like it). The bugtracker is deactivated on github, maybe it's a bit of confusion because of the move to apache. Feel free to contact them, i'm also still interested and would appreciate a solution, it's just low priority for me now.
  • The google group IS the bug-tracker and forum. Posting a new discussion there would be the fastest way to get a reply from them. I also plan to use this API in the future so I'd be interested to know about any response you receive.
  • Shortly after posting, I implemented a fix and sent a pull request. The update should be available in Cordova 1.6.0 when that is released. Or if you don't want to wait you can pull from the apache git, run make from the console, then open the dmg file it creates under dist and follow the upgrade instructions.
Sign In or Register to comment.