SlideShare a Scribd company logo
Android Design
Patterns
Godfrey Nolan
Android Application Architecture (Android Dev Summit) https://www.youtube.com/watch?v=BlkJzgjzL0c
What is Your Goal?
Scalable
Maintainable
Testing
What is Your Goal?
Scalable
Add new features quickly
Maintainable
No spaghetti code
Don't cross the streams
Testing
Easy to mock
Why?
Easier to add new features
Easier to understand
Easier to police
Make our life easier
Make Unit Testing easier
How do we get there?
https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
Classic Android
View Model
https://github.com/konmik/konmik.github.io/wiki/Introduction-to-Model-View-Presenter-on-Android
package alexandria.israelferrer.com.libraryofalexandria;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.TextView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.squareup.picasso.Picasso;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
public class MainActivity extends Activity {
private static final String PACKAGE = "com.israelferrer.alexandria";
private static final String KEY_FAVS = PACKAGE + ".FAVS";
private List<ArtWork> artWorkList;
private ArtWorkAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listView);
InputStream stream = getResources().openRawResource(R.raw.artwork);
Type listType = new TypeToken<List<ArtWork>>() {
}.getType();
artWorkList = new Gson().fromJson(new InputStreamReader(stream), listType);
final SharedPreferences preferences = getSharedPreferences(getPackageName()
, Context.MODE_PRIVATE);
for (ArtWork artWork : artWorkList) {
artWork.setRating(preferences.getFloat(PACKAGE + artWork.getId(), 0F));
}
adapter = new ArtWorkAdapter();
listView.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.filter) {
adapter.orderMode();
return true;
}
return super.onOptionsItemSelected(item);
}
private class ArtWorkAdapter extends BaseAdapter {
private boolean isOrder;
private final List<ArtWork> orderedList;
public ArtWorkAdapter() {
super();
orderedList = new LinkedList<ArtWork>();
}
@Override
public int getCount() {
return artWorkList.size();
}
@Override
public Object getItem(int position) {
return artWorkList.get(position);
}
@Override
public long getItemId(int position) {
return Long.valueOf(artWorkList.get(position).getId());
}
public void orderMode() {
isOrder = !isOrder;
if (isOrder) {
orderedList.clear();
orderedList.addAll(artWorkList);
Collections.sort(orderedList);
notifyDataSetChanged();
} else {
notifyDataSetChanged();
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ArtWork artWork;
if (isOrder) {
artWork = orderedList.get(position);
} else {
artWork = artWorkList.get(position);
}
View row;
switch (artWork.getType()) {
case ArtWork.QUOTE:
row = getLayoutInflater().inflate(R.layout.text_row, null);
TextView quote = (TextView) row.findViewById(R.id.quote);
TextView author = (TextView) row.findViewById(R.id.author);
quote.setText(""" + artWork.getText() + """);
author.setText(artWork.getAuthor());
break;
case ArtWork.PAINTING:
final SharedPreferences preferences = getSharedPreferences(getPackageName()
, Context.MODE_PRIVATE);
final HashSet<String> favs = (HashSet<String>) preferences
.getStringSet(KEY_FAVS,
new HashSet<String>());
row = getLayoutInflater().inflate(R.layout.painting_row, null);
ImageView image = (ImageView) row.findViewById(R.id.painting);
TextView painter = (TextView) row.findViewById(R.id.author);
painter.setText(artWork.getTitle() + " by " + artWork.getAuthor());
Picasso.with(MainActivity.this).load(artWork.getContentUrl()).fit()
.into(image);
RatingBar rating = (RatingBar) row.findViewById(R.id.rate);
rating.setRating(artWork.getRating());
rating.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float rating,
boolean fromUser) {
preferences.edit().putFloat(PACKAGE + artWork.getId(), rating).apply();
artWork.setRating(rating);
}
});
CheckBox fav = (CheckBox) row.findViewById(R.id.fav);
fav.setChecked(favs.contains(artWork.getId()));
fav.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final HashSet<String> favs = new HashSet<String>((HashSet<String>)
preferences
.getStringSet(KEY_FAVS,
new HashSet<String>()));
if (isChecked) {
favs.add(artWork.getId());
} else {
favs.remove(artWork.getId());
}
preferences.edit().putStringSet(KEY_FAVS,
favs).apply();
}
});
break;
case ArtWork.MOVIE:
case ArtWork.OPERA:
row = new ViewStub(MainActivity.this);
break;
default:
row = getLayoutInflater().inflate(R.layout.text_row, null);
}
return row;
}
}
}
Classic Android
Pros
Better the devil you know
Cons
Activities and Fragments quickly become large
Painful to make changes or add new features
All the logic in Activities, unit testing is impossible
Classic Android is not MVC
MVC
https://medium.com/@tinmegali/model-view-presenter-mvp-in-android-part-1-441bfd7998fe#.d19x8cido
http://androidexample.com/Use_MVC_Pattern_To_Create_Very_Basic_Shopping_Cart__-_Android_Example
package com.androidexample.mvc;
//imports
public class FirstScreen extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firstscreen);
final LinearLayout lm = (LinearLayout) findViewById(R.id.linearMain);
final Button secondBtn = (Button) findViewById(R.id.second);
//Get Global Controller Class object (see application tag in AndroidManifest.xml)
final Controller aController = (Controller) getApplicationContext();
/* ........ */
//Product arraylist size
int ProductsSize = aController.getProductsArraylistSize();
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
/******** Dynamically create view elements - Start **********/
for(int j=0;j< ProductsSize;j++)
{
// Get probuct data from product data arraylist
String pName = aController.getProducts(j).getProductName();
int pPrice = aController.getProducts(j).getProductPrice();
// Create LinearLayout to view elemnts
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
TextView product = new TextView(this);
product.setText(" "+pName+" ");
//Add textView to LinearLayout
ll.addView(product);
TextView price = new TextView(this);
price.setText(" $"+pPrice+" ");
//Add textView to LinearLayout
ll.addView(price);
final Button btn = new Button(this);
btn.setId(j+1);
btn.setText("Add To Cart");
// set the layoutParams on the button
btn.setLayoutParams(params);
package com.androidexample.mvc;
import java.util.ArrayList;
import android.app.Application;
public class Controller extends Application{
private ArrayList<ModelProducts> myProducts = new ArrayList<ModelProducts>();
private ModelCart myCart = new ModelCart();
public ModelProducts getProducts(int pPosition) {
return myProducts.get(pPosition);
}
public void setProducts(ModelProducts Products) {
myProducts.add(Products);
}
public ModelCart getCart() {
return myCart;
}
public int getProductsArraylistSize() {
return myProducts.size();
}
}
package com.androidexample.mvc;
public class ModelProducts {
private String productName;
private String productDesc;
private int productPrice;
public ModelProducts(String productName,String productDesc,int productPrice) {
this.productName = productName;
this.productDesc = productDesc;
this.productPrice = productPrice;
}
public String getProductName() {
return productName;
}
public String getProductDesc() {
return productDesc;
}
public int getProductPrice() {
return productPrice;
}
}
MVC
Pros
No business logic in UI
Easier to unit test
Cons
Doesn't scale, separates UI but not model
Controller often grows too big
https://github.com/konmik/konmik.github.io/wiki/Introduction-to-Model-View-Presenter-on-Android
MVP
Model-View-Presenter
https://speakerdeck.com/rallat/android-development-like-a-pro
MVP
Increases separation of concerns into 3 layers
Passive View - Render logic
Presenter - Handle User events (Proxy)
Model - Business logic
https://github.com/googlesamples/android-architecture/wiki/Samples-at-a-glance
https://www.linkedin.com/pulse/mvc-mvp-mvvm-architecture-patterns-shashank-gupta
https://github.com/erikcaffrey/Android-Spotify-MVP
public interface ArtistsMvpView extends MvpView{
void showLoading();
void hideLoading();
void showArtistNotFoundMessage();
void showConnectionErrorMessage();
void renderArtists(List<Artist> artists);
void launchArtistDetail(Artist artist);
}
public class ArtistsPresenter implements Presenter<ArtistsMvpView>, ArtistCallback {
private ArtistsMvpView artistsMvpView;
private ArtistsInteractor artistsInteractor;
public ArtistsPresenter() {
}
@Override public void setView(ArtistsMvpView view) {
if (view == null) throw new IllegalArgumentException("You can't set a null view");
artistsMvpView = view;
artistsInteractor = new ArtistsInteractor(artistsMvpView.getContext());
}
@Override public void detachView() {
artistsMvpView = null;
}
public void onSearchArtist(String string) {
artistsMvpView.showLoading();
artistsInteractor.loadDataFromApi(string, this);
}
public void launchArtistDetail(Artist artist) {
artistsMvpView.launchArtistDetail(artist);
}
//.....
}
public class ArtistsInteractor {
SpotifyService mSpotifyService;
SpotifyApp mSpotifyApp;
public ArtistsInteractor(Context context) {
this.mSpotifyApp = SpotifyApp.get(context);
this.mSpotifyService = mSpotifyApp.getSpotifyService();
}
public void loadDataFromApi(String query, ArtistCallback artistCallback) {
mSpotifyService.searchArtist(query)
.subscribeOn(mSpotifyApp.SubscribeScheduler())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(artistsSearch -> onSuccess(artistsSearch, artistCallback),
throwable -> onError(throwable, artistCallback));
}
public class MainActivity extends Activity implements MainView, AdapterView.OnItemClickListener {
private ListView listView;
private ProgressBar progressBar;
private MainPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list);
listView.setOnItemClickListener(this);
progressBar = (ProgressBar) findViewById(R.id.progress);
presenter = new MainPresenterImpl(this);
}
@Override public void setItems(List<String> items) {
listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items));
}
@Override public void showMessage(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
presenter.onItemClicked(position);
}
}
package com.antonioleiva.mvpexample.app.main;
public interface MainPresenter {
void onResume();
void onItemClicked(int position);
void onDestroy();
}
public class MainPresenterImpl implements MainPresenter, FindItemsInteractor.OnFinishedListener {
private MainView mainView;
private FindItemsInteractor findItemsInteractor;
public MainPresenterImpl(MainView mainView) {
this.mainView = mainView;
findItemsInteractor = new FindItemsInteractorImpl();
}
@Override public void onResume() {
if (mainView != null) {
mainView.showProgress();
}
findItemsInteractor.findItems(this);
}
@Override public void onItemClicked(int position) {
if (mainView != null) {
mainView.showMessage(String.format("Position %d clicked", position + 1));
}
}
@Override public void onDestroy() {
mainView = null;
}
@Override public void onFinished(List<String> items) {
if (mainView != null) {
mainView.setItems(items);
mainView.hideProgress();
}
}
}
public interface MainView {
void showProgress();
void hideProgress();
void setItems(List<String> items);
void showMessage(String message);
}
http://antonioleiva.com/mvp-android/
MVP Testing
View
Test render logic and interaction with presenter,
mock Presenter.
Presenter
Test that view events invoke the right model
method. Mock both View and Model.
Model
Test the business logic, mock the data source and
Presenter.
MVP
Pros
Complex Tasks split into simpler tasks
Smaller objects, less bugs, easier to debug
Testable
Cons
BoilerPlate to wire the layers.
Model can’t be reused, tied to specific use case.
View and Presenter are tied to data objects since
they share the same type of object with the Model.
https://speakerdeck.com/rallat/androiddevlikeaprodroidconsf
MVVM
Microsoft Pattern
Removes UI code from Activities/Fragments
View has no knowledge of model
Data Binding = Bind ViewModel to Layout
Goodbye Presenter, hello ViewModel
http://tech.vg.no/2015/07/17/android-databinding-goodbye-presenter-hello-viewmodel/
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/password_block"
android:id="@+id/email_block"
android:visibility="@{data.emailBlockVisibility}">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Email:"
android:minWidth="100dp"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
android:ems="10"
android:id="@+id/email"/>
</LinearLayout>
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
mBinding = FragmentMainBinding.bind(view);
mViewModel = new MainModel(this, getResources());
mBinding.setData(mViewModel);
attachButtonListener();
return view;
}
public void updateDependentViews() {
if (isExistingUserChecked.get()) {
emailBlockVisibility.set(View.GONE);
loginOrCreateButtonText.set(mResources.getString(R.string.log_in));
}
else {
emailBlockVisibility.set(View.VISIBLE);
loginOrCreateButtonText.set(mResources.getString(R.string.create_user));
}
}
http://tech.vg.no/2015/07/17/android-databinding-goodbye-presenter-hello-viewmodel/
MVVM
Pros
First Party Library
Compile time checking
Presentation layer in XML
Testable
Less code, no more Butterknife
Cons
Data Binding isn't always appropriate
Android Studio integration was flaky
Reactive - RxJava
Not really an architecture
Used in many other architectures
Event based Publish / Subscribe
public void doLargeComputation(
final IComputationListener listener,
final OtherParams params) {
Subscription subscription = doLargeComputationCall(params)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Result>>>() {
@Override public void onNext(final List<Result> results) {
listener.doLargeComputationComplete(results);
}
@Override public void onCompleted() {}
@Override public void onError(final Throwable t) {
listener.doLargeComputationFailed(t);
}
}
);
}
private Observable<List<Result>> doLargeComputationCall(final OtherParams params) {
return Observable.defer(new Func0<Observable<List<Result>>>() {
@Override public Observable<List<Result>> call() {
List<Result> results = doTheRealLargeComputation(params);
if (results != null && 0 < results.size()) {
return Observable.just(results);
}
return Observable.error(new ComputationException("Could not do the large computation"));
}
}
);
}
MVC w/RxJava
https://github.com/yigit/dev-summit-architecture-demo
Clean Architecture
Uncle Bob
Much better decoupling, better reusabiity
Lots more layers
https://github.com/rallat/EffectiveAndroid
Clean Architecture is...
Independent of Frameworks
Testable
Independent of UI
Independent of Database
Independent of any External Agency
Decoupled
Clean Architecture
https://github.com/rallat/EffectiveAndroid
Clean Architecture (Kotlin)
https://github.com/pardom/CleanNews
tearDown()
Act Early
Trust but Verify
Know what you're getting into
YAGNI
Repos
MVC: http://androidexample.com/Use_MVC_Pattern_To_Create_Very_Basic_Shopping_Cart__-_Android_Example
MVC-Reactive: https://github.com/yigit/dev-summit-architecture-demo
MVP: https://github.com/antoniolg/androidmvp
MVVM: https://github.com/ivacf/archi
Clean: https://github.com/rallat/EffectiveAndroid
Contact Details
godfrey@riis.com
@godfreynolan
slideshare.com/godfreynolan

More Related Content

What's hot

Android Programming Basics
Android Programming BasicsAndroid Programming Basics
Android Programming Basics
Eueung Mulyana
 
LINQ in C#
LINQ in C#LINQ in C#
LINQ in C#
Basant Medhat
 
Introduction to angular with a simple but complete project
Introduction to angular with a simple but complete projectIntroduction to angular with a simple but complete project
Introduction to angular with a simple but complete project
Jadson Santos
 
Angular
AngularAngular
Model view controller (mvc)
Model view controller (mvc)Model view controller (mvc)
Model view controller (mvc)
M Ahsan Khan
 
Spring MVC Framework
Spring MVC FrameworkSpring MVC Framework
Spring MVC Framework
Hùng Nguyễn Huy
 
Angularjs PPT
Angularjs PPTAngularjs PPT
Angularjs PPT
Amit Baghel
 
Angular Basics.pptx
Angular Basics.pptxAngular Basics.pptx
Angular Basics.pptx
AshokKumar616995
 
MVC ppt presentation
MVC ppt presentationMVC ppt presentation
MVC ppt presentation
Bhavin Shah
 
Mastering RecyclerView Layouts
Mastering RecyclerView LayoutsMastering RecyclerView Layouts
Mastering RecyclerView Layouts
Dave Smith
 
Android Fragment
Android FragmentAndroid Fragment
Android Fragment
Kan-Han (John) Lu
 
Java servlets
Java servletsJava servlets
Java servletslopjuan
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
Christoffer Noring
 
Angular data binding
Angular data binding Angular data binding
Angular data binding
Sultan Ahmed
 
Object-oriented Programming-with C#
Object-oriented Programming-with C#Object-oriented Programming-with C#
Object-oriented Programming-with C#Doncho Minkov
 
React lecture
React lectureReact lecture
React lecture
Christoffer Noring
 
Angular Introduction By Surekha Gadkari
Angular Introduction By Surekha GadkariAngular Introduction By Surekha Gadkari
Angular Introduction By Surekha Gadkari
Surekha Gadkari
 
Kotlin Multiplatform
Kotlin MultiplatformKotlin Multiplatform
Kotlin Multiplatform
Kevin Galligan
 
Collections and its types in C# (with examples)
Collections and its types in C# (with examples)Collections and its types in C# (with examples)
Collections and its types in C# (with examples)
Aijaz Ali Abro
 

What's hot (20)

Android Programming Basics
Android Programming BasicsAndroid Programming Basics
Android Programming Basics
 
LINQ in C#
LINQ in C#LINQ in C#
LINQ in C#
 
Introduction to angular with a simple but complete project
Introduction to angular with a simple but complete projectIntroduction to angular with a simple but complete project
Introduction to angular with a simple but complete project
 
Angular
AngularAngular
Angular
 
Model view controller (mvc)
Model view controller (mvc)Model view controller (mvc)
Model view controller (mvc)
 
Spring MVC Framework
Spring MVC FrameworkSpring MVC Framework
Spring MVC Framework
 
Angularjs PPT
Angularjs PPTAngularjs PPT
Angularjs PPT
 
Angular Basics.pptx
Angular Basics.pptxAngular Basics.pptx
Angular Basics.pptx
 
MVC ppt presentation
MVC ppt presentationMVC ppt presentation
MVC ppt presentation
 
Mastering RecyclerView Layouts
Mastering RecyclerView LayoutsMastering RecyclerView Layouts
Mastering RecyclerView Layouts
 
Android Fragment
Android FragmentAndroid Fragment
Android Fragment
 
Java servlets
Java servletsJava servlets
Java servlets
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
 
Angular data binding
Angular data binding Angular data binding
Angular data binding
 
Object-oriented Programming-with C#
Object-oriented Programming-with C#Object-oriented Programming-with C#
Object-oriented Programming-with C#
 
React lecture
React lectureReact lecture
React lecture
 
Angular Introduction By Surekha Gadkari
Angular Introduction By Surekha GadkariAngular Introduction By Surekha Gadkari
Angular Introduction By Surekha Gadkari
 
Kotlin Multiplatform
Kotlin MultiplatformKotlin Multiplatform
Kotlin Multiplatform
 
Collections and its types in C# (with examples)
Collections and its types in C# (with examples)Collections and its types in C# (with examples)
Collections and its types in C# (with examples)
 
Android Basic Components
Android Basic ComponentsAndroid Basic Components
Android Basic Components
 

Viewers also liked

From Maps to Apps the Future of Drone Technology
From Maps to Apps the Future of Drone TechnologyFrom Maps to Apps the Future of Drone Technology
From Maps to Apps the Future of Drone Technology
Godfrey Nolan
 
Bulletproof
BulletproofBulletproof
Bulletproof
Godfrey Nolan
 
Attacking android insecurity
Attacking android insecurityAttacking android insecurity
Attacking android insecurity
Godfrey Nolan
 
Automotive android
Automotive androidAutomotive android
Automotive android
Godfrey Nolan
 
Design Patterns every Android developer should know
Design Patterns every Android developer should knowDesign Patterns every Android developer should know
Design Patterns every Android developer should know
muratcanbur
 
SuperSites
SuperSitesSuperSites
SuperSites
TERN Australia
 
Curriculum de Juan Carlos Sánchez Illán
Curriculum de Juan Carlos Sánchez IllánCurriculum de Juan Carlos Sánchez Illán
Curriculum de Juan Carlos Sánchez Illán
Juan Carlos Sanchéz Illán
 
Streams Studio Support for IBM InfoSphere Streams V4.0
Streams Studio Support for IBM InfoSphere Streams V4.0Streams Studio Support for IBM InfoSphere Streams V4.0
Streams Studio Support for IBM InfoSphere Streams V4.0
lisanl
 
Bondia.cat 05/11/2013
Bondia.cat 05/11/2013Bondia.cat 05/11/2013
Bondia.cat 05/11/2013
Bondia Lleida Sl
 
LA CRÓNICA 617
LA CRÓNICA 617LA CRÓNICA 617
Java/Scala Lab: Игорь Вахромеев - Parallel your process with Spring Batch
Java/Scala Lab: Игорь Вахромеев - Parallel your process with Spring BatchJava/Scala Lab: Игорь Вахромеев - Parallel your process with Spring Batch
Java/Scala Lab: Игорь Вахромеев - Parallel your process with Spring Batch
GeeksLab Odessa
 
Estaciones de climatización, Herramientas y Accesorios #TerritorioHELLA
Estaciones de climatización, Herramientas y Accesorios #TerritorioHELLAEstaciones de climatización, Herramientas y Accesorios #TerritorioHELLA
Estaciones de climatización, Herramientas y Accesorios #TerritorioHELLA
HELLA Spain
 
Catalog Avon - Campania 05 / 2011 - avonstore
Catalog Avon - Campania 05 / 2011 - avonstoreCatalog Avon - Campania 05 / 2011 - avonstore
Catalog Avon - Campania 05 / 2011 - avonstoreVecina_ro
 
Manual de tecnicas radiologicas de bolso
Manual de tecnicas radiologicas de bolsoManual de tecnicas radiologicas de bolso
Manual de tecnicas radiologicas de bolso
Ademar Ribeiro
 
Controlling diseases to ensure better animal health
Controlling diseases to ensure better animal healthControlling diseases to ensure better animal health
Controlling diseases to ensure better animal health
Deepa Menon
 
TEMA 19 lA ARQUITECTURA DEL S.XX
TEMA 19 lA ARQUITECTURA DEL S.XXTEMA 19 lA ARQUITECTURA DEL S.XX
TEMA 19 lA ARQUITECTURA DEL S.XX
@evasociales
 

Viewers also liked (20)

From Maps to Apps the Future of Drone Technology
From Maps to Apps the Future of Drone TechnologyFrom Maps to Apps the Future of Drone Technology
From Maps to Apps the Future of Drone Technology
 
Bulletproof
BulletproofBulletproof
Bulletproof
 
Attacking android insecurity
Attacking android insecurityAttacking android insecurity
Attacking android insecurity
 
Automotive android
Automotive androidAutomotive android
Automotive android
 
Design Patterns every Android developer should know
Design Patterns every Android developer should knowDesign Patterns every Android developer should know
Design Patterns every Android developer should know
 
AADIMATIQ
AADIMATIQAADIMATIQ
AADIMATIQ
 
Технологии
ТехнологииТехнологии
Технологии
 
SuperSites
SuperSitesSuperSites
SuperSites
 
IP-guard Catalog
IP-guard CatalogIP-guard Catalog
IP-guard Catalog
 
Curriculum de Juan Carlos Sánchez Illán
Curriculum de Juan Carlos Sánchez IllánCurriculum de Juan Carlos Sánchez Illán
Curriculum de Juan Carlos Sánchez Illán
 
Streams Studio Support for IBM InfoSphere Streams V4.0
Streams Studio Support for IBM InfoSphere Streams V4.0Streams Studio Support for IBM InfoSphere Streams V4.0
Streams Studio Support for IBM InfoSphere Streams V4.0
 
Maria jose naranjo
Maria jose naranjoMaria jose naranjo
Maria jose naranjo
 
Bondia.cat 05/11/2013
Bondia.cat 05/11/2013Bondia.cat 05/11/2013
Bondia.cat 05/11/2013
 
LA CRÓNICA 617
LA CRÓNICA 617LA CRÓNICA 617
LA CRÓNICA 617
 
Java/Scala Lab: Игорь Вахромеев - Parallel your process with Spring Batch
Java/Scala Lab: Игорь Вахромеев - Parallel your process with Spring BatchJava/Scala Lab: Игорь Вахромеев - Parallel your process with Spring Batch
Java/Scala Lab: Игорь Вахромеев - Parallel your process with Spring Batch
 
Estaciones de climatización, Herramientas y Accesorios #TerritorioHELLA
Estaciones de climatización, Herramientas y Accesorios #TerritorioHELLAEstaciones de climatización, Herramientas y Accesorios #TerritorioHELLA
Estaciones de climatización, Herramientas y Accesorios #TerritorioHELLA
 
Catalog Avon - Campania 05 / 2011 - avonstore
Catalog Avon - Campania 05 / 2011 - avonstoreCatalog Avon - Campania 05 / 2011 - avonstore
Catalog Avon - Campania 05 / 2011 - avonstore
 
Manual de tecnicas radiologicas de bolso
Manual de tecnicas radiologicas de bolsoManual de tecnicas radiologicas de bolso
Manual de tecnicas radiologicas de bolso
 
Controlling diseases to ensure better animal health
Controlling diseases to ensure better animal healthControlling diseases to ensure better animal health
Controlling diseases to ensure better animal health
 
TEMA 19 lA ARQUITECTURA DEL S.XX
TEMA 19 lA ARQUITECTURA DEL S.XXTEMA 19 lA ARQUITECTURA DEL S.XX
TEMA 19 lA ARQUITECTURA DEL S.XX
 

Similar to Android Design Patterns

Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
DataArt
 
Saindo da zona de conforto… resolvi aprender android
Saindo da zona de conforto… resolvi aprender androidSaindo da zona de conforto… resolvi aprender android
Saindo da zona de conforto… resolvi aprender android
Daniel Baccin
 
Introduction to Spring Boot.pdf
Introduction to Spring Boot.pdfIntroduction to Spring Boot.pdf
Introduction to Spring Boot.pdf
ShaiAlmog1
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best PracticesYekmer Simsek
 
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
Michael Galpin
 
CodingSerbia2014-JavaVSPig
CodingSerbia2014-JavaVSPigCodingSerbia2014-JavaVSPig
CodingSerbia2014-JavaVSPig
Dusan Zamurovic
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
Elyse Kolker Gordon
 
Android TV: Building apps with Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback LibraryAndroid TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with Google’s Leanback Library
Joe Birch
 
VISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEVISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEDarwin Durand
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web APIhabib_786
 
Your Second iPhone App - Code Listings
Your Second iPhone App - Code ListingsYour Second iPhone App - Code Listings
Your Second iPhone App - Code Listings
Vu Tran Lam
 
Why SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptWhy SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptmartinlippert
 
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
Ali Parmaksiz
 
Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)
Fafadia Tech
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in Android
Robert Cooper
 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
Robert DeLuca
 

Similar to Android Design Patterns (20)

Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
 
Saindo da zona de conforto… resolvi aprender android
Saindo da zona de conforto… resolvi aprender androidSaindo da zona de conforto… resolvi aprender android
Saindo da zona de conforto… resolvi aprender android
 
Android crashcourse
Android crashcourseAndroid crashcourse
Android crashcourse
 
Introduction to Spring Boot.pdf
Introduction to Spring Boot.pdfIntroduction to Spring Boot.pdf
Introduction to Spring Boot.pdf
 
Action bar
Action barAction bar
Action bar
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
 
CodingSerbia2014-JavaVSPig
CodingSerbia2014-JavaVSPigCodingSerbia2014-JavaVSPig
CodingSerbia2014-JavaVSPig
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
 
Android TV: Building apps with Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback LibraryAndroid TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with Google’s Leanback Library
 
VISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEVISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLE
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web API
 
Test
TestTest
Test
 
Your Second iPhone App - Code Listings
Your Second iPhone App - Code ListingsYour Second iPhone App - Code Listings
Your Second iPhone App - Code Listings
 
Why SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptWhy SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScript
 
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
 
Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in Android
 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
 

More from Godfrey Nolan

Counting Cars with Drones
Counting Cars with DronesCounting Cars with Drones
Counting Cars with Drones
Godfrey Nolan
 
Customising QGroundControl
Customising QGroundControlCustomising QGroundControl
Customising QGroundControl
Godfrey Nolan
 
DJI Payload SDK
DJI Payload SDKDJI Payload SDK
DJI Payload SDK
Godfrey Nolan
 
Parrot Tutorials in Kotlin
Parrot Tutorials in KotlinParrot Tutorials in Kotlin
Parrot Tutorials in Kotlin
Godfrey Nolan
 
DJI Mobile SDK Tutorials in kotlin
DJI Mobile SDK Tutorials in kotlinDJI Mobile SDK Tutorials in kotlin
DJI Mobile SDK Tutorials in kotlin
Godfrey Nolan
 
Drone sdk showdown
Drone sdk showdownDrone sdk showdown
Drone sdk showdown
Godfrey Nolan
 
AI/ML in drones
AI/ML in dronesAI/ML in drones
AI/ML in drones
Godfrey Nolan
 
Getting started with tensor flow datasets
Getting started with tensor flow datasets Getting started with tensor flow datasets
Getting started with tensor flow datasets
Godfrey Nolan
 
Using ML to make your UI tests more robust
Using ML to make your UI tests more robustUsing ML to make your UI tests more robust
Using ML to make your UI tests more robust
Godfrey Nolan
 
Java best practices
Java best practicesJava best practices
Java best practices
Godfrey Nolan
 
Counting sheep with Drones and AI
Counting sheep with Drones and AICounting sheep with Drones and AI
Counting sheep with Drones and AI
Godfrey Nolan
 
Writing Secure Mobile Apps for Drones
Writing Secure Mobile Apps for DronesWriting Secure Mobile Apps for Drones
Writing Secure Mobile Apps for Drones
Godfrey Nolan
 
Android Device Labs
Android Device LabsAndroid Device Labs
Android Device Labs
Godfrey Nolan
 
The Day We Infected Ourselves with Ransomware
The Day We Infected Ourselves with RansomwareThe Day We Infected Ourselves with Ransomware
The Day We Infected Ourselves with Ransomware
Godfrey Nolan
 
Agile Android
Agile AndroidAgile Android
Agile Android
Godfrey Nolan
 
Agile Swift
Agile SwiftAgile Swift
Agile Swift
Godfrey Nolan
 
Android Refactoring
Android RefactoringAndroid Refactoring
Android Refactoring
Godfrey Nolan
 
Agile mobile
Agile mobileAgile mobile
Agile mobile
Godfrey Nolan
 
Tableau 10 and quickbooks
Tableau 10 and quickbooksTableau 10 and quickbooks
Tableau 10 and quickbooks
Godfrey Nolan
 
Network graphs in tableau
Network graphs in tableauNetwork graphs in tableau
Network graphs in tableau
Godfrey Nolan
 

More from Godfrey Nolan (20)

Counting Cars with Drones
Counting Cars with DronesCounting Cars with Drones
Counting Cars with Drones
 
Customising QGroundControl
Customising QGroundControlCustomising QGroundControl
Customising QGroundControl
 
DJI Payload SDK
DJI Payload SDKDJI Payload SDK
DJI Payload SDK
 
Parrot Tutorials in Kotlin
Parrot Tutorials in KotlinParrot Tutorials in Kotlin
Parrot Tutorials in Kotlin
 
DJI Mobile SDK Tutorials in kotlin
DJI Mobile SDK Tutorials in kotlinDJI Mobile SDK Tutorials in kotlin
DJI Mobile SDK Tutorials in kotlin
 
Drone sdk showdown
Drone sdk showdownDrone sdk showdown
Drone sdk showdown
 
AI/ML in drones
AI/ML in dronesAI/ML in drones
AI/ML in drones
 
Getting started with tensor flow datasets
Getting started with tensor flow datasets Getting started with tensor flow datasets
Getting started with tensor flow datasets
 
Using ML to make your UI tests more robust
Using ML to make your UI tests more robustUsing ML to make your UI tests more robust
Using ML to make your UI tests more robust
 
Java best practices
Java best practicesJava best practices
Java best practices
 
Counting sheep with Drones and AI
Counting sheep with Drones and AICounting sheep with Drones and AI
Counting sheep with Drones and AI
 
Writing Secure Mobile Apps for Drones
Writing Secure Mobile Apps for DronesWriting Secure Mobile Apps for Drones
Writing Secure Mobile Apps for Drones
 
Android Device Labs
Android Device LabsAndroid Device Labs
Android Device Labs
 
The Day We Infected Ourselves with Ransomware
The Day We Infected Ourselves with RansomwareThe Day We Infected Ourselves with Ransomware
The Day We Infected Ourselves with Ransomware
 
Agile Android
Agile AndroidAgile Android
Agile Android
 
Agile Swift
Agile SwiftAgile Swift
Agile Swift
 
Android Refactoring
Android RefactoringAndroid Refactoring
Android Refactoring
 
Agile mobile
Agile mobileAgile mobile
Agile mobile
 
Tableau 10 and quickbooks
Tableau 10 and quickbooksTableau 10 and quickbooks
Tableau 10 and quickbooks
 
Network graphs in tableau
Network graphs in tableauNetwork graphs in tableau
Network graphs in tableau
 

Recently uploaded

Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and GuidelinesMulti-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Sanjeev Rampal
 
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptxLiving-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
TristanJasperRamos
 
This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!
nirahealhty
 
Output determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CCOutput determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CC
ShahulHameed54211
 
How to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptxHow to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptx
Gal Baras
 
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
3ipehhoa
 
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
3ipehhoa
 
Latest trends in computer networking.pptx
Latest trends in computer networking.pptxLatest trends in computer networking.pptx
Latest trends in computer networking.pptx
JungkooksNonexistent
 
test test test test testtest test testtest test testtest test testtest test ...
test test  test test testtest test testtest test testtest test testtest test ...test test  test test testtest test testtest test testtest test testtest test ...
test test test test testtest test testtest test testtest test testtest test ...
Arif0071
 
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
3ipehhoa
 
ER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAEER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAE
Himani415946
 
BASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptxBASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptx
natyesu
 
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shopHistory+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
laozhuseo02
 
1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...
JeyaPerumal1
 
guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...
Rogerio Filho
 
The+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptxThe+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptx
laozhuseo02
 

Recently uploaded (16)

Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and GuidelinesMulti-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
 
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptxLiving-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
 
This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!
 
Output determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CCOutput determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CC
 
How to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptxHow to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptx
 
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
 
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
 
Latest trends in computer networking.pptx
Latest trends in computer networking.pptxLatest trends in computer networking.pptx
Latest trends in computer networking.pptx
 
test test test test testtest test testtest test testtest test testtest test ...
test test  test test testtest test testtest test testtest test testtest test ...test test  test test testtest test testtest test testtest test testtest test ...
test test test test testtest test testtest test testtest test testtest test ...
 
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
 
ER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAEER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAE
 
BASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptxBASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptx
 
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shopHistory+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
 
1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...
 
guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...
 
The+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptxThe+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptx
 

Android Design Patterns

  • 2. Android Application Architecture (Android Dev Summit) https://www.youtube.com/watch?v=BlkJzgjzL0c
  • 3. What is Your Goal? Scalable Maintainable Testing
  • 4. What is Your Goal? Scalable Add new features quickly Maintainable No spaghetti code Don't cross the streams Testing Easy to mock
  • 5. Why? Easier to add new features Easier to understand Easier to police Make our life easier Make Unit Testing easier
  • 6. How do we get there? https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
  • 7.
  • 10.
  • 11. package alexandria.israelferrer.com.libraryofalexandria; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.RatingBar; import android.widget.TextView; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.squareup.picasso.Picasso; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Type; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; public class MainActivity extends Activity { private static final String PACKAGE = "com.israelferrer.alexandria"; private static final String KEY_FAVS = PACKAGE + ".FAVS"; private List<ArtWork> artWorkList; private ArtWorkAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = (ListView) findViewById(R.id.listView); InputStream stream = getResources().openRawResource(R.raw.artwork); Type listType = new TypeToken<List<ArtWork>>() { }.getType(); artWorkList = new Gson().fromJson(new InputStreamReader(stream), listType); final SharedPreferences preferences = getSharedPreferences(getPackageName() , Context.MODE_PRIVATE); for (ArtWork artWork : artWorkList) { artWork.setRating(preferences.getFloat(PACKAGE + artWork.getId(), 0F)); } adapter = new ArtWorkAdapter(); listView.setAdapter(adapter); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.filter) { adapter.orderMode(); return true; } return super.onOptionsItemSelected(item); } private class ArtWorkAdapter extends BaseAdapter { private boolean isOrder; private final List<ArtWork> orderedList; public ArtWorkAdapter() { super(); orderedList = new LinkedList<ArtWork>(); } @Override public int getCount() { return artWorkList.size(); } @Override public Object getItem(int position) { return artWorkList.get(position); } @Override public long getItemId(int position) { return Long.valueOf(artWorkList.get(position).getId()); } public void orderMode() { isOrder = !isOrder; if (isOrder) { orderedList.clear(); orderedList.addAll(artWorkList); Collections.sort(orderedList); notifyDataSetChanged(); } else { notifyDataSetChanged(); } } @Override public View getView(int position, View convertView, ViewGroup parent) { final ArtWork artWork; if (isOrder) { artWork = orderedList.get(position); } else { artWork = artWorkList.get(position); } View row; switch (artWork.getType()) { case ArtWork.QUOTE: row = getLayoutInflater().inflate(R.layout.text_row, null); TextView quote = (TextView) row.findViewById(R.id.quote); TextView author = (TextView) row.findViewById(R.id.author); quote.setText(""" + artWork.getText() + """); author.setText(artWork.getAuthor()); break; case ArtWork.PAINTING: final SharedPreferences preferences = getSharedPreferences(getPackageName() , Context.MODE_PRIVATE); final HashSet<String> favs = (HashSet<String>) preferences .getStringSet(KEY_FAVS, new HashSet<String>()); row = getLayoutInflater().inflate(R.layout.painting_row, null); ImageView image = (ImageView) row.findViewById(R.id.painting); TextView painter = (TextView) row.findViewById(R.id.author); painter.setText(artWork.getTitle() + " by " + artWork.getAuthor()); Picasso.with(MainActivity.this).load(artWork.getContentUrl()).fit() .into(image); RatingBar rating = (RatingBar) row.findViewById(R.id.rate); rating.setRating(artWork.getRating()); rating.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() { @Override public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { preferences.edit().putFloat(PACKAGE + artWork.getId(), rating).apply(); artWork.setRating(rating); } }); CheckBox fav = (CheckBox) row.findViewById(R.id.fav); fav.setChecked(favs.contains(artWork.getId())); fav.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { final HashSet<String> favs = new HashSet<String>((HashSet<String>) preferences .getStringSet(KEY_FAVS, new HashSet<String>())); if (isChecked) { favs.add(artWork.getId()); } else { favs.remove(artWork.getId()); } preferences.edit().putStringSet(KEY_FAVS, favs).apply(); } }); break; case ArtWork.MOVIE: case ArtWork.OPERA: row = new ViewStub(MainActivity.this); break; default: row = getLayoutInflater().inflate(R.layout.text_row, null); } return row; } } }
  • 12. Classic Android Pros Better the devil you know Cons Activities and Fragments quickly become large Painful to make changes or add new features All the logic in Activities, unit testing is impossible Classic Android is not MVC
  • 14.
  • 16. package com.androidexample.mvc; //imports public class FirstScreen extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.firstscreen); final LinearLayout lm = (LinearLayout) findViewById(R.id.linearMain); final Button secondBtn = (Button) findViewById(R.id.second); //Get Global Controller Class object (see application tag in AndroidManifest.xml) final Controller aController = (Controller) getApplicationContext(); /* ........ */ //Product arraylist size int ProductsSize = aController.getProductsArraylistSize(); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); /******** Dynamically create view elements - Start **********/ for(int j=0;j< ProductsSize;j++) { // Get probuct data from product data arraylist String pName = aController.getProducts(j).getProductName(); int pPrice = aController.getProducts(j).getProductPrice(); // Create LinearLayout to view elemnts LinearLayout ll = new LinearLayout(this); ll.setOrientation(LinearLayout.HORIZONTAL); TextView product = new TextView(this); product.setText(" "+pName+" "); //Add textView to LinearLayout ll.addView(product); TextView price = new TextView(this); price.setText(" $"+pPrice+" "); //Add textView to LinearLayout ll.addView(price); final Button btn = new Button(this); btn.setId(j+1); btn.setText("Add To Cart"); // set the layoutParams on the button btn.setLayoutParams(params);
  • 17. package com.androidexample.mvc; import java.util.ArrayList; import android.app.Application; public class Controller extends Application{ private ArrayList<ModelProducts> myProducts = new ArrayList<ModelProducts>(); private ModelCart myCart = new ModelCart(); public ModelProducts getProducts(int pPosition) { return myProducts.get(pPosition); } public void setProducts(ModelProducts Products) { myProducts.add(Products); } public ModelCart getCart() { return myCart; } public int getProductsArraylistSize() { return myProducts.size(); } } package com.androidexample.mvc; public class ModelProducts { private String productName; private String productDesc; private int productPrice; public ModelProducts(String productName,String productDesc,int productPrice) { this.productName = productName; this.productDesc = productDesc; this.productPrice = productPrice; } public String getProductName() { return productName; } public String getProductDesc() { return productDesc; } public int getProductPrice() { return productPrice; } }
  • 18.
  • 19. MVC Pros No business logic in UI Easier to unit test Cons Doesn't scale, separates UI but not model Controller often grows too big
  • 22.
  • 23. MVP Increases separation of concerns into 3 layers Passive View - Render logic Presenter - Handle User events (Proxy) Model - Business logic
  • 27. public interface ArtistsMvpView extends MvpView{ void showLoading(); void hideLoading(); void showArtistNotFoundMessage(); void showConnectionErrorMessage(); void renderArtists(List<Artist> artists); void launchArtistDetail(Artist artist); } public class ArtistsPresenter implements Presenter<ArtistsMvpView>, ArtistCallback { private ArtistsMvpView artistsMvpView; private ArtistsInteractor artistsInteractor; public ArtistsPresenter() { } @Override public void setView(ArtistsMvpView view) { if (view == null) throw new IllegalArgumentException("You can't set a null view"); artistsMvpView = view; artistsInteractor = new ArtistsInteractor(artistsMvpView.getContext()); } @Override public void detachView() { artistsMvpView = null; } public void onSearchArtist(String string) { artistsMvpView.showLoading(); artistsInteractor.loadDataFromApi(string, this); } public void launchArtistDetail(Artist artist) { artistsMvpView.launchArtistDetail(artist); } //..... } public class ArtistsInteractor { SpotifyService mSpotifyService; SpotifyApp mSpotifyApp; public ArtistsInteractor(Context context) { this.mSpotifyApp = SpotifyApp.get(context); this.mSpotifyService = mSpotifyApp.getSpotifyService(); } public void loadDataFromApi(String query, ArtistCallback artistCallback) { mSpotifyService.searchArtist(query) .subscribeOn(mSpotifyApp.SubscribeScheduler()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(artistsSearch -> onSuccess(artistsSearch, artistCallback), throwable -> onError(throwable, artistCallback)); }
  • 28.
  • 29. public class MainActivity extends Activity implements MainView, AdapterView.OnItemClickListener { private ListView listView; private ProgressBar progressBar; private MainPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.list); listView.setOnItemClickListener(this); progressBar = (ProgressBar) findViewById(R.id.progress); presenter = new MainPresenterImpl(this); } @Override public void setItems(List<String> items) { listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items)); } @Override public void showMessage(String message) { Toast.makeText(this, message, Toast.LENGTH_LONG).show(); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { presenter.onItemClicked(position); } } package com.antonioleiva.mvpexample.app.main; public interface MainPresenter { void onResume(); void onItemClicked(int position); void onDestroy(); } public class MainPresenterImpl implements MainPresenter, FindItemsInteractor.OnFinishedListener { private MainView mainView; private FindItemsInteractor findItemsInteractor; public MainPresenterImpl(MainView mainView) { this.mainView = mainView; findItemsInteractor = new FindItemsInteractorImpl(); } @Override public void onResume() { if (mainView != null) { mainView.showProgress(); } findItemsInteractor.findItems(this); } @Override public void onItemClicked(int position) { if (mainView != null) { mainView.showMessage(String.format("Position %d clicked", position + 1)); } } @Override public void onDestroy() { mainView = null; } @Override public void onFinished(List<String> items) { if (mainView != null) { mainView.setItems(items); mainView.hideProgress(); } } } public interface MainView { void showProgress(); void hideProgress(); void setItems(List<String> items); void showMessage(String message); } http://antonioleiva.com/mvp-android/
  • 30. MVP Testing View Test render logic and interaction with presenter, mock Presenter. Presenter Test that view events invoke the right model method. Mock both View and Model. Model Test the business logic, mock the data source and Presenter.
  • 31. MVP Pros Complex Tasks split into simpler tasks Smaller objects, less bugs, easier to debug Testable Cons BoilerPlate to wire the layers. Model can’t be reused, tied to specific use case. View and Presenter are tied to data objects since they share the same type of object with the Model. https://speakerdeck.com/rallat/androiddevlikeaprodroidconsf
  • 32. MVVM Microsoft Pattern Removes UI code from Activities/Fragments View has no knowledge of model Data Binding = Bind ViewModel to Layout Goodbye Presenter, hello ViewModel
  • 34.
  • 35. <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/password_block" android:id="@+id/email_block" android:visibility="@{data.emailBlockVisibility}"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Email:" android:minWidth="100dp"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:ems="10" android:id="@+id/email"/> </LinearLayout> @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_main, container, false); mBinding = FragmentMainBinding.bind(view); mViewModel = new MainModel(this, getResources()); mBinding.setData(mViewModel); attachButtonListener(); return view; } public void updateDependentViews() { if (isExistingUserChecked.get()) { emailBlockVisibility.set(View.GONE); loginOrCreateButtonText.set(mResources.getString(R.string.log_in)); } else { emailBlockVisibility.set(View.VISIBLE); loginOrCreateButtonText.set(mResources.getString(R.string.create_user)); } } http://tech.vg.no/2015/07/17/android-databinding-goodbye-presenter-hello-viewmodel/
  • 36. MVVM Pros First Party Library Compile time checking Presentation layer in XML Testable Less code, no more Butterknife Cons Data Binding isn't always appropriate Android Studio integration was flaky
  • 37. Reactive - RxJava Not really an architecture Used in many other architectures Event based Publish / Subscribe
  • 38. public void doLargeComputation( final IComputationListener listener, final OtherParams params) { Subscription subscription = doLargeComputationCall(params) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<Result>>>() { @Override public void onNext(final List<Result> results) { listener.doLargeComputationComplete(results); } @Override public void onCompleted() {} @Override public void onError(final Throwable t) { listener.doLargeComputationFailed(t); } } ); } private Observable<List<Result>> doLargeComputationCall(final OtherParams params) { return Observable.defer(new Func0<Observable<List<Result>>>() { @Override public Observable<List<Result>> call() { List<Result> results = doTheRealLargeComputation(params); if (results != null && 0 < results.size()) { return Observable.just(results); } return Observable.error(new ComputationException("Could not do the large computation")); } } ); }
  • 40. Clean Architecture Uncle Bob Much better decoupling, better reusabiity Lots more layers
  • 42. Clean Architecture is... Independent of Frameworks Testable Independent of UI Independent of Database Independent of any External Agency Decoupled
  • 43.
  • 46.
  • 47. tearDown() Act Early Trust but Verify Know what you're getting into YAGNI
  • 48. Repos MVC: http://androidexample.com/Use_MVC_Pattern_To_Create_Very_Basic_Shopping_Cart__-_Android_Example MVC-Reactive: https://github.com/yigit/dev-summit-architecture-demo MVP: https://github.com/antoniolg/androidmvp MVVM: https://github.com/ivacf/archi Clean: https://github.com/rallat/EffectiveAndroid