Post on 14-Apr-2017
FROM GRAILS TO ANDROID A SIMPLE JOURNEY
GRAILS
@BRWNGRLDEV
ANDROID
@BRWNGRLDEV
OVERVIEW
@BRWNGRLDEV
OVERVIEW
▸Project Structure
@BRWNGRLDEV
OVERVIEW
▸Project Structure
▸User Interface
@BRWNGRLDEV
OVERVIEW
▸Project Structure
▸User Interface
▸Dependency Injection
@BRWNGRLDEV
OVERVIEW
▸Project Structure
▸User Interface
▸Dependency Injection
▸Persistence
@BRWNGRLDEV
PROJECT STRUCTURE@BRWNGRLDEV
GRAILS APP STRUCTURE
grails create-app
@BRWNGRLDEV
GRAILS APP STRUCTURE
grails create-app
@BRWNGRLDEV
GRAILS APP STRUCTURE
@BRWNGRLDEV
ANDROID APP STRUCTURE
@BRWNGRLDEV
ANDROID APP STRUCTURE
@BRWNGRLDEV
ANDROID APP STRUCTURE
@BRWNGRLDEV
▸app directory
ANDROID APP STRUCTURE
@BRWNGRLDEV
▸app directory
▸test directories
ANDROID APP STRUCTURE
@BRWNGRLDEV
▸app directory
▸test directories
▸gradle wrapper
ANDROID APP STRUCTURE
@BRWNGRLDEV
ANDROID APP STRUCTURE
@BRWNGRLDEV
most source code
ANDROID APP STRUCTURE
@BRWNGRLDEV
images
ANDROID APP STRUCTURE
@BRWNGRLDEV
views
ANDROID APP STRUCTURE
@BRWNGRLDEV
launcher icons
LAUNCHER ICONS
@BRWNGRLDEV
https://developer.android.com/guide/practices/ui_guidelines/icon_design_launcher.html
ANDROID APP STRUCTURE
@BRWNGRLDEV
strings, colors, sizes, etc.
DOMAIN MODELS
@BRWNGRLDEV
GRAILS DOMAIN CLASS
@BRWNGRLDEV
GRAILS DOMAIN CLASS
@BRWNGRLDEV
▸BookSpec
▸BookController
▸BookControllerSpec
▸/book/edit.gsp
▸/book/create.gsp
▸/book/index.gsp
▸/book/show.gsp
ANDROID DOMAIN CLASS
@BRWNGRLDEV
ANDROID DOMAIN CLASS
@BRWNGRLDEV
▸Book
ANDROID DOMAIN CLASS
@BRWNGRLDEV
▸Book
ANDROID DOMAIN CLASS
@BRWNGRLDEV
ANDROID DOMAIN CLASS
@BRWNGRLDEV
ANDROID DOMAIN CLASS
@BRWNGRLDEV
MVP
ANDROID DOMAIN CLASS
@BRWNGRLDEV
▸BookTest
▸BookPresenter
▸BookPresenterTest
▸BookView
▸BookActivity
▸BookActivityTest
▸activity_book.xml
▸activity_insert_update_book.xml
@BRWNGRLDEV
CONFIGURATION
@BRWNGRLDEV
GRAILS - BUILD.GRADLE
@BRWNGRLDEV
GRAILS - BUILD.GRADLE
@BRWNGRLDEV
ANDROID - BUILD.GRADLE
@BRWNGRLDEV
ANDROID - BUILD.GRADLE
@BRWNGRLDEV
ANDROID - BUILD.GRADLE
@BRWNGRLDEV
GRADLE COMMANDS
@BRWNGRLDEV
▸gradle tasks
▸gradle clean
▸gradle test
▸gradle assemble
GRADLE COMMANDS
@BRWNGRLDEV
▸gradle tasks
▸gradle clean
▸gradle test
▸gradle assemble
PROJECT STRUCTURE
@BRWNGRLDEV
▸Folder layout
▸Domain models
▸Gradle Configuration
@BRWNGRLDEV
USER INTERFACE@BRWNGRLDEV
GRAILS UI
@BRWNGRLDEV
GRAILS GSP PAGE
@BRWNGRLDEV
GRAILS GSP PAGE
@BRWNGRLDEV
GRAILS GSP PAGE
@BRWNGRLDEV
GRAILS GSP PAGE
@BRWNGRLDEV
GRAILS GSP PAGE
@BRWNGRLDEV
<f:display bean=“book”/>
ANDROID UI
@BRWNGRLDEV
ANDROID UI
@BRWNGRLDEV
@BRWNGRLDEV
XML?!
ARE YOU KIDDING ME?!!!
@BRWNGRLDEV
XML?!
ARE YOU KIDDING ME?!!!
@BRWNGRLDEV
XML?!
ARE YOU KIDDING ME?!!!
@BRWNGRLDEV
XML?!
ARE YOU KIDDING ME?!!!
ANDROID LAYOUT GUI
@BRWNGRLDEV
ANDROID LAYOUT GUI
@BRWNGRLDEV
ANDROID LAYOUT GUI
@BRWNGRLDEV
ANDROID XML LAYOUT
@BRWNGRLDEV
ANDROID XML LAYOUT
@BRWNGRLDEV
ANDROID XML LAYOUT
@BRWNGRLDEV
ANDROID XML LAYOUT
@BRWNGRLDEV
STYLE & SIZE RESOURCES
@BRWNGRLDEV
STYLE & SIZE RESOURCES
@BRWNGRLDEV
STYLE & SIZE RESOURCES
@BRWNGRLDEV
STYLE & SIZE RESOURCES
@BRWNGRLDEV
STYLE & SIZE RESOURCES
@BRWNGRLDEV
▸colors
▸styles
▸strings
▸sizes
▸themes
STYLE & SIZE RESOURCES
@BRWNGRLDEV
strings, colors, sizes, etc.
https://www.flickr.com/photos/bionicteaching/14668480106
https://developer.android.com/training/basics/supporting-devices/screens.html
DEVELOPER DOCS
@BRWNGRLDEV
USER INTERFACE
@BRWNGRLDEV
▸GSP pages
▸XML layout
▸Resource folders
@BRWNGRLDEV
DEPENDENCY INJECTION
@BRWNGRLDEV
DEPENDENCY INJECTION
@BRWNGRLDEV
THE CLIENT DELEGATES TO EXTERNAL CODE (THE INJECTOR) THE RESPONSIBILITY OF
PROVIDING ITS DEPENDENCIES. https://en.wikipedia.org/wiki/Dependency_injection
GRAILS - DEPENDENCY INJECTION
@BRWNGRLDEV
GRAILS - DEPENDENCY INJECTION
@BRWNGRLDEV
GRAILS - DEPENDENCY INJECTION
@BRWNGRLDEV
GRAILS - DEPENDENCY INJECTION
@BRWNGRLDEV
ANDROID - SIMPLE APPROACH
@BRWNGRLDEV
public class Injector {
}
ANDROID - SIMPLE APPROACH
@BRWNGRLDEV
public class Injector { private static BookService bookService;
}
ANDROID - SIMPLE APPROACH
@BRWNGRLDEV
public class Injector { private static BookService bookService;
public static BookService provideBookService () { if ( bookService == null ) { bookService = new BookService(); } return bookService;}
}
ANDROID - SIMPLE APPROACH
@BRWNGRLDEV
public class Activity { private BooksPresenter booksPresenter;
@Overrideprotected void onCreate (Bundle savedInstanceState) { …
booksPresenter = new BooksPresenter( Injector.provideBookService() ); }
}
ANDROID - DAGGER
@BRWNGRLDEV
http://google.github.io/dagger/
ANDROID - DAGGER
@BRWNGRLDEV
public class BooksPresenter { private final BookService bookService;
}
ANDROID - DAGGER
@BRWNGRLDEV
public class BooksPresenter { private final BookService bookService;
@Inject BooksPresenter(BookService bookService) {
this.bookService = bookService; }
}
ANDROID - DAGGER
@BRWNGRLDEV
@Module public class AppModule {
}
ANDROID - DAGGER
@BRWNGRLDEV
@Module public class AppModule {
@Provides @Singleton BookService provideBookService() {
return new BookService(); }
}
ANDROID - DAGGER
@BRWNGRLDEV
@Provides @Singleton BookService provideBookService() {
return new BookService(); }
@Inject BooksPresenter(BookService bookService) {
this.bookService = bookService; }
DEPENDENCY INJECTION
@BRWNGRLDEV
▸Spring
▸Simple Injector
▸Dagger
@BRWNGRLDEV
PERSISTENCE@BRWNGRLDEV
@BRWNGRLDEVhttp://gorm.grails.org/latest/
@BRWNGRLDEV
GORMdef book = new Book(title: ‘Clean Code’)
book.save()
@BRWNGRLDEV
GORMdef book = new Book(title: ‘Clean Code’)
book.save()
def book = Book.findByTitle(‘Clean Code’)
println book
@BRWNGRLDEV
GORMdef book = new Book(title: ‘Clean Code’)
book.save()
def book = Book.findByTitle(‘Clean Code’)
println book
def book = Book.get(1)
book.delete()
https://developer.android.com/training/basics/data-storage/databases.html
ANDROID
@BRWNGRLDEV
https://developer.android.com/training/basics/data-storage/databases.html
ANDROID
@BRWNGRLDEV
SQLITE
@BRWNGRLDEV
SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLITE
@BRWNGRLDEV
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues(); values.put(COLUMN_NAME_TITLE, title);
SQLITE
@BRWNGRLDEV
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues(); values.put(COLUMN_NAME_TITLE, title);
db.insert( TABLE_NAME, null, values);
SQLITE VS. GORM
@BRWNGRLDEV
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues(); values.put(COLUMN_NAME_TITLE, title);
db.insert( TABLE_NAME, null, values);
def book = new Book(title: ‘Clean Code’)
book.save()
REALM
@BRWNGRLDEVhttp://realm.io
REALM
@BRWNGRLDEV
REALM
@BRWNGRLDEV
▸Easy to Set Up
REALM
@BRWNGRLDEV
▸Easy to Set Up
▸Faster than ORMs
REALM
@BRWNGRLDEV
▸Easy to Set Up
▸Faster than ORMs
▸Has a Fluent API
REALM - CREATING A RECORD
@BRWNGRLDEV
realm.executeTransaction( new Realm.Transaction() { @Override public void execute (Realm realm) { Book book = realm.createObject(Book.class); book.setTitle(“Clean Code"); }} );
REALM - CREATING A RECORD
@BRWNGRLDEV
realm.executeTransaction( new Realm.Transaction() { @Override public void execute (Realm realm) { Book book = realm.createObject(Book.class); book.setTitle(“Clean Code"); }} );
REALM - QUERY
@BRWNGRLDEV
RealmResults<Book> results = realm.where(Book.class) .equalTo("title", “Clean Code") .or() .equalTo("title", “Clean Codez") .findAll();
REALM - QUERY
@BRWNGRLDEV
RealmResults<Book> results = realm.where(Book.class) .equalTo("title", “Clean Code") .or() .equalTo("title", “Clean Codez") .findAll();
REALM - CHANGE LISTENERS
@BRWNGRLDEV
bookListener = new RealmChangeListener() { @Override public void onChange(Book book) { // make changes }};
REALM - CHANGE LISTENERS
@BRWNGRLDEV
bookListener = new RealmChangeListener() { @Override public void onChange(Book book) { // make changes }};
book = realm.where(Book.class).equalTo("id", 1).findFirst(); book.addChangeListener(bookListener);
PERSISTENCE
@BRWNGRLDEV
▸GORM
▸Sqlite
▸Realm
@BRWNGRLDEV
SUMMARY
@BRWNGRLDEV
SUMMARY
▸Project Structure
@BRWNGRLDEV
SUMMARY
▸Project Structure
▸User Interface
@BRWNGRLDEV
SUMMARY
▸Project Structure
▸User Interface
▸Dependency Injection
@BRWNGRLDEV
SUMMARY
▸Project Structure
▸User Interface
▸Dependency Injection
▸Persistence
@BRWNGRLDEV
KEY TAKEAWAY
@BRWNGRLDEV
KEY TAKEAWAY
@BRWNGRLDEV
ANDROID IS REALLY HARD!
KEY TAKEAWAY
@BRWNGRLDEV
ANDROID IS REALLY HARD!FUN