Показать сообщение отдельно
Старый 31.01.2011, 13:17
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 14  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Всем привет! Пару дней сидел без интернета.

Цитата:
Сообщение от VitaliyKrivtsov Посмотреть сообщение
Если не вызвать принудительно GC, и подождать немножко пока сам запустится, то получим:
- loader удаляется если описаны от всех слушателей и e.target.loader.content не находится в списке отображения;
Верно только второе. Можно не отписывать loaderInfo. Второе верно только как следствие того, что опишу ниже.

Цитата:
- e.target.loader.content не находится в списке и без ссылки - тоже удаляется;
Логично.

Цитата:
- loader удаляется, если на e.target.loader.content есть ссылка, не находится в списке отображения, обнулен;
Неверно. Есть ссылка на content - Loader жив.

Цитата:
не удаляется loader, если не отписаться от слушателей;
Удаляется. Уже высказался.

Цитата:
не удаляется loader, если на e.target.loader.content была ссылка за пределами функции,
Тут я уже говорил. Если есть ссылка, неважно где: в пределах функции, метода или поля класса. Важно другое: пока она есть, значит она указывает на реальный живой объект,
Вышли мы из функции, ссылка пропала.

Цитата:
не удаляется loader, если e.target.loader.content находится в списке отображения но нет ссылки за пределами функции,
Верно. Ссылка в таком случае будет (stage._childList[N]...displayObjectContainer._childList[N] as DisplayObject).loaderInfo.loader;


Дальше расскажу что происходит с loader при загрузке растровых изображений (JPEG, PNG, GIF).

Эксперимент проводился с Adobe Flash Player 10.0 r45 debug. Результат исследований заставил задуматься.
Пока существует ссылка на BitmapData контента (loader.content as Bitmap).bitmapData, (loaderInfo.content as Bitmap).bitmapData, жив и лоадер.
Можно даже сделать ей dispose(), ничего не изменится. Скажу больше. Даже bitmapData.clone() не позволит удалиться лоадеру.

Однако после bitmapData.draw() GC может удалить Loader.

Код маленького эксперимента
Код AS3:
///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2011. Dimarik
//
///////////////////////////////////////////////////////////////////////////////
 
package
{
 
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.net.URLRequest;
 
	/**
	 *  @author				Dimarik
	 *  @version			1.0
	 *  @langversion		3.0
	 *  @playerversion		9.0
	 * 
	 */
	[SWF(width="400", height="200", frameRate="21", backgroundColor="#E0EEEE")]
 
	public class LoaderTest extends Sprite {
 
		//-------------------------------------------------------------------------
		//
		//   Constructor
		//
		//-------------------------------------------------------------------------
 
		public function LoaderTest() {
			super();
			super.addEventListener(Event.ADDED_TO_STAGE, this.initialize);
		}
 
		//-------------------------------------------------------------------------
		//
		//   Private methods
		//
		//-------------------------------------------------------------------------
 
		private var _bitmapData:	BitmapData;
 
		//-------------------------------------------------------------------------
		//
		//   Private methods
		//
		//-------------------------------------------------------------------------
 
		public function initialize(event:Event):void {
			(event.target as IEventDispatcher).removeEventListener(event.type, arguments.callee);
 
			super.stage.scaleMode = StageScaleMode.NO_SCALE;
			super.stage.align = StageAlign.TOP_LEFT;
 
			var url:		String = 'http://www.flasher.ru/forum/image.php?u=69797&dateline=1296252938';
			var request:	URLRequest = new URLRequest(url);
			var loader:		Loader = new Loader();
			loader.load(request);
 
			var li:			LoaderInfo = loader.contentLoaderInfo;
			li.addEventListener(Event.COMPLETE, this.handler_complete);
		}
 
		//-------------------------------------------------------------------------
		//
		//   Events handlers
		//
		//-------------------------------------------------------------------------
 
		/**
		 * @private
		 * В таком виде в методе не произойдет удаление Loader
		 */
		private function handler_complete(event:Event):void {
			var li:			LoaderInfo = event.target as LoaderInfo;
			var loader:		Loader = li.loader;
 
			trace(li.contentType);
 
			// Раскомментируйте, чтобы проверить, что отписывание не влияет на решение GC об удалении loader
			//li.removeEventListener(Event.COMPLETE,					this.handler_complete);
 
			var bitmap:		Bitmap = loader.content as Bitmap;
			var bitmapData:	BitmapData = bitmap.bitmapData;
 
			// Дублирование исходной BitmapData не влияет на лоадер. Он будет жить.
			var bitmapData2: BitmapData = bitmapData.clone();
 
			// Однако draw не обладает такой силой.
			// Раскомментируйте, чтобы проверить, что в этом случае лоадер будет удален
		/*
			var bitmapData2: BitmapData = new BitmapData(bitmapData.width, bitmapData.height);
			bitmapData2.draw(bitmap);
		*/
 
			bitmap = new Bitmap(bitmapData2);
 
			// Пока есть ссылка на bitmapData, лоадер не будет удален. Закомментируйте для удаления лоадера.
			this._bitmapData = bitmapData2;
 
			// Пока используется оригинальная bitmapData или раздупленная через clone() лоадер будет жить.
			//super.addChild(bitmap);
 
			loader.unloadAndStop();
		}
 
	}
}
Вывод. Если в аппдомене существует используемое растровое изображение (только не надо говорить, что изображение загружается не в аппдомен), то Loader, которым загрузили это изображение остается среди живых объектов и не удаляется.
__________________
Воспитан в TimeZero. Работаю в Mail.ru.