Fetch images asynchronous from url in unity3d - memory

I am making a game in which I need to integrate Facebook leader-board and facebook friends invitation like in subway surfer. I used official facebook sdk and got it done. But the approach I am following is not efficient.
My friend invite screen has its own UI so I could not use the default popup comes with facebook SDK.
I fetch all the friends list from graph api It provides me the list of all IDs of users . But I needed to get name and images of friends to show in a scroll list . I am fetching the images from url asynchronously but whenever I try to fetch the image my scroll list hangs up . here is my code
IEnumerator start ()
{
url ="http://profile.ak.fbcdn.net/hprofile-ak-prn2/t5/1116929_100003613987476_290892640_q.jpg";
WWW www = new WWW(url);
yield return www;
var texture = www.texture;
this.gameObject.GetComponent<UITexture>().mainTexture = texture;
}
I am using coroutines, but I dont know why my scroll hang up on scrolling if these are asynchronous ? The code is been taken form here . I have checked Threading but www can not be used in threads. I just want to smooth my scrollview which I made by using NGUI sdk during image fetching.
Problem 1 - How can I make smooth scrolling by asynchronous image download simultaneously.
Problem 2 - I am loading each image into UITexture of NGUI, which I instantiate at run time. But if one have 200 or above friends then my app's memory reach at apex point and eventually app crashes. Is there any other way to load large number of images so that they take reasonable memory .
Scroll is working smoothly during web call on editor but not on device (iOS). Why ?
Please guys help me to smooth my scroll view and memory issue. Any help shall highly be appreciated. Thakks :)

This is a common problem on devices for any list that has more than 50 items that include images. You need to control two things: initializing list items and downloading assets.
You do not need to load everything at once and display them. I would recommend breaking this down into three parts:
1. Store friend list data
Fetch all the user's Facebook friends and store it in a list. This does not include downloading the profile pictures, only the basic information and the URL of their profile picture. We will download the picture at a later step.
2. Pool list items
Don't create more than triple the list items you can display at any given time. While scrolling, you'll simply reuse the ones already created like so:
You should only need to do the third step in that picture only when the user has lifted his finger and the list has enough momentum to continue scrolling. Otherwise you should have enough items loaded in memory to not require this when the user simply drags the list.
When moving a list item either at the end or the beginning (depending on the direction of the scroll) you should load the friend's data. You still do not load profile pictures at this step.
3. Queuing image requests
You can use Unity's OnBecameVisible method to figure out when an item is currently visible. But generally you'll need a manager that keeps track of what items are visible at any given moment.
Every time the scroll list has no momentum and the user is not dragging it, you queue up requests to fetch the images for the items that are currently visible. This should be handled by a different manager that does the following:
Keeps N most recent profile pictures in memory to avoid loading them every time
Checks to see if the image is already downloaded by using LoadFromCacheOrDownload as Roberto suggested.
Makes sure that the item the request was made for is still visible before setting the texture (otherwise it keeps the image in memory)
Of course, this is very high level. There are many things to implement here and in many different ways. But I hope you get the idea.

I was thinking about this when I asked about starting many coroutines at the same time.
Well you just can't load them all at the same time and expect the app to run smoothly, the hardware is just not able to handle this.
You can made a loading screen or something similar where the user will have to wait to see/use the scroller (though I've never seen a game doing this for loading Facebook pictures) or you will have to give up in showing them all at the same time and create a pool of a small number of WWW connections that you can use at the same time, that is, limit the number of images being loaded at the same time, and only start loading a new image when one has finished.
Now one thing that can certainly speed things up - not in the first time that you run it, but subsequent runs - is to use WWW.LoadFromCacheOrDownload() instead of new WWW(). This method will store the pictures that were downloaded in the past and load them instead of redownloading. This is how every Unity game I've ever seen do integration with Facebook.

Related

Handling cache right?

I’m developing an application.
I have came to the point where I can’t decide what’s a good caching strategy:
The app shows restaurants nearby with images and videos:
If you go to a restaurant it pops up. If you go away, it disappears. If you go there again, it appears again.
Therefore I cache the photos with SDWebImage and the videos with a custom made video cacher.
So in a normal case when the user is walking in the city, the app downloads lots of images and videos, which may or may not be seen again.
I don’t know how other applications are working, but I made a function that deletes all image-video cache (that are not visible anymore) every 5 minutes.
Is that a good straregy? Or would it be better not to delete manually old photos-videos cache, IOS does it by itself?

iOS update number of views for a video file from server automatically

Video file loaded from server.
Video file has (number of views).
If any application user views that particular video the number of views should be incremented and updated.
If I am viewing that video and another user viewed that particular video, is it possible to automatically update the number of views without any user action.
If there is any possible solution AND is a good practice, what is the best approach to implement this using Objective-C?
I've seen some iOS apps updating the number of views for videos which keeps incrementing every second even if the internet connection is disabled, so I think that is a fake counter.
So I was going through a function call every 5 seconds to check the number of views for each video from the server, but I am not sure if it is a good practice, any suggestions?
Websockets are usually great for keeping things updated without any user interaction.
Take a look at this iOS framework: https://github.com/square/SocketRocket
There are different approaches to update the view-counter, the safest is if you put a REST-server "in front of the video file", which returns the video file and at the same time updates the number of views in your database.

How to handle displaying, searching, and filtering large volumes of images in an iOS app?

I have a webservice that acts as a form of a digital asset manager. Some of our users have THOUSANDS of images stored in their account. We want to give them an iPhone app that lets them access these images. We can use infinite scroll but we would like some form of a table of uicollectionview segmented by dates with a side index list that they can scroll through and jump to. To do that we would need to download ALL of their images into a collectionview, which seems insane.
How do others handle displaying, searching and filtering large volumes of images?
Typically when large amounts of data needs to be downloaded from a web service (or filesystem) the key is not to do it all at once, but to partition it into manageable pieces which you load and unload as needed. There is no one way to do this, but that is the general idea.
To manage this process it can be helpful to download a complete index that describes all the content (like a json list of image urls) without downloading every image or piece of data in the database (but not necessary - this won't work with millions of entries). This allows you to search and navigate through content without requiring huge downloads.
In your question it sounds like your images are grouped somewhat by date ranges. A possible procedure you could explore could be something like:
Download an index of all images with their associated dates and load this into memory. (In the thousands this should be no problem).
images : [
{
url: "http://someurl/image.png",
name: "Great Image!",
date: "12/3/15"
// possibly include more data like search tags...
},..
]
Begin downloading the initial set of images associated with most recent date range and display them as they complete.
When the user selects a new date range or scrolls of the page, show placeholder image tiles in the collection view. Start downloading the new images asynchronously and display them as they arrive.
Unload images from the previous date range from memory. (You could keep a cache in the filesystem).
Repeat as the visible area changes.
On iOS I usually use AFNetworking (Or AlamoFire for Swift) to handle asynchronous network requests.

Downloading lots of Images in an iPad App

I am working on an app where I need to download lots of images locally (so that they are available offline). The number of images can be 100 - 10,000. Each image may vary from 100K- 250K
I can do this via a NSOperationQueue and I have the code to make this work already but this question is more of a conceptual nature. I am not sure what is the best approach to take here.
1) Do I download all images as soon as the user logs in for the first time ? Based on the number of images, this could take a long time and what if the user closes the app meanwhile. I understand there is a limit on the time that can be spent by a background process in this case? Honestly, I dont want to do anything in the background (ie when app is closed)
2) Do I download images when a particular category is selected by the user? If a category has 800 images, then what happens if the user selects another category before all of those 800 images are finished downloading? I can always start threaded downloaded but will the thread keep on running if the user selects another category ?
3) Put something in "Settings" to let the user decide this themselves. Something like "Total Images: 8000" Images Available : 2000 and a button to say "Download All" which would display a UIProgressView of what's going on....so the user will probably wait till it's all done.
Or some other approach?
Thoughts?
As far as I understand from your description, including comments, I think that the best approach would be downloading all of your images in a thread and make the download process resumable. In this way, you are going to mirror a remote database of images for offline use.
What this entails is:
you keep track of which images you have downloaded;
each time the app starts/resumes, you start the downloading thread exactly from where you left;
you should also provide a mechanism so that the user is suitably informed when he is trying to access an image which has not been downloaded yet, but I think this should be no problem (you might also provide a progress indicator somewhere).
I would only download the image when the user actually needs to do something with the image. Your users will hate you if you download all the images upfront. :)

Best way to load distant data

I'm currently developping an iPhone app and need your opinion.
First, I am developping it for a Football (soccer) Club. It contains many tabs (at least these ones) :
News (Where I am displaying last news posted, obviously)
Shop (Where the user can buy stadium seats, and maybe various goodies)
Don't know yet exactly (But it will be related to Facebook/Twitter or stuff like that)
For every of theses tabs, I need to download XML data (using initWithContentOfURL). Right. But, that's where my problem is. Should I :
Load every needed xml pages at application start-up, and display a nice loading screen ?
Load every needed xml pages at the exact instant the user needs it in the application ?
In the first case, I get a slower application startup, but then, a faster navigation between tabs.
In the second case, my application starts relatively faster (still needs to load News XML, that's the welcome tab), but switching between tabs won't be as fluent as the first case (only the first time the tab is opened, of course).
Any advice?
Take a look at ASIHttpRequest which does provide some pre built caching mechanisms for you that may be appropriate and generally make interacting with web services easier
Load only what you need when you need it.
Furthermore, I wouldn't use initWithContentsOfUrl. It's a synchronous call, and it will lock your app. Instead, use an NSURLConnection to get the data asynchronously.

Resources