SlideShare a Scribd company logo
1 of 18
Download to read offline
Storage, FileSystem & SQL
Storage, FileSystem & SQL
✦There are several ways to store data in
Codename One, in this lesson I’ll break them
down
✦Each option has tradeoffs that should be weighed
carefully
Storage
✦If you are unsure about what you want to use Storage
is probably the best place to start
✦It’s simplest. Like a flat file system
✦When an app is uninstalled it’s deleted (notice it might
be restored from backup on reinstall)
✦In some OS’s (and simulator) it is implemented on top
of the regular file system but that is an implementation
detail! Don’t rely on that!
✦Storage can be seamlessly encrypted
FileSystemStorage
✦A map of the native OS filesystem
✦Hierarchy based, always uses / as separator and
always requires full paths
✦Can contain special roots e.g. SD card, caches
✦Behavior is often OS specific
✦Because of the low level nature features like seamless
encryption aren’t available (although it’s possible to
encrypt anything)
Storage FileSystemStorage
Portable Access to native features
Flat Hierarchy, always use full paths
Cleaned on uninstall Behavior varies on uninstall
Private to application Potentially exposed in some locations
Cached access Direct access
Great for small (cachable) files Great for larger files
Which Should I Pick?
serverInstance.getItemsAsync(items -> {
shoppingList.removeAll();
shoppingList.add(filler);
ArrayList<Map<String, Object>> data = new ArrayList<>();
for(Item i : items) {
if(!i.isDeleted()) {
Component c = createCheck(i.getName(), i.isMarked());
shoppingList.add(c);
shoppingList.add(createSeparator());
data.add(i.toMap());
}
}
shoppingList.revalidate();
// cache the data
try(OutputStream os = Storage.getInstance().createOutputStream("CachedData")) {
Map<String, Object> m = new HashMap<>();
m.put("root", data);
os.write(Result.fromContent(m).toString().getBytes("UTF-8"));
} catch(IOException err) {
Log.e(err);
}
});
Caching Results from the Server
serverInstance.getItemsAsync(items -> {
shoppingList.removeAll();
shoppingList.add(filler);
ArrayList<Map<String, Object>> data = new ArrayList<>();
for(Item i : items) {
if(!i.isDeleted()) {
Component c = createCheck(i.getName(), i.isMarked());
shoppingList.add(c);
shoppingList.add(createSeparator());
data.add(i.toMap());
}
}
shoppingList.revalidate();
// cache the data
try(OutputStream os = Storage.getInstance().createOutputStream("CachedData")) {
Map<String, Object> m = new HashMap<>();
m.put("root", data);
os.write(Result.fromContent(m).toString().getBytes("UTF-8"));
} catch(IOException err) {
Log.e(err);
}
});
Caching Results from the Server
Progress Change
I replaced the removal of the
progress indicator as the list
can now include many
arbitrary entries
serverInstance.getItemsAsync(items -> {
shoppingList.removeAll();
shoppingList.add(filler);
ArrayList<Map<String, Object>> data = new ArrayList<>();
for(Item i : items) {
if(!i.isDeleted()) {
Component c = createCheck(i.getName(), i.isMarked());
shoppingList.add(c);
shoppingList.add(createSeparator());
data.add(i.toMap());
}
}
shoppingList.revalidate();
// cache the data
try(OutputStream os = Storage.getInstance().createOutputStream("CachedData")) {
Map<String, Object> m = new HashMap<>();
m.put("root", data);
os.write(Result.fromContent(m).toString().getBytes("UTF-8"));
} catch(IOException err) {
Log.e(err);
}
});
Caching Results from the Server
serverInstance.getItemsAsync(items -> {
shoppingList.removeAll();
shoppingList.add(filler);
ArrayList<Map<String, Object>> data = new ArrayList<>();
for(Item i : items) {
if(!i.isDeleted()) {
Component c = createCheck(i.getName(), i.isMarked());
shoppingList.add(c);
shoppingList.add(createSeparator());
data.add(i.toMap());
}
}
shoppingList.revalidate();
// cache the data
try(OutputStream os = Storage.getInstance().createOutputStream("CachedData")) {
Map<String, Object> m = new HashMap<>();
m.put("root", data);
os.write(Result.fromContent(m).toString().getBytes("UTF-8"));
} catch(IOException err) {
Log.e(err);
}
});
Caching Results from the Server
Storage
I’m storing the cached data
as JSON because I already
have the code that does that
transport
if(Storage.getInstance().exists("CachedData")) {
JSONParser.setUseLongs(true);
JSONParser p = new JSONParser();
try(Reader r = new InputStreamReader(Storage.getInstance().createInputStream("CachedData"), "UTF-8")) {
Map<String, Object> result = p.parseJSON(r);
List<Map<String, Object>> lst = (List<Map<String, Object>>)result.get("root");
for(Map<String, Object> itm : lst) {
Item i = new Item(itm);
if(!i.isDeleted()) {
Component c = createCheck(i.getName(), i.isMarked());
shoppingList.add(c);
shoppingList.add(createSeparator());
}
}
shoppingList.revalidate();
} catch(IOException err) {
Log.e(err);
}
} else {
Component ip = FlowLayout.encloseCenterMiddle(new InfiniteProgress());
shoppingList.add(ip);
}
Loading Cached Server Results
SQLite
© Codename One 2017 all rights reserved
SQLite
✦SQLite is a native C embeddable database engine
that’s available almost everywhere
✦It’s very customizable and as a result implementations
on various OS’s aren’t completely consistent
✦It’s available in Android, iOS, UWP & JavaScript
✦SQLite is useful if you need a “real” database on the
device where you can perform fast queries
SQLite Device Fragmentation
✦The Android version is threadsafe where the iOS
version is not e.g. even the GC can crash SQLite on
iOS if it closes a cursor from the GC thread
✦The Android & iOS versions handle transaction
isolation differently
✦In JavaScript you can’t ship an app with your own
database
Shipping an App With a Database
✦One of the common use cases for SQLite is to ship
an app with a ready made database (e.g. nutritional
database) within the JAR:
String path = Display.getInstance().getDatabasePath("MyDB.db");
if(path != null && !FileSystemStorage.getInstance().exists(path)) {
try(InputStream i = Display.getInstance().getResourceAsStream(getClass(), "/MyDB.db");
OutputStream o = FileSystemStorage.getInstance().openOutputStream(path)) {
Util.copy(i, o);
} catch(IOException err) {
Log.e(err);
}
}
Database db = null;
Cursor cur = null;
try {
db = Display.getInstance().openOrCreate("MyDB.db");
cur = db.executeQuery(sqlStatement);
while(cur.next()) {
Row r = cur.getRow();
String s = r.getString(cur.getColumnIndex("columnName"));
// ....
}
} catch(IOException err) {
Log.e(err);
ToastBar.showErrorMessage("Error: " + err);
} finally {
Util.cleanup(db);
Util.cleanup(cur);
}
Issue a Query
Database db = null;
Cursor cur = null;
try {
db = Display.getInstance().openOrCreate("MyDB.db");
cur = db.executeQuery(sqlStatement);
while(cur.next()) {
Row r = cur.getRow();
String s = r.getString(cur.getColumnIndex("columnName"));
// ....
}
} catch(IOException err) {
Log.e(err);
ToastBar.showErrorMessage("Error: " + err);
} finally {
Util.cleanup(db);
Util.cleanup(cur);
}
Issue a Query
Cleanup
It’s crucial to cleanup
properly. Otherwise on iOS
the app might crash as the
GC might cleanup before your
code causing a thread conflict
What did we learn?
✦When to choose file system storage and when to
choose storage
✦How to implement data caching/offline mode
using storage
✦The problems and value proposition of SQLite
Thank You

More Related Content

Similar to Storage, FileSystem & SQL.pdf

Matthew Vignau: Memory Management in SharePoint 2007 Development
Matthew Vignau: Memory Management in SharePoint 2007 DevelopmentMatthew Vignau: Memory Management in SharePoint 2007 Development
Matthew Vignau: Memory Management in SharePoint 2007 Development
SharePoint Saturday NY
 
OWB11gR2 - Extending ETL
OWB11gR2 - Extending ETL OWB11gR2 - Extending ETL
OWB11gR2 - Extending ETL
Suraj Bang
 
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NCAndroid Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Jim Tochterman
 
Offline strategies for HTML5 web applications - pfCongres2012
Offline strategies for HTML5 web applications - pfCongres2012Offline strategies for HTML5 web applications - pfCongres2012
Offline strategies for HTML5 web applications - pfCongres2012
Stephan Hochdörfer
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
Igor Bronovskyy
 
Sharepoint Saturday India Online best practice for developing share point sol...
Sharepoint Saturday India Online best practice for developing share point sol...Sharepoint Saturday India Online best practice for developing share point sol...
Sharepoint Saturday India Online best practice for developing share point sol...
Shakir Majeed Khan
 

Similar to Storage, FileSystem & SQL.pdf (20)

Matthew Vignau: Memory Management in SharePoint 2007 Development
Matthew Vignau: Memory Management in SharePoint 2007 DevelopmentMatthew Vignau: Memory Management in SharePoint 2007 Development
Matthew Vignau: Memory Management in SharePoint 2007 Development
 
Android | Busy Java Developers Guide to Android: Persistence | Ted Neward
Android | Busy Java Developers Guide to Android: Persistence | Ted NewardAndroid | Busy Java Developers Guide to Android: Persistence | Ted Neward
Android | Busy Java Developers Guide to Android: Persistence | Ted Neward
 
OWB11gR2 - Extending ETL
OWB11gR2 - Extending ETL OWB11gR2 - Extending ETL
OWB11gR2 - Extending ETL
 
Compass Framework
Compass FrameworkCompass Framework
Compass Framework
 
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NCAndroid Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
 
How do I - Storage, FileSystem & SQL - Transcript.pdf
How do I - Storage, FileSystem & SQL - Transcript.pdfHow do I - Storage, FileSystem & SQL - Transcript.pdf
How do I - Storage, FileSystem & SQL - Transcript.pdf
 
第一次用Parse就深入淺出
第一次用Parse就深入淺出第一次用Parse就深入淺出
第一次用Parse就深入淺出
 
Itemscript, a specification for RESTful JSON integration
Itemscript, a specification for RESTful JSON integrationItemscript, a specification for RESTful JSON integration
Itemscript, a specification for RESTful JSON integration
 
Assetic (Zendcon)
Assetic (Zendcon)Assetic (Zendcon)
Assetic (Zendcon)
 
Core Data with Swift 3.0
Core Data with Swift 3.0Core Data with Swift 3.0
Core Data with Swift 3.0
 
NoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices -  Michael HacksteinNoSQL meets Microservices -  Michael Hackstein
NoSQL meets Microservices - Michael Hackstein
 
Quick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase ServerQuick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase Server
 
Express Presentation
Express PresentationExpress Presentation
Express Presentation
 
Offline strategies for HTML5 web applications - pfCongres2012
Offline strategies for HTML5 web applications - pfCongres2012Offline strategies for HTML5 web applications - pfCongres2012
Offline strategies for HTML5 web applications - pfCongres2012
 
Bkbiet day2 & 3
Bkbiet day2 & 3Bkbiet day2 & 3
Bkbiet day2 & 3
 
Android Data Storagefinal
Android Data StoragefinalAndroid Data Storagefinal
Android Data Storagefinal
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 
Bubbles – Virtual Data Objects
Bubbles – Virtual Data ObjectsBubbles – Virtual Data Objects
Bubbles – Virtual Data Objects
 
Sharepoint Saturday India Online best practice for developing share point sol...
Sharepoint Saturday India Online best practice for developing share point sol...Sharepoint Saturday India Online best practice for developing share point sol...
Sharepoint Saturday India Online best practice for developing share point sol...
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 

More from ShaiAlmog1

More from ShaiAlmog1 (20)

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
 

Recently uploaded

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 

Storage, FileSystem & SQL.pdf

  • 2. Storage, FileSystem & SQL ✦There are several ways to store data in Codename One, in this lesson I’ll break them down ✦Each option has tradeoffs that should be weighed carefully
  • 3. Storage ✦If you are unsure about what you want to use Storage is probably the best place to start ✦It’s simplest. Like a flat file system ✦When an app is uninstalled it’s deleted (notice it might be restored from backup on reinstall) ✦In some OS’s (and simulator) it is implemented on top of the regular file system but that is an implementation detail! Don’t rely on that! ✦Storage can be seamlessly encrypted
  • 4. FileSystemStorage ✦A map of the native OS filesystem ✦Hierarchy based, always uses / as separator and always requires full paths ✦Can contain special roots e.g. SD card, caches ✦Behavior is often OS specific ✦Because of the low level nature features like seamless encryption aren’t available (although it’s possible to encrypt anything)
  • 5. Storage FileSystemStorage Portable Access to native features Flat Hierarchy, always use full paths Cleaned on uninstall Behavior varies on uninstall Private to application Potentially exposed in some locations Cached access Direct access Great for small (cachable) files Great for larger files Which Should I Pick?
  • 6. serverInstance.getItemsAsync(items -> { shoppingList.removeAll(); shoppingList.add(filler); ArrayList<Map<String, Object>> data = new ArrayList<>(); for(Item i : items) { if(!i.isDeleted()) { Component c = createCheck(i.getName(), i.isMarked()); shoppingList.add(c); shoppingList.add(createSeparator()); data.add(i.toMap()); } } shoppingList.revalidate(); // cache the data try(OutputStream os = Storage.getInstance().createOutputStream("CachedData")) { Map<String, Object> m = new HashMap<>(); m.put("root", data); os.write(Result.fromContent(m).toString().getBytes("UTF-8")); } catch(IOException err) { Log.e(err); } }); Caching Results from the Server
  • 7. serverInstance.getItemsAsync(items -> { shoppingList.removeAll(); shoppingList.add(filler); ArrayList<Map<String, Object>> data = new ArrayList<>(); for(Item i : items) { if(!i.isDeleted()) { Component c = createCheck(i.getName(), i.isMarked()); shoppingList.add(c); shoppingList.add(createSeparator()); data.add(i.toMap()); } } shoppingList.revalidate(); // cache the data try(OutputStream os = Storage.getInstance().createOutputStream("CachedData")) { Map<String, Object> m = new HashMap<>(); m.put("root", data); os.write(Result.fromContent(m).toString().getBytes("UTF-8")); } catch(IOException err) { Log.e(err); } }); Caching Results from the Server Progress Change I replaced the removal of the progress indicator as the list can now include many arbitrary entries
  • 8. serverInstance.getItemsAsync(items -> { shoppingList.removeAll(); shoppingList.add(filler); ArrayList<Map<String, Object>> data = new ArrayList<>(); for(Item i : items) { if(!i.isDeleted()) { Component c = createCheck(i.getName(), i.isMarked()); shoppingList.add(c); shoppingList.add(createSeparator()); data.add(i.toMap()); } } shoppingList.revalidate(); // cache the data try(OutputStream os = Storage.getInstance().createOutputStream("CachedData")) { Map<String, Object> m = new HashMap<>(); m.put("root", data); os.write(Result.fromContent(m).toString().getBytes("UTF-8")); } catch(IOException err) { Log.e(err); } }); Caching Results from the Server
  • 9. serverInstance.getItemsAsync(items -> { shoppingList.removeAll(); shoppingList.add(filler); ArrayList<Map<String, Object>> data = new ArrayList<>(); for(Item i : items) { if(!i.isDeleted()) { Component c = createCheck(i.getName(), i.isMarked()); shoppingList.add(c); shoppingList.add(createSeparator()); data.add(i.toMap()); } } shoppingList.revalidate(); // cache the data try(OutputStream os = Storage.getInstance().createOutputStream("CachedData")) { Map<String, Object> m = new HashMap<>(); m.put("root", data); os.write(Result.fromContent(m).toString().getBytes("UTF-8")); } catch(IOException err) { Log.e(err); } }); Caching Results from the Server Storage I’m storing the cached data as JSON because I already have the code that does that transport
  • 10. if(Storage.getInstance().exists("CachedData")) { JSONParser.setUseLongs(true); JSONParser p = new JSONParser(); try(Reader r = new InputStreamReader(Storage.getInstance().createInputStream("CachedData"), "UTF-8")) { Map<String, Object> result = p.parseJSON(r); List<Map<String, Object>> lst = (List<Map<String, Object>>)result.get("root"); for(Map<String, Object> itm : lst) { Item i = new Item(itm); if(!i.isDeleted()) { Component c = createCheck(i.getName(), i.isMarked()); shoppingList.add(c); shoppingList.add(createSeparator()); } } shoppingList.revalidate(); } catch(IOException err) { Log.e(err); } } else { Component ip = FlowLayout.encloseCenterMiddle(new InfiniteProgress()); shoppingList.add(ip); } Loading Cached Server Results
  • 11. SQLite © Codename One 2017 all rights reserved
  • 12. SQLite ✦SQLite is a native C embeddable database engine that’s available almost everywhere ✦It’s very customizable and as a result implementations on various OS’s aren’t completely consistent ✦It’s available in Android, iOS, UWP & JavaScript ✦SQLite is useful if you need a “real” database on the device where you can perform fast queries
  • 13. SQLite Device Fragmentation ✦The Android version is threadsafe where the iOS version is not e.g. even the GC can crash SQLite on iOS if it closes a cursor from the GC thread ✦The Android & iOS versions handle transaction isolation differently ✦In JavaScript you can’t ship an app with your own database
  • 14. Shipping an App With a Database ✦One of the common use cases for SQLite is to ship an app with a ready made database (e.g. nutritional database) within the JAR: String path = Display.getInstance().getDatabasePath("MyDB.db"); if(path != null && !FileSystemStorage.getInstance().exists(path)) { try(InputStream i = Display.getInstance().getResourceAsStream(getClass(), "/MyDB.db"); OutputStream o = FileSystemStorage.getInstance().openOutputStream(path)) { Util.copy(i, o); } catch(IOException err) { Log.e(err); } }
  • 15. Database db = null; Cursor cur = null; try { db = Display.getInstance().openOrCreate("MyDB.db"); cur = db.executeQuery(sqlStatement); while(cur.next()) { Row r = cur.getRow(); String s = r.getString(cur.getColumnIndex("columnName")); // .... } } catch(IOException err) { Log.e(err); ToastBar.showErrorMessage("Error: " + err); } finally { Util.cleanup(db); Util.cleanup(cur); } Issue a Query
  • 16. Database db = null; Cursor cur = null; try { db = Display.getInstance().openOrCreate("MyDB.db"); cur = db.executeQuery(sqlStatement); while(cur.next()) { Row r = cur.getRow(); String s = r.getString(cur.getColumnIndex("columnName")); // .... } } catch(IOException err) { Log.e(err); ToastBar.showErrorMessage("Error: " + err); } finally { Util.cleanup(db); Util.cleanup(cur); } Issue a Query Cleanup It’s crucial to cleanup properly. Otherwise on iOS the app might crash as the GC might cleanup before your code causing a thread conflict
  • 17. What did we learn? ✦When to choose file system storage and when to choose storage ✦How to implement data caching/offline mode using storage ✦The problems and value proposition of SQLite