DexClassLoader - добавяне на функционалност

Правя някои тестове с DexClassLoader, за да видя дали е възможно да „актуализирам“ приложението си с нова функционалност. В момента имам този метод за тестване, който работи с testClass и изпълнява метода test(). Това, което бих искал да знам, е как мога да „заменя“ или „актуализирам“ и вече съществуващ клас..? Всякакви идеи или други предложения са добре дошли.

Метод:

    public static void loadExtLib(String pathDexFile, Context ctx) {

    String temp = ctx.getDir("temp", 0).toString();


        DexClassLoader classLoader = new DexClassLoader(pathDexFile,
                    temp, null, ctx.getClass().getClassLoader());


          String testClass = "com.mystudio.myapp.TestClass";
          Class<?> libProviderClass = null;
          try {
            libProviderClass = classLoader.loadClass(testClass);
        } catch (ClassNotFoundException e1) {

            e1.printStackTrace();
        }


          try {
            Method m = libProviderClass.getDeclaredMethod("test", null);
            try {
                m.invoke(libProviderClass, null);

            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e1) {
            e1.printStackTrace();
        }
          Log.v("loadClass", "loaded: " + testClass);


}

person olealgo    schedule 27.08.2013    source източник


Отговори (1)


Не можете да "замените" или "актуализирате" клас като цяло; само класове, заредени от DexClassLoader или един от неговите дъщерни зареждащи програми, ще могат изобщо да видят заредения клас. Не можете, например, да замените java.lang.String с версия, която прави престъпни неща, за да заобиколи ограниченията за сигурност в даден клас.

Това донякъде намалява полезността от зареждане на множество класове с едно и също име. От друга страна, той гарантира, че действията на зареждащия клас A са независими от действията на зареждащия клас B, стига единият да не е родител на друг.

Един възможен полезен подход за работа с класове, заредени по време на изпълнение, е да имате интерфейс, дефиниран в базовия зареждащ инструмент, който се изпълнява както от „стари“, така и от „нови“ версии на класа. Като се позовавате на екземпляри на класовете през интерфейса, избягвате факта, че "старият" код не може да види дефиницията на "новия" клас.

(Най-добрият начин да помислите за това е да маркирате мислено всеки клас с неговия зареждащ клас. Тогава е очевидно, че не можете да подадете String'new към функция, написана за String'old, но ако и двете имплементират CharSequence'old, тогава винаги можете да се обърнете към тях чрез че.)

Има малко код в тестовете на Dalvik, който упражнява "замяна" по време на изпълнение и може да бъде полезно да се прочете. Вижте тестовете на 068-classloader . Съдържанието на src и src-ex е вградено в отделни .jar файлове; последният се зарежда по време на изпълнение.

person fadden    schedule 27.08.2013
comment
Много полезна информация точно тук, fadden. Благодаря много :) Ще се опитам да премина през процеса на добавяне на нови класове (с различни имена) с актуализирана функционалност и да заменя класовете/методите, където се извикват, ако е налична нова функционалност. Това трябва да работи, надявам се. Ще пробвам поне :) - person olealgo; 27.08.2013