1

I am wondering how Titanium handles images. If I were to load an image in a image view, then change the image in the image view to a local image, and then change the image back to the previous image would the image view need to download the previous image again?

Not sure how Titanium handles downloaded images, but I would think it does not cache them.

I was thinking i could create some off screen images and set some other Image Views to their image url, but would this work? Or would the image view download the image?

Just trying to figure out how the image views work in titanium and the best way to ensure I can preload/reuse images.

Thanks

james
  • 2,595
  • 9
  • 43
  • 70

2 Answers2

7

Update April 2015: As of Titanium 3.X, there is caching in images as per Gautier's answer below


There is no caching of remote images in an ImageView by default. In your scenario, the remote image would be redownloaded again when you switched back to it.

In most of my projects, I create a cachingImageView that saves the local image after it downloads. This is inspired by Dawson Toth's work at https://gist.github.com/938172. The only problem is if the image changes on the server once it has been cached locally, the client doesn't get the updated image unless the file name changes. Code is below.

exports.createCachingImageView = function(params) {
    var image = Ti.UI.createImageView();

    image.doRemote = function(imageURL) {
        image.remoteImage = imageURL;
        var file = Ti.Filesystem.getFile(somedirectory, image.localFileName(imageURL));

        if(!file.exists()) {
             // cached file does not exist, load the image
            image.addEventListener("load", image.saveImageOnLoad);
            image.image = imageURL;
        } else {
            Ti.API.debug(image.localFileName(imageURL) + ' does exist, just setting image');
            image.image = file.nativePath;
        }
    };

    image.saveImageOnLoad = function(e) {
        Ti.API.debug('saving image ' + image.localFileName(image.remoteImage));
        var f = Ti.Filesystem.getFile(somedirectory, image.localFileName(image.remoteImage));
        if(!f.read()) {
            f.write(e.source.toBlob());
        }
        e.source.removeEventListener('load', image.saveImageOnLoad);
    };

    image.localFileName = function(imageURL) {
        hashedSource = Ti.Utils.md5HexDigest(imageURL + '');
        return hashedSource;
    };
    if(params.image) {
        image.doRemote(params.image);
    }

    for(var v in params) {
        if(v != 'image') {
            image[v] = params[v];
        }
    }

    return image;
};

If you want to download the image stand alone without using an imageView, use a Ti.Network.httpClient to get the image and save it to the file system like so:

xhr.onload = function(){    
  var file = Ti.Filesystem.getFile(somedirectory, somefilename );
  file.write(this.responseData);
}

I use this to fetch images ahead of time so they should right away when the client uses them.

Jeff Bonnes
  • 1,128
  • 6
  • 6
  • Please, @Jeff Bonnes, could you tell me what the first sentence means? Does a newer version of Titanium lets you cache images "natively", without having to write much code? I'm interested –  Apr 24 '15 at 16:11
  • Yes - an version of the SDK > 3 seems to cache images without any additional code required. See the answer below. – Jeff Bonnes Apr 30 '15 at 05:35
  • @JeffBonnes It appears the built-in image caching no longer works on android > 6 . Remote images are reloaded every time when you set the image property. – Muhammad Qasim May 03 '18 at 11:28
0

Digging out this quite old question, since I had to do same thing.

From Android 3.1 & iOS, there's now a default cache : see http://docs.appcelerator.com/titanium/latest/#!/guide/Image_Best_Practices-section-30082525_ImageBestPractices-Cachingremoteimages

On the Android platform, the cache is limited to 25 MB and data remains for the lifetime of the application (as long as it's installed on device). On the iOS platform, the cache size is not predetermined (size cannot be guaranteed) and data remains there until iOS cleans the directory (needs more local storage).

This documentation page has its own implementation of a manual caching for images, too.

var Utils = {
  /* modified version of https://gist.github.com/1243697 */
  _getExtension: function(fn) {
    // from http://stackoverflow.com/a/680982/292947
    var re = /(?:\.([^.]+))?$/;
    var tmpext = re.exec(fn)[1];
    return (tmpext) ? tmpext : '';
  },
  RemoteImage: function(a){
    a = a || {};
    var md5;
    var needsToSave = false;
    var savedFile;
    if(a.image){
      md5 = Ti.Utils.md5HexDigest(a.image)+this._getExtension(a.image);
      savedFile = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory,md5);
      if(savedFile.exists()){
        a.image = savedFile;
      } else {
        needsToSave = true;
      }
    }
    var image = Ti.UI.createImageView(a);
    if(needsToSave === true){
      function saveImage(e){
        image.removeEventListener('load',saveImage);
        savedFile.write(
          Ti.UI.createImageView({image:image.image,width:'auto',height:'auto'}).toImage()
        );
      }
      image.addEventListener('load',saveImage);
    }
    return image;
  }
};
// example usage
var image = Utils.RemoteImage({
  image:'http://farm7.staticflickr.com/6059/6262552465_e53bccbd52_z.jpg',
  defaultImage:'KS_nav_ui.png',
  width:300,
  height:200,
  top:20
});
win2.add(image);
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – Mark Sep 21 '14 at 16:45
  • 1
    Sure, completing my answer. Thanks Mark. – Gautier Michelin Sep 21 '14 at 17:31