Как использовать GWT-RequestFactory в Android SyncAdapter (всегда получая ValidationTool-Error)

Я получил вопрос об использовании GWT-RequestFactory в Android. В качестве отправной точки я использовал код из «Create a AppEngine connected Android-Project» -Wizard (информация: http://code.google.com/intl/de-DE/eclipse/docs/appengine_connected_android.html ), и он Отлично работал.

Но теперь в моем случае я хочу расширить это приложение, чтобы использовать локальный ContentProvider с SQLite, а SyncService с SyncAdapter синхронизировать данные из ContentProvider с AppEngine с помощью RequestFactory. Теперь моя проблема заключается в следующем: я могу позвонить

MyRequestFactory requestFactory = Util.getRequestFactory(mContext, MyRequestFactory.class); 

В любой деятельности, которую я хочу, и вы получите экземпляр MyRequestFactory. (Примечание: Util – это класс, созданный мастером.) Но если я попытаюсь сделать тот же вызов из моего SyncAdapter, я получу java.lang.RuntimeException: для com.hotool.client должен быть запущен RequestFactory ValidationTool. MyRequestFactory RequestFactory type ".

Возможно, для вашей информации: метод Util.getRequestFacory выглядит следующим образом:

 /** * Creates and returns an initialized {@link RequestFactory} of the given * type. */ public static <T extends RequestFactory> T getRequestFactory( Context context, Class<T> factoryClass) { T requestFactory = RequestFactorySource.create(factoryClass); SharedPreferences prefs = getSharedPreferences(context); String authCookie = prefs.getString(Util.AUTH_COOKIE, null); String uriString = Util.getBaseUrl(context) + RF_METHOD; URI uri; try { uri = new URI(uriString); } catch (URISyntaxException e) { Log.w(TAG, "Bad URI: " + uriString, e); return null; } requestFactory.initialize(new SimpleEventBus(), new AndroidRequestTransport(uri, authCookie)); return requestFactory; } 

Ошибка возникает в RequestFactorySource, который находится в файле requestfactory-client.jar. Я думаю, что это может быть проблема Class-Loader, но попытался понять это без успеха.

Я попытался использовать ValidationTool, но в первую очередь это не помогло, и, во-вторых, я обнаружил, что классы, созданные ValidationTool, уже созданы (возможно, благодаря обработке аннотаций, как упоминалось здесь: http://code.google. Com / p / google-web-toolkit / wiki / RequestFactoryInterfaceValidation )

Кто-нибудь может понять, что может это сделать?

Большое спасибо и с наилучшими пожеланиями.

Маркус Нойеншвандер

    Вы правы Марк, это проблема класса-загрузчика.

    Это происходит в requestfactory-client.jar, здесь соответствующий источник:

     class InProcessRequestFactory extends AbstractRequestFactory { //... public InProcessRequestFactory(Class<? extends RequestFactory> requestFactoryInterface) { this.requestFactoryInterface = requestFactoryInterface; deobfuscator = Deobfuscator.Builder.load(requestFactoryInterface, Thread.currentThread().getContextClassLoader()).build(); } //... } 

    а также

     public class Deobfuscator { //... public static class Builder { public static Builder load(Class<?> clazz, ClassLoader resolveClassesWith) { Throwable ex; try { Class<?> found; try { // Used by the server found = Class.forName(clazz.getName() + GENERATED_SUFFIX, false, resolveClassesWith); } catch (ClassNotFoundException ignored) { // Used by JRE-only clients found = Class.forName(clazz.getName() + GENERATED_SUFFIX_LITE, false, resolveClassesWith); } Class<? extends Builder> builderClass = found.asSubclass(Builder.class); Builder builder = builderClass.newInstance(); return builder; } catch (ClassNotFoundException e) { throw new RuntimeException("The RequestFactory ValidationTool must be run for the " + clazz.getCanonicalName() + " RequestFactory type"); } catch (InstantiationException e) { ex = e; } catch (IllegalAccessException e) { ex = e; } throw new RuntimeException(ex); } //... } 

    Проблема заключается в том, что Thread.currentThread (). GetContextClassLoader (), кажется, возвращает нулевое значение при вызове из адаптера синхронизации на Android, поскольку поток адаптера синхронизации создается системой, а не вашим приложением.

    Я решил это, вызвав вручную вызов setContextClassLoader в методе onPerformSync перед созданием экземпляра requestfactory:

     @Override public void onPerformSync(final Account account, Bundle extras, String authority, final ContentProviderClient provider, final SyncResult syncResult) { Thread.currentThread().setContextClassLoader(mContext.getClassLoader()); // ... MyRequestFactory requestFactory = Util.getRequestFactory(mContext, MyRequestFactory.class, acsidToken); // ... } 

    Я надеюсь в этом есть смысл. Andreas