TTTableViewController is a bit jumpy? - three20

I'm using the TTTableViewController and datasource and I notice every time a new cell is being loaded it is a little bit sticky. My source code is too long to post so I was wondering if there were any tips or things to look out for to optimize the three20 table view?

This is very interesting. I have a tableView that creates many UIImageViews in lazy loaded cells and replacing imageWithContentsOfFile virtually removed a slight pause when the cells were being recreated. Each cell has 1 changing image, and 2-3 images that never change.
According to this thread, imageNamed should not be used: img_data_lock iphone - imageNamed vs imageWithContentsofFile, I have not noticed any crashes with imageNamed, can you explain why this is so?

Related

Images in listview are not released from memory when out of view

I am displaying images from the internet in a vertical ListView. I fetch the images using http.get (not using cached network image cuz I do not want to cache the images). Then I insert the image Uint8List into image.memory(). What happens is that as the user scrolls the list and images are loading, the ram keeps increasing until the whole app crashes. Any ideas what to do ?
Yeah, this is the normal behavior. I don't know why exactly. My theory is that the images by default are disposed if the dart objects holding references to them are garbage collected rather then when the widgets are knocked off the widgets tree, but don't take my word for it- that's just my personal reasoning. It may be completely wrong.
To get around this, I use Extended Image pakcage It's constructors take a bool clearMemoryCacheWhenDispose which disposes of images in RAM in scroll lists. You may do that or visit the package code to see how he's doing it, and replicate it.
Other advice I can give is to make sure your images are of the appropriate size. If you are loading your images locally check this part of the documentation to have different dimensions selected for different screen sizes https://flutter.dev/docs/development/ui/assets-and-images#loading-images
If you are fetching your images from network which is more likely, make sure their sizes are appropriate, and have different sizes served if you can. If you don't have control over that set cacheWidth and cacheHeight in Image.memory these will reduce the cached image in memory (RAM). You see by default Flutter caches images in full resolution despite their apparent size in the device/app. For example if you want your image to display in 200x200 box then set cacheWidth to 200 * window.devicePixelRatio.ceil() you will find window in dart:ui, and if you only set cacheWidth, the ratio of your images will remain true. Same true if you only set cacheHeight. Also do use ListView.builder as suggested.
I am disappointed at how little is said about this in Flutter docs. Most of the time people discover this problem when their apps start crashing. Do check your dev tools regularly for memory consumption. It's the best indicator out there.
Cheers and good luck
I was having the same issue and found a fix thanks to #moneer!
Context:
Users in my app can create shared image galleries which can easily contain several hundred images. Those are all displayed in a SliverGrid widget. When users scrolled down the list, too many images were loaded into RAM and the app would crash.
Things I had already implemented:
Image resizing on the server side and getting the appropriate sized images on the client based on the device pixel ratio and the tile size in the gallery
I made sure that my image widgets were properly disposing when out of view, but the memory size kept building up as the user scrolled through all the images anyway
Implement cacheHeight to limit the size of the cached image to the exact size of the displayed image
All these things helped but the app would eventually still crash every time the user scrolled down far enough.
The fix:
After some googling I stumbled upon this thread and tried the extended_image_package as #moneer suggested. Setting the clearMemoryCacheWhenDispose flag to true fixed the issue of the app crashing as it was now properly clearing the images from memory when they were out of view. Hooray! However, in my app users can tap on an image and the app navigates to an image detail page with a nice Hero animation. When navigating back the image would rebuild and this would cause a rebuild 'flicker'. Not that nice to look at and kind of distracting.
I then noticed that there's also an enableMemoryCache flag. I tried setting this to false and that seems to work nicely for me. The Network tab in Dart DevTools seems to show that all images are only fetched from the network once when scrolling up and down the gallery multiple times. The app does not crash anymore.
I'll have to more testing to see if this leads to any performance issues (if you can think of any please let me know).
The final code:
ExtendedImage.network(
_imageUrl,
cacheHeight: _tileDimension,
fit: BoxFit.cover,
cache: true, // store in cache
enableMemoryCache: false, // do not store in memory
enableLoadState: false, // hide spinner
)
I had a similar issue when I loaded images from files in a ListView.
[left-side: old code, right-side: new code]
The first huge improvement for me: not to load the whole list at once
ListView(children:[...]) ---> ListView.builder(...).
The second improvement was that images are no longer loaded at full-size:
Image.file("/path") ---> Image.file("/path", cacheWidth: X, cacheHeight: Y)
These two things solved my memory problems completely
Ideally caching happens kind of by default after some conditions are fulfilled. So its upon your app to be responsible to handle and control how the caching will happen.
Checkout this answer
https://stackoverflow.com/a/24476099/12264865

What is the best way to display and apply filters to RAW images on macOS?

I am creating a simple photo catalogue application for macOS to see whether the latest APIs can significantly improve performance of loading directories with large numbers of images.
So far it looks pretty promising and loading around 600 45MB RAW image thumbnails using QLThumbnailGenerator and CGImageSourceCreateWithURL is super fast allowing thumbnail images and image metadata to be displayed almost instantly.
Displaying these images in a NSCollectionView using a CALayer in the NSCollectionViewItem's view also appears to be extremely fast and scrolling is very smooth.
I did find that QLThumbnailGeneratorseems to start failing after a few hundred images and starts returning error code 108 if I call the api in a continuous loop - I fixed that by calling CGImageSourceCopyPropertiesAtIndex immediately after the thumbnail generator api call - so maybe there is a timing issue or not enough file handles or something if the api is called to quickly and for too long.
However I am still having trouble rendering a full sized image to the display - here I am using a NSScrollView with a layer backed NSView documentView. Everything is super fast until the following call:
view.layer.contents = cgImage
And at this point the entire main thread hangs until the image has loaded - and this may take a few seconds.
Once it has loaded it's fine and zooming in and out by changing the documentView frame size is very fast - scrolling around the full size image is also super smooth without any of the typical hiccups.
Is there a way of loading these images without causing the UI to freeze ?
I've seen the recent WWDC2020 session where they demonstrate similar scrolling of large numbers of images but I haven't been able to find anything useful on loading large images other than CATiledLayer - but it's not really clear if that is the right answer for this problem.
The old Apple sample RawExpose seemed to be an option but most of that code is deprecated and it seems one has to use MetalKit not instead of GLKit - unfortunately there is no example of using MetaKit with Core Image that I can find.
FYI - I tried using some the new SwiftUI CollectionView and List but they seem to be significantly slower than AppKit and I found some of the collection view items never render - of course these could just be bugs in the macOS 11 beta.
OK - well I finally figured it out and it's complicated but simple. It's complicated because there are so many options to choose from and so many outdated sample apps to look at. In any event I think I have solved most if not all the issues related to using metal backed CALayers and rendering realtime updates of the images as CIFilter adjustments are applied. There are many pieces to the puzzle and happy to share if anyone is looking for help.
Some key pointers:
I am using CAMetalLayer and NSView
I override the CAMetalLayer.display(layer:) method and call the layer.setNeedsDisplay() when the user slides an adjustment slider.
I chain together all the CIFilters, including the RAW filter created with CIFilter(imageUrl:)
Most importantly I use the RAW filters scaleFactor parameter to size the image - encountered major performance issues using any other method to resize the image for the views size
Don't expect high performance if the image is zoomed right in - 50% is seems to be the limit for 45megapixel RAW imaged from Nikon D850.
A short video of the result is here https://youtu.be/5wp0CIWAoIM

Images in datagridview once more time

I need your advice on a rather simple question - I'd like to draw an image in datagridview cell.
The problem is that the number of rows can be rather big: up to 100 000 of rows, sometimes more than that.
I tried using CellFormating but in this case the grid is blinking. I tried to set DoubleBuffered = true but it got only worse - the window hung and CPU usage was showing 100%. Other controls stopped drawing itself. Moreover it did not help blinking too much (even on several rows).
So I tried to use source DataTable and added a column. Than I filled it with images. But it was a fail: app memory grew very fast on a big datatable and it just crashed.
Also I tried using DataSourceChanged event and settings images like row[cell].Value = . It fires but grid works strange: sometimes it shows images, sometimes it does not. I read that you must set underlying data to make this working but it caused memory problems as I wrote.
I changed image to text so far but certainly I'd like to have moe user-friendly UI.
What can I do in this case? Probably I should give up images or change display logic at all? I.e. use virtual mode. I tried to use it long ago but I had some difficulties so I just skipped this way and my grid is working in non-virtual mode.
Ok, I eventually used CellFormatting event. It looks like blinking has gone away without my help. Images are looking fine.

Is this a IKImageBrowserView?

I want to know is this a IKImageBrowserView object? And How can I add an NSProgressIndicator when loading the image?
It certainly looks like it could be one. How you add a progress indicator depends entirely on how you download the image. If you are using NSURLConnection then you can get status updates through connection:didReceiveResponse: and connection:didReceiveData:. The response structure contains the expected length of the file, which you would use as the maximum of your progress indicator, and the data contains the length of the data that you recieved in that chunk. Add that length to the lengths of the previous chunks you get will give you how much data you have received so far. That would be the position on your progress indicator.
I think it is not IKImageBrowserView.It is a NSCollectionView.I also faced this problem then I googled and searched in internet to add NSProgressIndicator in IKImageBrowserView I did not get any solution. Finally I found NSCollectionView is the way to add NSProgressIndicator animation when images loading.So I moved to NSCollectionView. click here to more details.

UIImage ImageNamed method

In my app, I am loading several images onto a UIScrollView and I highlight a portion of the scroll view using Core Graphics routine. I have used the CGImageRelease and CGContextRelease to manage the memory during the routines.
When I run the app using instruments (allocation), I see that the memory consumption keeps rising with every swipe of the scrollView. This at one point leads to the app becoming really slow.
For loading different images, I use the UIImage ImageNamed method, I have come across some posts indicating that this is not a good idea since the method results in autoreleased images which creates memory issues. I would like to know if I am looking a the right place for the error. What could be the possible place to look for this unusual memory consumption?
Also, using the allocation of Instruments, I can just see that increase in the memory, is it possible to pin point the code where these allocations happen?
Thanks in advance for your help!
Best
DKV
For loading different images, I use the UIImage ImageNamed method, I have come across some posts indicating that this is not a good idea since the method results in autoreleased images which creates memory issues.
No, that's not the issue. Anything that doesn't involve you calling alloc, init[WithSomethingOrOther:], and release yourself is going to get the image autoreleased.
The problem is that imageNamed: continues to own the image after it hands it to you. Every image you obtain from imageNamed: stays in that cache, permanently associated with that name. It's not merely a “load this image” method; it's a “load this image and keep it alive forever*” method.
*Where “forever” means “until the end of my process”.
I would like to know if I am looking a the right place for the error. What could be the possible place to look for this unusual memory consumption?
In Instruments. It will tell you exactly how many of each kind of object you are creating, and how much total memory objects of each kind are occupying, and you can sort that list to determine what's eating up memory. Then you can drill down into each class and into each object to determine what's keeping objects alive after you need them.

Resources