2013-01-07 35 views
6

Mam z trzema zdjęciami w każdym wierszu, zaimplementowanymi przy użyciu UITableView.Osiągnij płynne przewijanie siatki zdjęć dzięki tysiącom zdjęć z dysku

Mam pamięć podręczną w pamięci (przy użyciu NSCache), która ma pojemność 100 obrazów, więc jednocześnie będę miał co najwyżej 100 obrazów w pamięci, mimo że mam tysiące obrazów na dysku, aby pokazać się w siatka.

Wszystkie moje obrazy są w formacie JPEG 4KB-20KB.

Dzięki tej infrastrukturze obrazy są stale ładowane i rozładowywane z pamięci podręcznej NSCache, gdy użytkownik przewija siatkę. Przy normalnym przewijaniu wszystko wygląda dobrze, mam około 55-58 fps.

Gdy użytkownik zacznie się przesuwać szybciej iz powrotem, mam dwa przypadki:

  1. Gdybym oddzielić zadanie obraz ładowania od głównego wątku, ja skończyć brakuje obrazów na starcie zdjęć, bo moja komórki są wyświetlane, zanim obrazy zostaną wczytane do pamięci.

    (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
         UIImage *image = getImageFromCacheForImagePath:imagePath; 
         dispatch_async(dispatch_get_main_queue(), ^{ 
          cell.leftGridItem.imageView.image = image; 
         }); 
        }); 
    } 
    
  2. Jeśli mam zadanie ładowania obrazów w głównym wątku, pojawia się jąkanie. Mam około 36-45 fps.

    (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
        UIImage *image = getImageFromCacheForImagePath:imagePath; 
        cell.leftGridItem.imageView.image = image; 
    } 
    

getImageFromCacheForImagePath:imagePath dostaje obraz bezpośrednio z NSCache gdyby istniał, czy nie, obraz jest ładowany z pliku i jest ustawiony na NSCache do późniejszego użycia, ale ustawić limit NSCache 100.

Czego próbowali/manipulowane:

  1. Unikaj clipsToBounds dla widoków obrazu siatki.
  2. Ładowanie obrazów w wątku tła.
  3. Korzystanie z kolejek NSOperation.
  4. Ładowanie obrazów w partiach po 100 (działa, ale z szybkim przewijaniem, czas ładowania obrazu był opóźniony).

Próbuję osiągnąć ten sam efekt, co aplikacja Zdjęcia rodzime.

Twoje sugestie są mile widziane.

+1

Proszę przejrzeć kod w pytaniu. Formatowanie wymagało pomocy, a po wykonaniu ujawniło pewne problemy (zobacz kod '^ {", który wygląda na to, że powinien uruchomić nowy blok kodu, ale nie wydaje mi się poprawny). Próbowaliśmy pomóc Ci sformatować to poprawnie, ale nie jest to jasne. – ErikE

+0

Zastanawiam się, czy nie generują miniatur w trybie off-line, jak w czasie importu, a następnie niewielki rozmiar miniaturek daje im znaczną przewagę przy ładowaniu głównego wątku. –

Odpowiedz

0

Miałem też ten sam problem kilka dni temu, więc GitHub jest najlepszym miejscem do szukania rozwiązań open source, więc wypróbuj te linki.

Sprawdź PF-GridView lub DTGridView.

również spojrzeć na AQGridView, How to Write a Custom Image Picker like UIImagePicker,

prostu trzeba zrobić bit manupulation według nasze potrzeby i działa jak mistrz.

+0

dziękuję za sugestię, problemem jest bardziej sprytne i terminowe ładowanie obrazów z dysku do pamięci, tak że nie będę korzystać z dużej ilości pamięci, ale nadal będę wyświetlać obrazy w widoku siatki z płynnym przewijaniem. Podobnie jak natywna aplikacja Zdjęcia, nawet przy tysiącach zdjęć mają płynne przewijanie, tak jakby wszystkie obrazy znajdowały się w pamięci. Próbuję dowiedzieć się, jak sobie z tym radzą. –

0

Mam zaimplementowany płynny stół przewijania zawierający ponad 700 obrazów. Kluczem było nie tylko ładowanie obrazów w tle, ale także zmiana rozmiaru w tle, aby idealnie pasowały do ​​pojemnika.Zmiana rozmiaru Apperently to zbyt ciężka operacja, aby zrobić to w wątku UI.