我对Android中GWT-RequestFactory的使用有疑问。作为一个起点,我使用了“创建一个AppEngine连接的Android-Project”-Wizard(信息:http://code.google.com/intl/de-DE/eclipse/docs/appengine_connected_android.html)中的代码,它运行得很好。
但是在我的情况下,我希望扩展此应用程序以使用带有SQLite的本地ContentProvider和带SyncAdapter的SyncService使用RequestFactory将ContentProvider中的数据同步到AppEngine。 现在我的问题如下:我可以打电话
MyRequestFactory requestFactory = Util.getRequestFactory(mContext, MyRequestFactory.class);
在我想要的任何活动中,将收到MyRequestFactory的实例。 (注意:Util是由向导创建的类。)但是如果我尝试从我的SyncAdapter进行相同的调用,我会得到一个 java.lang.RuntimeException:必须为com.hotool.client.MyRequestFactory RequestFactory类型“。
运行RequestFactory ValidationTool。也许您的信息: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 中 我认为,这可能是一个类加载器问题,但试图找出它没有成功。
我尝试使用ValidationTool,但首先它没有帮助,其次我发现,ValidationTool将生成的类已经到位(可能由于此处提到的注释处理:http://code.google.com/p/google-web-toolkit/wiki/RequestFactoryInterfaceValidation )
有人知道可能导致这种情况的原因吗?
非常感谢和最诚挚的问候。
Markus Neuenschwander
答案 0 :(得分:4)
你是对的Mark,这是一个类加载器问题。
它发生在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上的同步适配器调用时返回空值,因为同步适配器线程是由系统创建的,而不是由您的应用程序创建的。
我通过在创建requestfactory实例之前调用onPerformSync方法中的手动调用setContextClassLoader来解决这个问题:
@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);
// ...
}
我希望这是有道理的。 安德烈亚斯