背景
我一直在尝试修改Robospice Ormlite example code,这是我成功运行的。我所做的唯一更改是我有一个包含对象数组的JSON响应。
我创建了两个类:
public class Foos extends ArrayList<Foo>
public class Foo
我遇到了初始问题,因为我的JSON响应是一个没有外部容器的纯数组。我通过谷歌小组了解到解决这个问题的方法是创建一个扩展ArrayList的“假”类(Foos)。这产生了以下代码:
public class FooRequest extends SpringAndroidSpiceRequest< Foos > {
private String baseUrl;
public FooRequest() {
super( Foos.class );
this.baseUrl = "http://somewhere.com/jsonurl";
}
@Override
public Foos loadDataFromNetwork() throws RestClientException {
Ln.d( "Call web service " + baseUrl );
return getRestTemplate().getForObject( baseUrl, Foos.class );
}
}
然后我创建了以下服务代码,改编自示例。
public class MySpiceService extends SpringAndroidSpiceService {
private static final int WEBSERVICES_TIMEOUT = 10000;
@Override
public CacheManager createCacheManager( Application application ) {
CacheManager cacheManager = new CacheManager();
List< Class< ? >> classCollection = new ArrayList< Class< ? >>();
// add persisted classes to class collection
classCollection.add( Foos.class );
// init
RoboSpiceDatabaseHelper databaseHelper = new RoboSpiceDatabaseHelper( application, "sample_database.db", 2 );
InDatabaseObjectPersisterFactory inDatabaseObjectPersisterFactory = new InDatabaseObjectPersisterFactory( application, databaseHelper, classCollection );
cacheManager.addPersister( inDatabaseObjectPersisterFactory );
return cacheManager;
}
@Override
public RestTemplate createRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
// set timeout for requests
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setReadTimeout( WEBSERVICES_TIMEOUT );
httpRequestFactory.setConnectTimeout( WEBSERVICES_TIMEOUT );
restTemplate.setRequestFactory( httpRequestFactory );
// web services support xml responses
MappingJacksonHttpMessageConverter jsonConverter = new MappingJacksonHttpMessageConverter();
FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
final List< HttpMessageConverter< ? >> listHttpMessageConverters = restTemplate.getMessageConverters();
listHttpMessageConverters.add( jsonConverter );
listHttpMessageConverters.add( formHttpMessageConverter );
listHttpMessageConverters.add( stringHttpMessageConverter );
restTemplate.setMessageConverters( listHttpMessageConverters );
return restTemplate;
}
}
问题
代码在没有任何强制关闭的情况下运行但是我从未在我的activity中触及RequestListener内部类。成功或失败消息方法都被触发,并且调试似乎很难,所以感觉就像是“静默失败”。
public final class MyRequestListener implements RequestListener< Foos > {
@Override
public void onRequestFailure( SpiceException spiceException ) {
Toast.makeText( SampleSpiceActivity.this, "failure", Toast.LENGTH_SHORT ).show();
}
@Override
public void onRequestSuccess( final Articles result ) {
Toast.makeText( SampleSpiceActivity.this, "success", Toast.LENGTH_SHORT ).show();
}
}
我尝试了什么
我试图用Ormlite注释来注释类Foo,看看这个库是否需要帮助,但仍然没有运气。如下所述:
@DatabaseTable
public class Foo {
@DatabaseField(generatedId = true)
private int id;
@DatabaseField
private String someText;
}
当我真正想要一个存储Foo的数据库表时,我想知道这是否是Foos类的结果。任何建议都会很棒!
答案 0 :(得分:2)
这个问题在RoboSpice中并不是真正的错误,而是ORM Lite模型的限制。
如果要使用ORMLite序列化Foo集合,则必须使用序列化作为Foo集合的类。你接近是对的。然而,你不能只是摆脱它来单独存储Foo元素。您不仅需要使用Foos类来解析响应,还需要将数据存储在数据库中。
Foos应该:
问题是你不能注释一个类并说“我是Foreig Collection”。此注释只能用于字段,而不能用于类。所以,如果你的班级“持有”一个集合,那将会奏效,但不适用于“是一个”集合的类。
所以,我认为简短的回答是:不,你不能用ORM Lite做到这一点。你必须保存一个顶级像FOOS,但它应该对ORM精简版可序列化,为此,它需要有一个集合场,并不能直接是一个集合。
答案 1 :(得分:2)
为了补充这个优秀的问题,我也遇到了这种“沉默的失败”,并且不知道该怎么做。 我最终在Android工作室内选择了查看logcat中的所有消息,因此不仅是android错误,而是一切。我选择“详细”和“无过滤器”来做到这一点。
当我运行我的应用程序时,我发现我收到无提示错误的原因是因为我没有为我的SQL生成唯一ID,这导致它被炸弹。
Caused by: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: post.ID (code 1555)
我通过在外部类ID字段上执行此操作来修复它,这允许它自己生成唯一ID:
@DatabaseField(allowGeneratedIdInsert=true, generatedId=true)
private int ID;
答案 2 :(得分:1)
正如@Snicolas所说,你应该改为Collection而不是ArrayList。我想或多或少地做同样但没有结果对象,我对这个问题RoboSpice persist JSON array with OrmLite的解决方法应该适合你。
@DatabaseTable
public class Foos {
@DatabaseField(id = true)
private int id;
@ForeignCollectionField(eager = false)
private Collection<Foo> result;
// getters and setters
...
}
@DatabaseTable
public class Foo {
@DatabaseField(id = true)
private int id;
@DatabaseField(foreign = true)
private Foos foos;
// getters and setters
...
}