1

For iOS (in Objective-C), every class has a load() method that is called when the class is loaded. iOS seems to load ALL of the classes (or at least all of the ones that have the load() method defined) when the app starts.

I've taken advantage of this in several iOS programs to register handler classes with a centralized message handler, for instance, that takes a message type and uses the handler class to create an instance object specific to each message.

Using load() for this allows the code to do auto-registration without having to list all of the classes somewhere and invoking them by hand - it's less error-prone in some sense.

Here's some example code:

Specialized payload object (Update payload class):

@implementation
+(void)load
{
    [Payload registerMessageName:@"Update"
                  forMessageKind:kPayloadUpdate
              withPayloadHandler:[Update class]];
}

Payload message handler

static NSMutableDictionary *s_payloadFactoryDict = nil;
static NSMutableDictionary *s_kindToNameMap = nil;
static NSMutableDictionary *s_nameToKindMap = nil;


@implementation

+(void)registerMessageName:(NSString *)messageName
            forMessageKind:(PayloadKind)kind
        withPayloadHandler:(Class)handlerClass
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        s_payloadFactoryDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:nil];
        s_kindToNameMap = [[NSMutableDictionary alloc] initWithObjectsAndKeys:nil];
        s_nameToKindMap = [[NSMutableDictionary alloc] initWithObjectsAndKeys:nil];
    });
    
    NSNumber *kindNum = [NSNumber numberWithInt:kind];

    [s_nameToKindMap setObject:kindNum 
                        forKey:messageName];

    [s_kindToNameMap setObject:messageName
                        forKey:kindNum];

    [s_payloadFactoryDict setObject:handlerClass
                             forKey:kindNum];
} 

I now want to do something similar in Android / Java. Is there a similar approach that is the preferred model?

EDIT/FOLLOW-ON: Is there a good way of using reflection to do this?

auspicious99
  • 3,902
  • 1
  • 44
  • 58
Cubs Fan Ron
  • 687
  • 6
  • 17
  • 1
    There is no equivalent of `load()` that I am aware of for Java, though you can use static initializer blocks for a similar role. However, classes are not loaded into the VM until they are first used. – CommonsWare Jul 04 '13 at 22:03
  • Yeah, that's what I was afraid of - looks like I'm back to centralizing the registration function as well. It's not as icky as I'm making it sound, its more of editing multiple files when adding a new thing. – Cubs Fan Ron Jul 04 '13 at 22:16
  • 1
    No way besides bruteforce style use of `Class.forName("com.foo.ClassName")` maybe. Another possibility would be using Java's annotation preprocessor capabilities to generate code that loads the classes automatically – zapl Jul 04 '13 at 23:33
  • Anyone who get an answer can get my bounty. Thank you! – Tony Jul 14 '21 at 04:52
  • 1
    One idea can be using annotation processing, for example define an annotation like `@AutoLoad` and the static `load` function, inside you annotation processor (which happens in compile time) generate a `callLoads` function in a class, which calls `load` function on every single class having that annotation (by code generation) and finally inside your app's onCreate, call that generated function `callLoads` – Amin Jul 15 '21 at 21:27
  • @Amin that's a good idea. If you write a full answer, I will give you 100 reps as bounty. Thank you! – Tony Jul 18 '21 at 11:23
  • Knock knock! I got a solution. Is anyone still interested in? – Tony Mar 13 '23 at 09:39

1 Answers1

1

There are few ways for achieving what you want.

  1. use static block in classes that you want to "regiser". It's pretty straight forward, and easy. Main drawback is, you cannot keep track of all the classes, but the the classes you "annotated"
class LoadedClassHandler {
    static void handleLoadedClass(Class<?> cls) {
        // whatever you want to do with that information
    }
}

[....]

class Example {
    static {
       LoadedClassHandler.handleLoadedClass(Example.class);
    }
}
  1. create a custom classloader, and register loaded classes in there through overriden findClass().

More on that here How to put custom ClassLoader to use?

it's considerably more difficult approach, yet in most cases it'll do what you want to achieve, which is: having a generic way of keeping a track of loaded classes

Remeber of few things

  • registration will occur only once (if you do it right)
  • resources are loaded through same classloader too.
  • LoadedClassHandler is the class that you create yourself =)

good luck!

Miron Balcerzak
  • 886
  • 10
  • 21
  • As @CommonsWare commented 8 years ago: "However, classes are not loaded into the VM until they are first used". Firebase sdk doesn't need to be called to activated. I'm sure that it's possible but nobody found – Tony Jul 18 '21 at 11:19
  • haven't noticed it's such an old post... oh well - you are right - classes are loaded as they are used – Miron Balcerzak Jul 18 '21 at 19:26
  • NP! I'm still looking for it for 5 years :) – Tony Jul 20 '21 at 01:39