PDA

View Full Version : Problem with carousel and lot's of pictures



flixmeplease
5 Jul 2010, 9:36 AM
Hi all,

i'am currently working on a mobile App for the iPad. In this app i'am using a carousel, to show a slideshow of images, located on a different server.

So the Problem is, i don't know, how many pictures i have to show in the carousel.
To fix this issue i'am adding on the fly new items in the carousel for every picture i receive from the server.

Source-Code (just the adding-part):


if (myCondition) {
...
carousel1.add({html: tempHtml}); // tempHtml is the generated HTML-code for setting up my image-tag
carousel1.doLayout();

tempImage = new Image();
tempImage.src = stringToUrl;

document.getElementById(idCounter).src = tempImage.src; // adding the source to the generated image-tag
...
}


This works fine.
But after adding a view images by this way, i get a crashed mobile Safari on my iPad:((. I think that browsers cache is overloaded.

I've tried to remove previous items from the carousel to free a little bit of memory, but it doesn't solve the problem.
So any idea what i can do to prevent these crashes?

kind regards

flixmeplease

TommyMaintz
5 Jul 2010, 1:53 PM
It might be another issue unrelated to memory on the iPad that we aren't aware of. Would it be possible to see the source code of the app so that we can investigate this further?

flixmeplease
5 Jul 2010, 11:42 PM
Hi Tommy,

thanks for your fast reply.
My source-code is based on the carousel-example and differs not much from it.

Lets see what we have :-?

- Index.js


var carousel1;

Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
layout: 'card',
indicator: false,
onReady: function() {

// Create a Carousel of Items
carousel1 = new Ext.Carousel({
defaults: { cls: 'cardtest' },
// Adding the first 5 items for precaching
items: [{
id: 'card-0',
html: '<img width="768px" height="939px" id="0" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0003.jpg&width=768&height=939" />'
},{
id: 'card-1',
html: '<img width="768px" height="939px" id="1" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0004.jpg&width=768&height=939" />'
},{
id: 'card-2',
html: '<img width="768px" height="939px" id="2" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0005.jpg&width=768&height=939" />'
},{
id: 'card-3',
html: '<img width="768px" height="939px" id="3" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0006.jpg&width=768&height=939" />'
},{
id: 'card-4',
html: '<img width="768px" height="939px" id="4" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0007.jpg&width=768&height=939" />'
}]
});
new Ext.Panel({
fullscreen: true,
layout: {
type: 'vbox',
align: 'stretch'
},
defaults: {
flex: 1
},
items: [carousel1]
});
}
});


So the only thing i have done here is to add 5 items with html-img tags.


- ext-touch-debug.js



// URL index
// i have to start with this index, because the url-index on the server starts with a 3, don't ask me why ...
var urlIndex = 8;
var idCounter = 5;

function setNext() {

stringToUrl = "http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F";

if(urlIndex <= 9) {
stringToUrl = stringToUrl + "000";
stringToUrl = stringToUrl + urlIndex;
}
else if (urlIndex > 9 && urlIndex <= 99) {
stringToUrl = stringToUrl + "00";
stringToUrl = stringToUrl + urlIndex;
}
else if (urlIndex > 99 && urlIndex <= 999) {
stringToUrl = stringToUrl + "0";
stringToUrl = stringToUrl + urlIndex;
}

stringToUrl = stringToUrl + ".jpg&width=768&height=939";

var tempHtml = "<img width='768px' height='939px' id='";
tempHtml = tempHtml + idCounter;
tempHtml = tempHtml + "' />";

carousel1.add({html: tempHtml});
carousel1.doLayout();

tempImage = new Image();
tempImage.src = stringToUrl;

document.getElementById(idCounter).src = tempImage.src;

tempImage = null;

urlIndex++;
idCounter++;
}


The setNext() function is called here:



...
onScrollEnd: function(scroller) {
var activeX = this.activeItemX,
deltaX = scroller.offset.x - activeX,
width = this.el.getWidth();


if (deltaX < 0 && Math.abs(deltaX) > width / 2) {
this.next();
setNext();

}

else if (deltaX > 0 && Math.abs(deltaX) > width / 2) {
this.previous();
}
...


nothing else is changed in this file.

Index.html is without any changes.

I know this code isn't realy cleaned up, i have to add some 'if's' and 'else' more to clean it a little, but this is my way to code, first the basic function and after that the cosmetic-stuff :D.

When i run this code on my mac in the safari everything works like it should. Only on the iPad after maybe 25 items added safari crashes.
Adding that numbers of items directly in the index.js and not on the fly results in the same, safari starts and after 1 second crashed.


Kind regards

flixmeplease

TommyMaintz
6 Jul 2010, 1:32 PM
First of all, I would highly advice not to just add code in the global namespace, especially not in ext-touch-debug.js. Also, you might want to bundle your functionality inside an extension of our components. For example, I moved the behavior that you want into a subclass called InfiniteCarousel. The following code works for me without crashing my iPad up until the point that there are no more images available on the server. You might want to implement logic in the InfiniteCarousel that removes the first items each time another item is added, and puts it back in when you navigate close to the first card again.



Ext.ns('Ext.ux');

Ext.ux.InfiniteCarousel = Ext.extend(Ext.Carousel, {
fetchThreshold: 1,

onCardSwitch : function(card) {
Ext.ux.InfiniteCarousel.superclass.onCardSwitch.call(this, card);

if (this.items.length - this.items.indexOf(card) <= (this.fetchThreshold + 1)) {
this.scroller.on('scrollend', function() {
var nextCard = this.fetchNextCard();
if (nextCard) {
this.add(nextCard);
this.doComponentLayout();
}
}, this, {single: true});
}
},

// Template method
fetchNextCard : function() {
return null;
}
});


Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
layout: 'card',
indicator: false,
onReady: function() {
// URL index
// i have to start with this index, because the url-index on the server starts with a 3, don't ask me why ...
var urlIndex = 8;
var idCounter = 5;

new Ext.ux.InfiniteCarousel({
fullscreen: true,
fetchThreshold: 2,
items: [{
id: 'card-0',
html: '<img width="768px" height="939px" id="0" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0003.jpg&width=768&height=939" />'
},
{
id: 'card-1',
html: '<img width="768px" height="939px" id="1" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0004.jpg&width=768&height=939" />'
},
{
id: 'card-2',
html: '<img width="768px" height="939px" id="2" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0005.jpg&width=768&height=939" />'
},
{
id: 'card-3',
html: '<img width="768px" height="939px" id="3" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0006.jpg&width=768&height=939" />'
},
{
id: 'card-4',
html: '<img width="768px" height="939px" id="4" src="http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F0007.jpg&width=768&height=939" />'
}],

fetchNextCard : function() {
var stringToUrl = "http://84.201.68.228:8080/fsi/server?type=image&source=onlinekat%2Fonlinekat_mm%2Ffsi-test%2FHeine%2F";

if (urlIndex <= 9) {
stringToUrl = stringToUrl + "000";
stringToUrl = stringToUrl + urlIndex;
}
else if (urlIndex > 9 && urlIndex <= 99) {
stringToUrl = stringToUrl + "00";
stringToUrl = stringToUrl + urlIndex;
}
else if (urlIndex > 99 && urlIndex <= 999) {
stringToUrl = stringToUrl + "0";
stringToUrl = stringToUrl + urlIndex;
}

stringToUrl = stringToUrl + ".jpg&width=768&height=939";

var tempHtml = '<img width="768" height="939" id="card-' + idCounter + '" ';
tempHtml += 'src="' + stringToUrl + '" />';

urlIndex++;
idCounter++;

return {html: tempHtml};
}
});
}
});

flixmeplease
6 Jul 2010, 11:06 PM
Wow... what a kind of superb support.
Mr TommyMaintz i have to thank you a lot.

So i'm going to use your code as a awesome base for my app ;)
And now its time for me to do the cosmetics :D

Again thanks a lot.

__Edit:

Hmpf i think i was a little euphoric ;)
So i copy/pasted your code, added it to a clean project (index.js) and getting the same problems again. After adding 31 images i get a crashed Safari.

Tried to fix the problem with:
- Adding a remove-function (removing the last card after adding a new card), results in pictures are no more displayed after 36 added (just empty cards). But i can slide to infinity, no crashes.

-Resizing the images to something really small (5 x 5 px) allows me to slide through all of them located on the server (70 and more).

I have no more further idea what the problem is. Especially you said, you can slide trough all the images on the server.

Any idea?

arpecop
11 Jul 2010, 5:26 PM
your help is extremely helpful, :-?
as the previous member I am completely lost with this , can you help me with feature that disables - 2 state so the load would not overheat /:) our devices

thanks

TommyMaintz
13 Jul 2010, 1:22 PM
Ok, I will see what I can do in terms of providing an example that does this. We are planning on extending our carousel to support dynamic loading of new cards, I'm just not sure if we can guarantee to have this included in the initial 1.0 release.

flixmeplease
15 Jul 2010, 4:15 AM
Hi all,

after a break i'am back :-)
At the first, it seems that this problem is a known issue coming from the memory management of the ipad.
By my experience after adding something like 6-7 mb of images, the application crashes or shows just empty image-boxes.

So for me i found 2 ways to get this problem 'fixed'.

1st:
If you only use a fixed value of image-tags (i tested it with 1 to 5) and never (re)move them from the DOM, just override the src of them, you can 'refresh' those with as much images as you want.
Using the add and remove function provided by the sencha-touch api you will run into an memory-crash.
In my opinion, this is not really a fix, because imho you have to add new items, to be able to slide in the carousel. Moving the img-Tag to a newly added empty div results in a memory-crash too.

2nd:
I added an iframe. There i placed my carousel. When the carousel slides to another card, i add a new item to it.
After adding a few of items (depends on how big the size of your images is) i reload the iframe with a parameter holding the current page to start from this after reload.
Reloading the iframe fixes the memory-crash. I can add as many images as i want.
But this even sounds not very clean to me.

So i wil go on and see what can be figured out.

Greets

jpadilla
19 Jul 2010, 12:49 PM
Hey flixmeplease,

Im also having this problem. The iframe idea could be a solution. Ive tried removing carousel items after loading new ones, but i still get black pages after a few images. Im using this with a UIWebView on an iPad App. If you find a nice solution to this please post us what you did! Kinda stuck with this

Thanks

flixmeplease
20 Jul 2010, 1:33 AM
Hi jpadilla,

as soon as i get a version running, i will post it here.
But for me it seems like a bigger problem, taking some days to fix.
At the moment i am trying to use canvas-tags instead of img-tags and the most important thing, a caching-strategy.
I can run to a lot of images with it but it has a horrible performance :-(.

Because you are using an UIWebView you must have some native code. Why you do not use a native Objectiv-C image slider? Its maybe the faster and easier way until the safari memory problem is fixed.

Greets.

ankuravlani
25 Aug 2010, 3:41 PM
Hi,

I am dynamically adding photos to carousel.

Ext.getCmp("photoCarousel").add({ html:'<img src="img url"/>'});
Ext.getCmp("photoCarousel").add({ html:'<img src="img url"/>'});

But my issue is is doesnt display the images even after

Ext.getCmp("photoCarousel").getLayoutTarget().repaint();
Ext.getCmp("photoCarousel").doLayout();
Ext.getCmp("photoCarousel").doComponentLayout();

But if i do a orientation change it automatically disaply the images. Any help is appreciated.

Thanks,
Ankur.