Java – RoboSpice and ORMLite – Access data

RoboSpice and ORMLite – Access data… here is a solution to the problem.

RoboSpice and ORMLite – Access data

I just started using RoboSpice for a new Android app. RoboSpice is used with ORMLite and SpringAndroidSpiceService to read JSON from REST web services.

For now, I managed to:

  • Create a custom SpiceService
  • Requests for data from WS are rare
  • Use ORMLite to save data to a database

… Thanks to “robospice-sample-ormlite” sample .

The main part of my app (question at the bottom):

The underlying activity

public abstract class BaseActivity extends RoboActivity {

private SpiceManager spiceManager = new SpiceManager(MySpiceService.class);

@Override
    protected void onStart() {
        super.onStart();
        spiceManager.start(this);
    }

@Override
    protected void onStop() {
        if (spiceManager.isStarted()) {
            spiceManager.shouldStop();
        }
        super.onStop();
    }

protected SpiceManager getSpiceManager() {
        return spiceManager;
    }

}

SplashActivity

public class SplashActivity extends BaseActivity {
    ...
    @Override
    protected void onStart() {
        super.onStart();
        ...
        getSpiceManager().execute(foosRequest, new Integer(0), DurationInMillis.ONE_HOUR, new FoosRequestListener());
        getSpiceManager().execute(barsRequest, new Integer(1), DurationInMillis.ONE_HOUR, new BarsRequestListener());

 Start MainActivity after X seconds (handler + startActivity(intent...)
        ...
    }

public final class FoosRequestListener implements RequestListener<Foos> {
        @Override
        public void onRequestFailure(SpiceException spiceException) {
            Toast.makeText(MainActivity.this, "failure foo", Toast.LENGTH_SHORT).show();
        }

@Override
        public void onRequestSuccess(final Days result) {
            Toast.makeText(MainActivity.this, "success foo", Toast.LENGTH_SHORT).show();
            String originalText = getString(R.string.textview_text);
            mLoremTextView.setText(originalText + result.getResult().iterator().next().getMoonrise());
        }
    }

public final class BarsRequestListener implements RequestListener<Bars> {
        @Override
        public void onRequestFailure(SpiceException spiceException) {
            Toast.makeText(MainActivity.this, "failure bars", Toast.LENGTH_SHOR ).show();
        }

@Override
        public void onRequestSuccess(final Months result) {
            Toast.makeText(MainActivity.this, "success bars", Toast.LENGTH_SHORT).show();
        }
    }
}

MySpiceService

public class MySpiceService extends SpringAndroidSpiceService {
    ...
    @Override
    public CacheManager createCacheManager(Application application) throws CacheCreationException {
        CacheManager cacheManager = new CacheManager();
        List<Class<?>> classCollection = new ArrayList< Class< ? >>();

 Add persisted classe(s) to class collection
        classCollection.add(Foos.class);  Collection of "Foo"
        classCollection.add(Foo.class);
        classCollection.add(Bars.class);  Collection of "Bars"
        classCollection.add(Bar.class);

 Init
        RoboSpiceDatabaseHelper databaseHelper = new RoboSpiceDatabaseHelper(application, DATABASE_NAME, DATABASE_VERSION);
        InDatabaseObjectPersisterFactory inDatabaseObjectPersisterFactory = new InDatabaseObjectPersisterFactory(application, databaseHelper, classCollection);
        cacheManager.addPersister(inDatabaseObjectPersisterFactory);

return cacheManager;
    }

@Override
    public RestTemplate createRestTemplate() {
        ...
        return restTemplate;
    }
}

An application consists of a splash activity and other activities. The splash screen starts the MainActivity after a few seconds (currently just a timer).

What I want to do is download all the data from the splash screen (RoboSpice already caches/saves this data in the SQLite database) and then accesses it from other activities.


Question 1:
Can I access and manipulate database data outside of SplashActivity? How (can you provide some code examples)?

The Wiki page I’m not very clear about “RoboSpiceDataBaseHelper”: it is said that “RoboSpiceDataBaseHelper is used to manage database creation and version management”, but in the next paragraph it is pointed out that certain methods allow “querying and retrieving data from the database”. In the RoboSpice sample, there is no content about retrieving data from other activities. How can I harness the power of ORMLite?

I’ve read this Google Groups topic from Snicolas:

Note that RoboSpice caching is meant to be transparent and is completely encapsulated in the SpiceService. It should be possilbe to access the cache system (in your case the databse) directly through a shared reference to it (shared by the service and your activities). Also, in that case, nothing will prevent side-effects like concurrent access or database inconsistency.

So, what to do?
I’m totally lost 🙁

Edit 03/01: Due to my lack of RoboSpice and ORMLite capabilities, I’m confused about how to implement such a solution/how to do it myself (at least it works). I don’t know how to use/combine RoboSpiceDatabaseHelper, InDatabaseObjectPersister, InDatabaseObjectPersisterFactory….


Question 2:

My last question has nothing to do with data access (I’m asking with this topic).

Why does getSpiceManager().execute(barsRequest, new Integer(1), DurationInMillis.ONE_HOUR, null) do nothing (no callback to RequestListener)? In fact, in my case (splash screen), I don’t need callbacks. Can I avoid it?


Thanks!

Solution

Question 1:

You must share RoboSpiceDatabaseHelper between your service and the place where you want to access it.

The cleanest way is to use an inject framework like RoboGuice. A quick and dirty hack is to create a static provider for this instance, or even dirtier and faster, making RoboSpiceDatabaseHelper a singleton.

— update

When using RoboGuice, you can:

Create your own RoboSpiceDatabaseHelper class and annotate it with @Singleton:

@Singleton
public class MyRoboSpiceDatabaseHelper extends RoboSpiceDatabaseHelper {
...
}

In your spiceservice and classes that need access to the database, you can declare a member:

@Inject
RoboSpiceDatabaseHelper databaseHelper;

You will then get a suitable singleton that allows you to share database access.

Question 2:

If you really need to do it quickly, just create a stub/virtual listener. RS does not execute requests without a listener.

Related Problems and Solutions