PDA

Просмотр полной версии : Параметр weakKeys класса Dictionary


Akopalipsis
13.10.2013, 01:57
я сразу прошу не ругаться, если Вам покажется, что ответ написан в хелпе и так очевиден, когда ты уже его знаешь...
В хелпе написано -
Предписывает объекту Dictionary использовать в ключах объектов «слабые» ссылки. Если единственная ссылка на объект находится в указанном объекте Dictionary, ключ подходит для очистки и при удалении объекта удаляется из таблицы.
и если я правильно понимаю, то при удалении _sprite обьект _key должен удаляться из памяти.
Чтобы убедиться точно, я пробовал удалять ключ, в надежде, что удалится обьект из словаря.
Но и в том и в другом случаи, в памяти весят оба обьекта.
Как сделать, чтобы удаление было настоящим и что именно удаляется само, когда что то удалить руками?
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.utils.Dictionary;

public class Main extends Sprite
{
private var _dictionary:Dictionary;
private var _key:Sprite;
private var _sprite:Sprite;

public function Main()
{
_dictionary = new Dictionary(true);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);

_key = new Sprite();

_sprite = new Sprite();
_dictionary[_key] = _sprite;
}
private function mouseDownHandler(event:MouseEvent):void
{
_dictionary[_key] = null;
trace(_dictionary[_key]);
}

}

}
Даже если сделать вот так, то ключ все равно не удаляется ( точнее сказать, что то одно не удаляется ).
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.utils.Dictionary;

public class Main extends Sprite
{
private var _dictionary:Dictionary;

public function Main()
{
_dictionary = new Dictionary(true);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);

addDictionary(new Sprite(), new Sprite());
}
private function addDictionary(key:Sprite, sprite:Sprite):void
{
_dictionary[key] = sprite;
}
private function removeDictionary(key:Sprite):void
{
_dictionary[key] = null;
trace(_dictionary[key]);
}
private function mouseDownHandler(event:MouseEvent):void
{
removeDictionary(new Sprite());
}

}

}

Wolsh
13.10.2013, 02:13
В первом коде ссылка на объект остается в приватном свойстве _sprite. Вы обнуляете только ссылку в Справочнике, а точнее записываете новое значение null по ключу.
Во втором коде — Вы считаете что new Sprite() == new Sprite()? А потрейсить? Это же РАЗНЫЕ объекты, а значит разные ключи.

Добавлено через 8 минут
Кроме того, приглядевшись к первому коду, я засомневался что Вы вообще правильно поняли хелп.
Речь в нем идет о КЛЮЧЕ, а не о значении.
Ключом в Dictionary выступает Объект. Так вот когда ссылок на этот Объект больше нет, запись в справочнике стирается, потому что никто больше не сможет к ней обратиться, никто не знает этот Объект, этот КЛЮЧ.

Akopalipsis
13.10.2013, 02:25
Wolsh Вам в очередной раз - Спасибо! Мне оочень не хочется, что бы Вы перестали реагировать на мои вопросы из-за вот таких глупостей, но дело вот как было..
Часа два я искал информацию и читал. Затем я создал тему и сразу понял, что ссылка кроется в _sprite и я быстренько начал проверять, и написал второй код. Второй день подряд думаю о том, что нужно немного отдыхать.. но это не возможно)
И у меня ещё один вопрос, который меня давно мучает - если использовать в качестве ключа статические переменные\константы из другого класса, то это должно сработать? я этого не знаю, потому не знаю, что случается со статическими свойствами и методами...

Wolsh
13.10.2013, 02:49
Хм. Теоретически да, на практике просто не пробовал)))

Вот кстати код для теста. Первый раз запустите как есть и кликните — странное дело, хотя ссылку на s обнулили, в справочнике так и сидит ключ-спрайт и значение. Просто GC не запускается, ибо памяти выше крыши. Но если раскомментировать и запускать его принудительно, случается описанное в хелпе волшебство.

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.system.System;
import flash.utils.Dictionary;

/**
* ...
* @author Wolsh
*/
public class Main extends Sprite
{
private var _d:Dictionary;

public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
_d = new Dictionary(true);
var s:Sprite = new Sprite();
_d[s] = "value by Sprite key";
for (var obj:Object in _d)
{
trace(obj, _d[obj]);
}
s = null;
for (var obj2:Object in _d)
{
trace(obj2, _d[obj2]);
}
//System.gc();
stage.addEventListener(MouseEvent.CLICK, handlerClick);
}

private function handlerClick(e:MouseEvent):void
{
for (var obj:Object in _d)
{
trace(obj, _d[obj]);
}
}
}
}

Akopalipsis
13.10.2013, 03:10
Wolsh большое Спасибо!
Хм. Теоретически да, на практике просто не пробовал)))
Возможно я что то сделал не правильно, но использую статическую константу в качестве ключа
после вызова GC один бьект висит в памяти. Но я вижу Вы удаляете ключ, что влечёт за собой удаление обьекта связанного с ним. А я думал, что наоборот, используя обьект в качестве ключа, удалять его за счет удаления эллемента.
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.utils.Dictionary;

public class Main extends Sprite
{
private var _dictionary:Dictionary;


public function Main()
{
_dictionary = new Dictionary(true);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);

addDictionary(Test.key, new Sprite());
}
private function addDictionary(key:Sprite, sprite:Sprite):void
{
_dictionary[key] = sprite;
}
private function removeDictionary(key:Sprite):void
{
_dictionary[key] = null;
trace(_dictionary[key]);
}
private function mouseDownHandler(event:MouseEvent):void
{
removeDictionary(Test.key);
}

}

}

Wolsh
13.10.2013, 03:20
То есть "спасибо" Вы сказали, еще не прочитав вторую часть моего ответа..
Хотя бы название параметра не наводит Вас ни на какие мысли? Почему там weakKeys а не weakValues?

Akopalipsis
13.10.2013, 03:49
То есть "спасибо" Вы сказали, еще не прочитав вторую часть моего ответа..
Да, я не видел вторую часть.
Почему там weakKeys а не weakValues?
Действительно, вот теперь кажется - что да, как же я сразу то не обратил внимания.)
Ещё одно Вам Спасибо! И Спасибо!

Wolsh
13.10.2013, 04:09
А я думал, что наоборот, используя обьект в качестве ключа, удалять его за счет удаления эллемента.А как Вы представляете себе "удаление элемента"? В AS3 нет деструкторов. Вы НЕ можете сами удалить объект. Вы можете только обнулить на него ссылки. Но одна из них как раз и хранится в Справочнике по какому-то ключу. И пока есть эта ссылка, объект не может быть удален GC. А если Вы обнулите эту ссылку, то, простите, связи между ключом и ТЕМ объектом уже просто нет — по старому ключу Вы записали новое значение, null. Судьба ключа больше никак не связана с судьбой объекта. Удалится он или нет — ключ больше за него не отвечает))
Кроме того, как Вы себе представляете поведение программы, когда из справочника вдруг ни с того ни с сего исчезает некое свойство? Вы создали ключ, и в каком-то месте к нему обращаетесь. Но оказывается, что такого ключа уже нет, потому что объект, на который хранилась ссылка по этому ключу, уничтожен? В чем связь? Ключ это свойство Справочника. Для его удаления есть конкретный метод delete. Ключ не может исчезать только оттого, что где-то Вы записали null в переменную, которая ссылалась на тот же объект, на который в Справочник записана ссылка под этим ключом.
weakKeys это "слабый ключ". Ключ это Объект, то есть ССЫЛКА на какой-то объект. Так вот weakKeys говорит, что если единственной ссылкой на Объект-ключ будет только этот КЛЮЧ, то он уничтожается. Это не может привести к сбою программы, потому что больше никто не может обратиться к справочнику и запросить значение по этому ключу — ведь никто больше не знает этого ключа, на этот объект-ключ больше нет ни одной ссылки, кроме самого ключа. Он бесполезен. Добраться до него и его значения можно только перечислением for..in или for each, как в моем коде. Но назвать сам ключ уже не может никто.

Akopalipsis
13.10.2013, 13:57
Wolsh Спасибо! Вы намного лучше любых книг и хелпов обьясняете.