Guy Joel McLean
Guy Joel McLean

Reputation: 1049

Why am I getting Error 1007: Instantiation attempted on a non contructor, on Android only?

I've seen the error before, usually when we're trying to call a constructor for an object that the interpreter hasn't seen yet. Most likely a dynamic attempt at instantiation. However, I'm currently experiencing the error on a line of execution on Android devices only.

See the guilty function below -

public class XMLBuilder
{

    private var elementClasses:Dictionary;
    private var elements:Dictionary;

    public function XMLBuilder() 
    {
        elementClasses = new Dictionary();
        elements = new Dictionary();
    }

    public function buildFromXML(xml:XML):void 
    {
        elements = new Dictionary();

        var element:StardustElement;
        var node:XML;
        for each (node in xml.*.*) {
        //error thrown on line below// 
        element = StardustElement(new elementClasses[node.name()] ());
            if (elements[node.@name] != undefined) {
                throw new DuplicateElementNameError("Duplicate element name: " + node.@name, node.@name, elements[node.@name], element);
            }
            elements[[email protected]()] = element;
        }
        for each (node in xml.*.*) {
            element = StardustElement(elements[[email protected]()]);
            element.parseXML(node, this);
        }
    }

    public function registerClass(elementClass:Class):void {
        var element:StardustElement = StardustElement(new elementClass());
        if (!element) {
            throw new IllegalOperationError("The class is not a subclass of the StardustElement class.");
        }
        if (elementClasses[element.getXMLTagName()] != undefined) {
            throw new IllegalOperationError("This element class name is already registered: " + element.getXMLTagName());
        }
        elementClasses[element.getXMLTagName()] = elementClass;
    }
}

Where the object 'elementClasses' is a dictionary that contains a set of Classes. (And In this case it does, i've checked while debugging on both iOS & Android). And where evaluating 'elementClasses[node.name()] is Class' returns true.

Does anybody know of any quirks in AIR that would cause this to happen on Android only? Or anything in this function that jumps-out?

Upvotes: 0

Views: 61

Answers (1)

Guy Joel McLean
Guy Joel McLean

Reputation: 1049

So, in AS3 XML node.name() will return a QName object. If you look at my registerClass(elementClass:Class), you will see that we're adding classes to the elementClasses dictionary using element.getXMLTagName() which returns a String.

Now, apparently in AIR iOS if we attempt a lookup on someDict[someQName], someQName.toString() or some kind of cast is attempted. Whereas in AIR Android, it would appear that it attempts to use the QName object itself as the key.

I would say that the Android implementation has the expected behaviour, but it's definitely fishy to me...

Fixed code below. node.name().localName used instead essentially.

public function buildFromXML(xml:XML):void 
{
    elements = new Dictionary();

    var element:StardustElement;
    var node:XML;
    for each (node in xml.*.*) {

    element = StardustElement(new elementClasses[node.name().localName] ());
        if (elements[node.@name] != undefined) {
            throw new DuplicateElementNameError("Duplicate element name: " + node.@name, node.@name, elements[node.@name], element);
        }
        elements[[email protected]()] = element;
    }
    for each (node in xml.*.*) {
        element = StardustElement(elements[[email protected]()]);
        element.parseXML(node, this);
    }
}

public function registerClass(elementClass:Class):void {
    var element:StardustElement = StardustElement(new elementClass());
    if (!element) {
        throw new IllegalOperationError("The class is not a subclass of the StardustElement class.");
    }
    if (elementClasses[element.getXMLTagName()] != undefined) {
        throw new IllegalOperationError("This element class name is already registered: " + element.getXMLTagName());
    }
    elementClasses[element.getXMLTagName()] = elementClass;
}

Upvotes: 1

Related Questions