[英]Robospice storing object that extends ArrayList in database via Ormlite
背景
我一直在嘗試修改Robospice Ormlite示例代碼 ,我已成功運行該代碼 。 我所做的唯一更改是我有一個包含對象數組的JSON響應。
我創建了2個類:
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類的結果。 任何建議都會很棒!
這個問題實際上並不是RoboSpice中的錯誤,而是ORM Lite模型的限制。
如果要使用ORMLite序列化Foo集合,則必須使用序列化作為Foo集合的類。 你接近是對的。 然而,你不能只是擺脫它來單獨存儲Foo元素。 您不僅需要使用Foos類來解析響應,還需要將數據存儲在數據庫中。
Foos應該:
問題是你不能注釋一個類並說“我是一個Foreig集合”。 此注釋只能用於字段,而不能用於類。 因此,如果你的班級將“持有”一個集合,那將是有效的,但不適用於“是一個”集合的類。
所以,我認為簡短的回答是:不,你不能用ORM Lite做到這一點。 你必須存儲像Foos這樣的頂級類,但它應該是ORM Lite的可序列化的,為此它需要有一個集合字段,而不能直接收集。
為了補充這個優秀的問題,我也遇到了這種“沉默的失敗”,並且不知道該怎么做。 我最終在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;
正如@Snicolas所說,你應該改為Collection而不是ArrayList。 我想做或多或少相同但沒有結果對象,我在這個問題上的解決方法RoboSpice堅持使用OrmLite的JSON數組應該適合你。
@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
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.