Robospice存储对象,通过Ormlite在数据库中扩展ArrayList

时间:2013-04-04 01:57:58

标签: java android generics ormlite robospice

背景

我一直在尝试修改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类的结果。任何建议都会很棒!

3 个答案:

答案 0 :(得分:2)

这个问题在RoboSpice中并不是真正的错误,而是ORM Lite模型的限制。

如果要使用ORMLite序列化Foo集合,则必须使用序列化作为Foo集合的类。你接近是对的。然而,你不能只是摆脱它来单独存储Foo元素。您不仅需要使用Foos类来解析响应,还需要将数据存储在数据库中。

Foos应该:

  • 定义ID
  • 使用DataBaseTable和DataField以及Foreign collection
  • 进行注释

问题是你不能注释一个类并说“我是Foreig Collection”。此注释只能用于字段,而不能用于类。所以,如果你的班级“持有”一个集合,那将会奏效,但不适用于“是一个”集合的类。

所以,我认为简短的回答是:不,你不能用ORM Lite做到这一点。你必须保存一个顶级像FOOS,但它应该对ORM精简版可序列化,为此,它需要有一个集合场,并不能直接是一个集合。

答案 1 :(得分:2)

为了补充这个优秀的问题,我也遇到了这种“沉默的失败”,并且不知道该怎么做。 我最终在Android工作室内选择了查看logcat中的所有消息,因此不仅是android错误,而是一切。我选择“详细”和“无过滤器”来做到这一点。

logcat

当我运行我的应用程序时,我发现我收到无提示错误的原因是因为我没有为我的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
    ...
}