Я пытаюсь использовать библиотеку iCarousel в monotouch.Я успешно перенес библиотеку, все работает отлично, но приложение вылетает, если вы вводите слишком много UIImageViews с изображениями внутри, что является нормальным, потому что iCarousel похож на UIScrollView.
Я определенно должен каким-то образом использовать ленивую систему загрузки из вторичного потока и отображать только 3-4 изображения одновременно, но я не знаю, как сделать эту работу плавной.
На данный момент я установил это в делегате iCarousel:
bool threadsAlive = true;
public cDelegate()
{
ThreadPool.QueueUserWorkItem( delegate { refresh_visible(); } );
}
public override void DidScroll (iCarousel carousel)
{
scrolling = true;
}
public override void DidEndScrollingAnimation (iCarousel carousel)
{
scrolling = false;
//show images that are currently on the screen
ThreadPool.QueueUserWorkItem( delegate { ShowCurrent(); } );
//hides images that are not on the screen
ThreadPool.QueueUserWorkItem( delegate { hideInvisibleImages(); } );
}
void refresh_visible()
{
while( threadsAlive )
{
while( scrolling )
{
ShowCurrent();
}
}
}
void refresh_hidden()
{
while( threadsAlive )
{
while( scrolling )
{
hideInvisibleImages();
}
}
}
public void ShowCurrent()
{
var ds = _carousel.DataSource as cDataSource;
var left_index = _carousel.CurrentItemIndex - 1;
var right_index = _carousel.CurrentItemIndex + 2;
if( left_index < 0 ) left_index = 0;
if( right_index >= ds.Lista.Count ) right_index = ds.Lista.Count - 1;
//
for( var i = left_index; i < right_index ; i++ )
{
var img = ds.Lista[i];
if( img.Image == null )
{
BeginInvokeOnMainThread( delegate{
img.Image = UIImage.FromFile( img.UserObject.ToString() );
});
}
}
}
void hideInvisibleImages()
{
Console.WriteLine("ascund!");
var ds = _carousel.DataSource as cDataSource;
var left_index = _carousel.CurrentItemIndex - 1;
var right_index = _carousel.CurrentItemIndex + 2;
if( left_index < 0 ) left_index = 0;
if( right_index >= ds.Lista.Count ) right_index = ds.Lista.Count - 1;
//
for( var i=0; i<left_index; i++ )
{
var img = ds.Lista[i];
if( img.Image != null )
{
img.Image.Dispose();
img.Image = null;
}
}
for( var i=right_index; i<ds.Lista.Count; i++ )
{
var img = ds.Lista[i];
if( img.Image != null )
{
img.Image.Dispose();
img.Image = null;
}
}
}
Код на самом деле очень прост: есть основной поток, который показывает только 1 изображение слева от текущегоИндекс и два изображения заранее, а другой поток, который очищает все остальные изображения, скрывает их.
Работает, память в порядке, но не гладкая на устройстве, немного "зависает" при прокрутке.Есть еще один способ сделать это?Или, может быть, я должен изменить алгоритм?