Implementing Spring-like package scanning in Android

后端 未结 5 970
情话喂你
情话喂你 2020-12-30 17:03

I\'m attempting to implement a package-scanning feature, similar to Spring\'s component-scan, for the Android framework I\'m developing. Basically, I would like

相关标签:
5条回答
  • 2020-12-30 17:33

    I wanted to find all the subclass at runtime. So I've been looking for android class scanning. This is my final code from what I gathered in web. You will get the idea.

    public static void findSubClasses(Context context, Class parent) {
        ApplicationInfo ai = context.getApplicationInfo();
        String classPath = ai.sourceDir;
        DexFile dex = null;
        try {
            dex = new DexFile(classPath);
            Enumeration<String> apkClassNames = dex.entries();
            while (apkClassNames.hasMoreElements()) {
                String className = apkClassNames.nextElement();
                try {
                    Class c = context.getClassLoader().loadClass(className);
                    if (parent.isAssignableFrom(c)) {
                        android.util.Log.i("nora", className);
                    }
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                //              android.util.Log.i("nora", className);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                dex.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-30 17:39

    Take a look at Vogar's ClassPathScanner. It uses it to find test cases on the class path.

    0 讨论(0)
  • 2020-12-30 17:44

    In your java build process incorporate the class path scanning, generating injection data/code. This could then be ported too to Dalvik. It is even more efficient that dynamic scanning.

    0 讨论(0)
  • 2020-12-30 17:46

    I share the opinion of Joop Eggen and find his approach a good one. In Android I try to avoid the usual web app features which lead to a long lasting application start. I do not use reflection or package scanning.

    But if you want to .... if I understand it correctly you want to have an annotation for a class. Instead of using annotations you could also use marker interfaces (to just have more possibilites).

    1) Look at

    • Annotation: Java custom annotation and dynamic loading
      Has an implementation in the question which just answers your question.
    • Annotation: Scanning Java annotations at runtime
    • Interface: Find Java classes implementing an interface
    • Interface: Is something similar to ServiceLoader in Java 1.5?
    • Interface: How can I get a list of all the implementations of an interface programmatically in Java?
    • Interface: Since the approach is expensive, maybe the ServiceLoader is a compromise between execution time and comfort, since it loads only the classes given in the services file. On the other hand if only classes with a certain interface are in your package then the ServiceLoader isn't that faster.

    2) AndroidAnnotations

    I would prefer the way AndroidAnnotations work (maybe an integration in AndroidAnnotations is the preferable way): It automatically adds an extra compilation step that generates source code, using the standard Java Annotation Processing Tool. So instead of runtime scanning you execute code based on the annotations generated during compile time.

    I think the Bean/EBean annotation could work for you (only single class): https://github.com/excilys/androidannotations/wiki/Enhance%20custom%20classes

    A scan-feature is not available, see this thread

    3) Writing your own annotation processor

    • See APT (Annotation Processing Tool). The idea would be to generate a static function which returns a list of classes which are annotated, so that no class scanning is needed.
    • A very good ressource is http://javadude.com/articles/annotations/index.html
    0 讨论(0)
  • 2020-12-30 17:47

    EDIT:

    I found this issue in the Android issue tracker. It appears that ClassLoader.getResource(String) is 'working as expected', in that it returns null. This is expected because the DalvikVM does not keep the resources around after compiling. There are workarounds listed in the issue, but there may be another way to access the classes you desire.

    Use the PackageManager to get a hold of an instance of ApplicationInfo. ApplicationInfo has a public field called sourceDir which is the full path (a String) to the location of the source directory for that application. Create a File from this String, and you should be able to navigate to your package within the source directory. Once there, you can use the method from my original answer to find the classes you are looking for.

    String applicationSourceDir = 
        getPackageManager().getApplicationInfo(androidPackageName, 0).sourceDir;
    

    /EDIT

    You should be able to use the ClassLoader.getResource(String) to get a URL to your specific package (the passed in String being the package name you are interested in delimited by path separators rather than periods). With this URL you can then call getFile(), from which you can create a Java File to the package folder. Call packageFile.listFiles() from there, and you have your classes/subpackages.

    Be recursive with the subpackages, and with the classes find the Class object using the static Class.forName(String) method.

    0 讨论(0)
提交回复
热议问题