【问题标题】:Java/Android equivalent of Objective-C/iOS load() methodJava/Android 等效于 Objective-C/iOS 的 load() 方法
【发布时间】:2013-07-04 22:00:18
【问题描述】:

对于 iOS(在 Objective-C 中),每个类都有一个 load() 方法,该方法在类加载时被调用。 iOS 似乎会在应用启动时加载所有类(或至少所有定义了load() 方法的类)。

我在几个 iOS 程序中利用了这一点,向集中式消息处理程序注册处理程序类,例如,它采用消息类型并使用处理程序类来创建特定于每条消息的实例对象。

为此使用load() 允许代码进行自动注册,而无需在某处列出所有类并手动调用它们 - 从某种意义上说,它不易出错。

下面是一些示例代码:

专门的payload对象(更新payload类):

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

有效负载消息处理程序

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];
} 

我现在想在 Android / Java 中做类似的事情。是否有类似的方法是首选模型?

EDIT/FOLLOW-ON:有没有使用反射的好方法?

【问题讨论】:

  • 我所知道的 Java 中没有 load() 的等价物,尽管您可以使用静态初始化程序块来扮演类似的角色。但是,类在第一次使用之前不会加载到 VM 中。
  • 是的,这就是我所害怕的 - 看起来我也回到了集中注册功能。它不像我说的那么讨厌,它更多的是在添加新东西时编辑多个文件。
  • 除了蛮力使用Class.forName("com.foo.ClassName") 之外别无他法。另一种可能性是使用 Java 的注释预处理器功能来生成自动加载类的代码
  • 任何得到答案的人都可以获得我的赏金。谢谢!
  • 一个想法可以是使用注解处理,例如定义像@AutoLoad这样的注解和静态load函数,在你的注解处理器内部(发生在编译时)生成一个callLoads函数在一个类中,它在每个具有该注释的类(通过代码生成)上调用 load 函数,最后在您的应用程序的 onCreate 中,调用生成的函数 callLoads

标签: android ios classloader


【解决方案1】:

有几种方法可以实现您想要的。

  1. 在要“注册”的类中使用静态块。这很简单,而且很容易。主要缺点是,您无法跟踪所有类,而是您“注释”的类
class LoadedClassHandler {
    static void handleLoadedClass(Class<?> cls) {
        // whatever you want to do with that information
    }
}

[....]

class Example {
    static {
       LoadedClassHandler.handleLoadedClass(Example.class);
    }
}
  1. 创建一个自定义类加载器,并通过重写的 findClass() 在其中注册加载的类。

更多信息在这里How to put custom ClassLoader to use?

这是相当困难的方法,但在大多数情况下,它会完成您想要实现的目标,即:使用通用方法来跟踪已加载的类

记住几件事

  • 注册只会发生一次(如果你做得对的话)
  • 资源也是通过同一个类加载器加载的。
  • LoadedClassHandler 是您自己创建的类 =)

祝你好运!

【讨论】:

  • 正如@CommonsWare 8 年前评论的那样:“但是,类在首次使用之前不会加载到 VM 中”。无需调用 Firebase sdk 即可激活。我确信这是可能的,但没有人找到
  • 没有注意到这是一篇很老的帖子...哦,好吧 - 你是对的 - 类是在使用时加载的
  • NP!我还在寻找它 5 年 :)
猜你喜欢
  • 2012-07-28
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多