3. HELLO
WE'RE MAKINGDEVS
We are programmers
We're NOT great so ware developers, but we do our best
Programming is our favorite job and hobbie
We're learning about many platforms
We really want to be so ware professionals
You can find us as 'makingdevs' almost on every social
network (GitHub, Twitter, Facebook)
5. DISCLAIMER
Everything can be done with Java, but really?
We're newbies with Android, so maybe you found novice's
errors
Prefer fully type static lang? Try Ceylon
We don't support the Mafia
We're available a er this talk
This talk just be not enough to all that we want to show
This presentation represents our brief experience
6. AGENDA
Our history in Android
So, what is Groovy?
Why Groovy? (If you don't know...)
Essentials in Groovy (The intro is here)
What can we do? (The code is here)
Facing problems
Conclusion
7. OUR HISTORY IN
ANDROID
A team programming for Web and Backend Services, now
has to make iOS and Android apps
10. WHY GROOVY?
3 million of downloads in 1 year
On Github since 2011(The same date as GoA born)
It's a dependency of 25000+ OSS Projects
Runs a JVM, Java code is valid code, but Groovy goes
beyond
Stop the suffer!!!
Java on Android is very verbose
Is OO, dynamic, functional, statically type checked and/or
compiled
Alex(Sascha) Klei is using it?
Boring vs. Fun!!!!
17. MODELS AND GROOVY BEANS
@CompileStatic
class Checkin implements Serializable {
Date created_at // Retrofit, you know!
String method
Date updated_at
@Bindable
S3Asset s3_asset
Barista baristum = new Barista()
// ... more properties
// No more getters and setters
}
29. @BINDABLE (2)
class SearchVenueFoursquareFragment extends Fragment {
GPSLocation mGPSLocation
@Override
void onCreate(@Nullable Bundle savedInstanceState) {
mGPSLocation = new GPSLocation()
mGPSLocation.addPropertyChangeListener { property ->
GPSLocation gpsLocation = property["source"] as GPSLocation
if (gpsLocation.latitude && gpsLocation.longitude) {
mFoursquareManager.getVenuesNear(new VenueCommand(latitude: gpsLocati
currentLatitude = gpsLocation.latitude
currentLongitude = gpsLocation.longitude
}
}
mLocationUtil.init(getActivity(), mGPSLocation)
}
}
30. @BINDABLE (3)
@CompileStatic
@Singleton
class LocationUtil implements GoogleApiClient.ConnectionCallbacks, GoogleApiC
GPSLocation mGPSLocation
void init(Context context, GPSLocation mGPSLocation){
this.mGPSLocation = mGPSLocation
// More init code
}
// A lot of methods
@Override
void onLocationChanged(Location location) {
mGPSLocation.setLatitude(location.getLatitude())
mGPSLocation.setLongitude(location.getLongitude())
}
}
31. TRAITS(1)
public class ShowCheckinFragment extends Fragment{
ImageView showImage
ImageUtil mImageUtil1 = new ImageUtil()
String pathPhoto
void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK) {
pathPhoto = data.getStringExtra("PATH_PHOTO")
mImageUtil1.setPhotoImageView(getContext(), pathPhoto, showImage)
}
}
}
}
Be careful we're using the getContext() of Fragment
32. TRAITS(2)
class FormCheckinFragment extends Fragment {
// The same...
}
class ProfileFragment extends Fragment {
// The same...
}
class BaristaFragment extends Fragment {
// The same...
}
34. TRAITS(3)
@CompileStatic
trait OnActivityResultGallery {
ImageView showImage
ImageUtil mImageUtil1 = new ImageUtil()
String pathPhoto
void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK) {
pathPhoto = data.getStringExtra("PATH_PHOTO")
mImageUtil1.setPhotoImageView(getContext(), pathPhoto, showImage)
}
}
}
abstract Context getContext()
}
Be careful anyway...
35. TRAITS(4)
class FormCheckinFragment
extends Fragment implements OnActivityResultGallery {
}
class ProfileFragment
extends Fragment implements OnActivityResultGallery {
}
class BaristaFragment
extends Fragment implements OnActivityResultGallery {
}
37. USING CAMERA
floatingActionButtonCamera.onClickListener = {
Fragment cameraFragment = new CameraFragment()
cameraFragment.setSuccessActionOnPhoto { File photo ->
getActivity().onBackPressed()
uploadPicture(photo)
}
cameraFragment.setErrorActionOnPhoto {
Toast.makeText(context, "Error al caputar la foto", Toast.LENGTH_SHORT)
getActivity().onBackPressed()
}
getFragmentManager()
.beginTransaction()
.replace(((ViewGroup) getView().getParent()).getId(), cameraFragmen
.addToBackStack(null).commit()
}
38. USING CAMERA(2)
class CameraFragment extends Fragment {
Closure successActionOnPhoto // Look ma!
Closure errorActionOnPhoto
@Override
void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_TAKE_PHOTO
&& resultCode == Activity.RESULT_OK) {
mImageUtil.addPictureToGallery(getContext(),photoFile.getPath())
Bitmap bitmapResize = mCamaraUtil.getScaledBitmap(photoFile.absolut
File photo = mCamaraUtil.saveBitmapToFile(bitmapResize,photoFile.ge
bitmapResize.recycle() // Stackoverflow!!!
successActionOnPhoto(photo)
} else {
errorActionOnPhoto()
}
}
// Handling the fragment and the camera
}
39. WHAT ELSE WE CAN DO?
RxJava
Test with Spock
Groovy extensions
Fastlane & CI & CD(Crashlytics)
40. WE FOUND SOME PATTERNS
BUILDING APPS
Model based design
KVO, KVC
Closure based design
Always use closures
41. FACING PROBLEMS (P1)
Groovy is dynamic
Bytecode is different
Classes at runtime?
64k method limit(solved with ProGuards)
Android Studio does not support Groovy 100%
42. FACING PROBLEMS (P2)
ABOUT THE DEXED FILES
Dalvik VM = new bytecode format
Groovy generates JVM bytecode
Translation don't through the dex
No native support for generating classes at runtime