Upload
felixsanhueza
View
35
Download
7
Embed Size (px)
DESCRIPTION
Architectural concepts for modern android development
Citation preview
1. Introduction2. Android
i. Historyii. WorldPhoneiii. Ecosystemiv. DesignConsiderationsv. EmergingUseCases
3. TDDwithRobolectrici. LabBackgroundii. Lab:RobolectricIntegrationiii. Lab:FirstTestiv. WhatToTestv. BestPracticesvi. Lab:UtilityFunctionsvii. OtherTesting
4. Architecturei. Androidii. ModelViewControlleriii. BuildingBlocksiv. MessagePassingv. ThreadingModel
5. Fundamentalsi. Activitiesii. Manifestiii. LayoutsandViewsiv. ViewGroupsv. Fragmentsvi. Lab:DesignChunking
i. Handout:DesignChunkingii. Solution:DesignChunking
vii. Lab:ConstructTheViewi. Lab:AddDisplayFragmentii. Lab:AddButtonFragmentiii. Lab:DisplayViewiv. Lab:AddButtons
viii. Applicationix. Lab:AddApplicationx. Lab:EventBus
6. ResourceSystemi. DesignPrinciplesii. Styles&Themesiii. Dimensions&Colorsiv. Lab:ViewStylesv. Qualifiersvi. Lab:FlexibleDimensionsvii. Lab:Internationalizationviii. Drawablesix. Lab:ButtonStatex. Lab:AppIcon
7. ManagingtheLifecyclei. ApplicationLifecycleii. ActivityLifecycle
TableofContents
iii. FragmentLifecycleiv. Lab:VisualizingtheLifecyclev. Backstackvi. FragmentManagervii. Lab:AddCalculatorFragmentviii. InstanceState
8. Lab:Calculatori. Lab:Requirements&Designii. Lab:UserInteractioniii. Lab:GettingOnTheBusiv. Lab:Testingv. Lab:RoutingEventsvi. Lab:MakeItWorkvii. Lab:DeviceRotation
9. Appendixi. Toolsii. Maveniii. Resourcesiv. IntelliJCommands
10. Epilogue11. AboutTheAuthor12. Bibliography
ThisworkbookwasoriginallycreatedbyCoreyLeighLatislawastrainingmaterialsforanin-personclass.
Thisisfreealphaversionofthisbook,Ihopeyouenjoyit!Jointhemailinglisttokeepupwiththeofficialrelease.
Aportionofthedaywillbededicatedtolecture,butit'simportanttogetyoucodingandexploringassoonaspossible!
Wewillbeworkingthroughaseriesoflabassignmentsasacomplementtothematerialyouwillbelearning.Ourfirstassignmentwillbecreatingacalculatorapplication.ThiswillcoverseveralfoundationalAndroidtopics.Thesecondassignmentwillbearegionalfoodrecommendationappwherewe'llcovernetworking,datamanagement,andservices.
We'llbepairprogrammingforthemajorityofthelabsessions.Youarewelcometoswitchuppairsasoftenasyoulike,butworkingsoloisn'tpermitted.Ifwehaveanoddnumberofparticipants,I'llpairwithsomeoneintheclass.
Therearemanypairingmethodologiesoutthere,butIgenerallyfavorpingponging.Inthismodelsomeonewritesafailingtest(red)andthenyouswitchwho'sinthedriver'sseat.Thenewdevelopermakesthetestpass(green)andrefactors(refactor)asnecessary.Thentheywriteafailingtestandthecyclestartsoveragain.
Ifyouhaven'tpairprogrammedbefore,Ithinkyou'lllikeit.Itcanbequitefunandit'sagreatwaytolearnfromothers.
WhatToExpect
HandsOn
PairProgramming
AccordingtoMeier,"mobile-phoneownershipeasilysurpassescomputerownership[and]2009markedtheyearthatmorepeopleaccessedtheInternetforthefirsttimefromamobilephoneratherthanaPC.Manypeoplebelievethatwithinthenext5yearsmorepeoplewillaccesstheInternetbymobilephoneratherthanusingpersonalcomputers."
Devices,suchasphonesandtablets,arequiteliterallychangingtheworldonepersonandoneappatatime.Smartphoneshavebecomeanindispensablepartofourlivesintheshorttimetheyhavebeenaround!
Thepotentialyouhavetocreateausefulappforpeopletheworldoverisarareandspecialgift.It'shardtothinkofsomethingmorerewardingtodointhisworldthantomakesuchapersonalconnectionandchangethecourseofpeople'slives.Youcanequippeoplewithknowledge,tools,andgamesthatwillmakethemcompetitiveintheyearstocomeastechnologyadvances.
It'sanexcitingtimetobecomeandAndroiddeveloper!Thereisahighdemandandlotsofopportunitytomakeanimpactlocallyandglobally.
KnowingthefoundationsofAndroidwillhelpyouonyourexplorationofthisfascinatingplatformtohelpyoumakeappsthatcanliterallychangetheworld!
Meier,Reto(2012-04-05).ProfessionalAndroid4ApplicationDevelopment(KindleLocations499-502).JohnWileyandSons.KindleEdition.
Chapter1:Android
Resources
AbriefhistoryoftheAndroidworld.
Globalshipmentshavebeenrisingatafastpace.AccordingtotheIDC,lastyearaloneitrose23%.By2018,therewillbeanadditional1.8billiondevicesinpeople'shands.
Ofthosephones,80.2%willbeAndroid!
History
SmartphoneMomentumStillEvidentwithShipmentsExpectedtoReach1.2Billionin2014andGrowing23.1%Over2013.May28,2014.Retrievedfromhttp://www.idc.com/getdoc.jsp?containerId=prUS24857114.
References
Androidissointriguingbecauseit'sasystemthat'saccessibletotheworldover,notjusttherichestinoursocieties.
WhatmakesAndroidsoaccessibleisit'sprice.AccordingtoSherman,it'sonaveragelessthanhalfthepriceofaniOSdevice.
AsofJanuarythisyear,we'vereachedatippingpointwitha$50phone,accordingtoOxford.Thisflingsthedoorswidetodevelopingnationsandopensanewworldofpossibilitiesforapps.Wecancreatemeaningfulexperiencesthatwilltransformtheworld.PhonesarenowhalfthepriceofanOneLaptopPerChildlaptopandarguablymorepowerfultoempowernewpeopletojointheglobalstage.
AtGoogleI/O,theyunveiledAndroidOne.ThissystemofpartnershipsbetweenOEMsandGooglewillrapidlyaccelerateadoptioninemergingmarketslikelysurpassingcurrentprojections.ThisprojectcoupledwithotherinitiativestobringfasterInternetconnectionstothe"dark"regionsoftheworldwillrapidlyacceleratetechnologyinthoselocations.
Emergingmarkets,suchasChina,Russia,andIndiaarethefastestgrowingsegment,whichprovidesplentyofnewusecasesandproblemstosolve.
"Shipmentswillmorethandoublebetweennowand2018withinkeyemergingmarkets,includingIndia,Indonesia,andRussia.Inaddition,Chinawillaccountfornearlyathirdofallsmartphoneshipmentsin2018."
AccordingtoOxford,"two-thirdsofSouthAfricanswillhaveamobiledatasubscriptionby2017,morethandoubling"thecurrentusage.Also,predictionsestimatethat"mobiledatasubscriptionsinNigeriaandKenyawillrisefromfourpercent"toapproximately25%.
Howcanyoubestimpactthosemarkets?
Sherman,J.February18,2014.Retrievedfromhttp://www.digitaltrends.com/mobile/android-way-cheaper-than-ios/.
WorldPhone
References
Oxford,A.January31,2014.Sub-$50AndroidsmartphonehitsSouthAfricaasMTNlaunchesSteppa.Retrievedfromhttp://www.zdnet.com/sub-50-android-smartphone-hits-south-africa-as-mtn-launches-steppa-7000025828/.Oxford,A.September19,2013.Two-thirdsofSouthAfricanswillbeonlineby2017asmobiledatabooms,Retrievedfromhttp://www.zdnet.com/two-thirds-of-south-africans-will-be-online-by-2017-as-mobile-data-booms-7000020901/.SmartphoneMomentumStillEvidentwithShipmentsExpectedtoReach1.2Billionin2014andGrowing23.1%Over2013.May28,2014.Retrievedfromhttp://www.idc.com/getdoc.jsp?containerId=prUS24857114.
Androidhasbeenevolvingforthelastseveralyearsandexpandingitsreachthroughvariousphonesandtablets.AtGoogleI/O2014,theyannouncedthattheyarestandardizingtheAndroidlandscapeacrossphones,tablets,inadditiontowearabletechnologysuchasGlassandWear,TVandevencars!AllofthesedevicesruntheAndroidOSandgiveyoumanyavenuestocreateinnovativenewsystems.
OneofthelatestadditionstotheunifiedplatformisAndroidinwatchform.
Thisexcitingnewplatformnotonlyprovidesnotifications(similartothestatusbaronyourphone),butalsoprovidesnewmodesofinteraction.Ifyouhaveanexistingapplicationwithnotifications,youalreadyhaveapresenceonWear.
Ifyou'reinterestedinWear,checkoutAndroid'swebsite:http://developer.android.com/training/building-wearables.html
GoogleGlassisanotificationengine,camera,videorecorder,andapplicationhostonyourface.Controversyaside,thereareplentyofinterestingtechnicalaspectstoexplore.
TherearetwobasicflavorsofGlassapps.FirstyoucanwriteapplicationswiththemirrorAPI,whichdeliverscontenttoyourGlassusingyourownbackend.YoudeliverHTML-basedcardsfordisplay.
TheotheroptionistowritenativeAndroidapplicationsusingtheGlassDevelopmentKit(GDK).Ifyou'reinterestedindevelopingGlassapps,checkoutthedeveloperwebsite:https://developers.google.com/glass/develop/gdk/
Google'slatestattemptatputtingAndroidonyourTVwasannouncedatGoogleI/Othisyear.InsteadofrunningaforkofAndroid,astheill-fatedGoogleTVdid,itnowrunsfull,nativeAndroid.Italsohascastingabilitiesbuiltin(integratedChromecast).
Ifyou'reinterestedindevelopingTVapps,here'smoreinfo:http://developer.android.com/preview/tv/start/index.html
Weknowrelativelylittleabouttheplatformsinceitwasrecentlyannounced,butit'llworkasaseconddisplayandaninputdevice.YourappswillrunontheintegratedAndroiddeviceinthedashboard(notonthecar).
DeviceEcosystem
AndroidWear
GoogleGlass
AndroidTV
AndroidAuto
DesigningamobileapplicationisverydifferentfromdesigningforaPC.OnaPC,youcanassumefastprocessors,sizablememory,lotsofstoragespace,andalargedisplay.Usersaregenerallyexpectingtospendalotoftimeinyourapplicationtoaccomplishalargergoal,suchaswritingabookordoingtheirfinances.
Amobilephoneisaverydifferentdevice!Usersinteractwithitinverydifferentwaysthantheydowithanormalcomputer.Theyareoftenaccomplishingshorttaskswhileonthego.
AccordingtoMeier,"comparedtodesktopornotebookcomputers,mobiledeviceshaverelatively:
LowprocessingpowerLimitedRAMLimitedpermanentstoragecapacitySmallscreenswithlowresolutionHighcostsassociatedwithdatatransferIntermittentconnectivity,slowdatatransferrates,andhighlatencyUnreliabledataconnectionsLimitedbatterylife"
Mobilephonebatteriesarenotoriousforquicklylosingachargeandpeoplegetveryfrustratedwhentheycan'tusetheirphoneforanentireday.Manypeoplecarryaboutbatteryboostersandchargerssothattheywillhaveaccesstotheirphonesafteradayofheavyusage.Youshouldwriteyourapplicationstobeabatteryfriendlyaspossible.
Thisisevenmoreimportantinthefurtherflungregionsoftheworld,whereKochisharesthat"rechargingyourphoneeverynightisnotanoptionifyouliveinaruralvillagewithoutelectricity.AtoneofUNICEF'sprojectsinruralSenegal,Iencounteredavillageentrepreneurwhostartedabusinesswherehewouldcollecteveryone'scellphonesandforasmallfee,biketoanelectrifiedvillageafewhoursaway,thenbikebackwithphonesatfullcharge."
Kochifurtherstatesthat,"peopleinthesecountriesspendalotofmoneytokeeptheirphonescharged.Developingaphonewhosebatterylastsforaweek,"andapplicationsthatdon'tneedlesslywastebatterypower,"wouldunlocksmartphonestoalargemarketsegment."
It'sexpensivetopurchasedata.We'refairlyluckyintheUnitedStatestohaveubiquitousaccesstonetworksonthegoandaffordableplans.That'snotalwaysthecase,eveninotherdevelopednations.
Tobeabetterdevicecitizen,limittheamountofdatayoudownloadwhileonmobilenetworksandmaximizetheamountyoudownloadanduploadwhenusershaveafasterconnection,suchasWi-Fi.
Youhavenoideawhatdevicewillberunningyourapplication,especiallysincetheAndroidOSiseverexpandingtonewdevicesandformfactors.Youmustdesignresponsiveappsthatscaletothemultitudeofdevicesonwhichyourapplicationcouldrun.
DesignConsiderations
Hardwareconsiderations
Batteryusage
Datausage
Unknownenvironments
Anotherthingtokeepinmindisthatyouruser'sattentionspanismuchshorterwhenusingaportabledevice.Usersareusuallyengagedinadifferentactivitywhenusingyourapp,e.g.attendingaparty.ShortburstsofactivitylikesharingapictureonInstagram,sendingatweetaboutthefestivities,orsendingatexttomeetupwiththeirfriendsisthenameofthegame.
Youalsocan'tassumethatyouhavetheirfullattentionspanforlong.Youwantyourdesignstobebeautifulandintuitivetohelpthemquicklyaccomplishtheirtask.
Youdon'twantyouruserstobesurprisedbyyourapplication.Youwanttomakesurethatyourdesignsareintuitiveandbehaveinwaysthatareeasytounderstand.Ageneralruleofthumbisifyouneedalengthytutorialtointroduceyourusertotheinterface,it'sprobablytoocomplicated!
Youalsodon'twantuserssurprisedbyabackgroundactionorlocation-basedactionthattheyhaven'texplicitlysignedupfor.Agreatexampleofwhatnottodoisregularlyannoyingthemwithnotificationsaboutratingyourapplicationorsendingadswhentheyhaven'trequestedthem.
Kochi,E.May27,2012.Retrievedfromhttp://techcrunch.com/2012/05/27/mobile-developing-world/.Meier,Reto(2012-04-05).ProfessionalAndroid4ApplicationDevelopment(KindleLocations1123-1128).JohnWileyandSons.KindleEdition.
Attentionspan
Principleofleastsurprise
References
Inseveralculturestabletsandevenphonesareviewedascommunaldevicesthataresharedforthebenefitofthecommunity.ThatisadifferentmodelthanwetypicallyassumeintheUnitedStates!
Herearesomeofthemostinterestingemergingusecasesindevelopingnations.
AccordingtoKochi,"airtimehasbecomeanotherformofcurrency.Imagineyouneedtogetasmallamountofmoneytoyoursisterwholivesinavillagethat'stenhoursdriveaway.Theeasiestwayforyoutodothatistobuysomeairtime,butinsteadoftoppingupyourownprepaidmobileserviceyoutopuphers.Forasmallfee,shecannowgoandcashoutthisairtimewithanagentthatsellsairtime."
Ogunlesialsosharesthatphonesareableto"abletotransformordinarycitizensdisenchantedbytheirgovernments,intoresistancefighters."Theabilitytosharepicturesandtextinrealtimeisapowerfulwaytofightbrutaland/orcorruptregimes.Ontheflipside,theycanmakecitizenseasiertotrack.
MobilephonescanspeedreconnectionwithlovedonesinrefugeecampsbyprovidingaSMSorotherregistryfordisplacedpersons(Ogunlesi).Theycouldalsobeusedtocoordinatevolunteereffortsontheground.
AccordingtoOgunlesi,"byservingasplatformsforsharingweatherinformation,marketprices,andmicro-insuranceschemes,mobilephonesareallowingAfrica'sfarmerstomakebetterdecisions,translatingintohigher-earningpotentials.Farmersareabletosendatextmessagetofindoutcroppricesinplacesthousandsofkilometersaway."
AccordingtoTsao,inUganda,"lessthan21%ofbirthsofchildrenlessthanfiveyearsoldareregistered."Amobileplatformwasdevelopedsothat"individualscanregisterbirthsanddeaths."
Also"malaria,adiseaseaffectingnearly3.5billionpeople,hastheopportunitytobethefirstdiseasebeatenentirelybymobile."Thereareseveraleffortsincludingamobileremindersforusingbednets,enabledonations,andincreaseaccesstotestingandtreatment(Tsao).
"Traffickers,throughtheuseofmobiles,areabletoorganize,advertise,andstreamlinetheirillicitactivitieswhileexpandingtheircriminalnetworks.Asaconsequence,morepeopleareenslavedthanattheheightoftheAtlantictrade,andpartlyduetoanadditiveabilitytocommunicate."MobileprovidesavarietyoftoolsthatcouldmakethisamuchriskierbusinessbyincreasingcommunicationcapabilitiesandphysicaltrackingthroughGPS(Tsao).
Ogunlesi,T.andBusari,S.September14,2012.Retrievedfromhttp://www.cnn.com/2012/09/13/world/africa/mobile-
EmergingUseCases
MobilePayments
Activism
DisasterManagement
Agriculture
Health
HumanTrafficking
References
phones-change-africa/.Kochi,E.May27,2012.Retrievedfromhttp://techcrunch.com/2012/05/27/mobile-developing-world/.Tsao,C.October,8,2013.Retrievedfromhttp://www.huffingtonpost.com/clara-tsao/6-ways-mobile-techology-h_b_4054076.html.
IcompletelyagreewithMartinFowler:
Tome,legacycodeissimplycodewithouttests....Codewithouttestsisbadcode.Itdoesn'tmatterhowwellwrittenitis;itdoesn'tmatterhowprettyorobject-orientedorwell-encapsulateditis.Withtests,wecanchangethebehaviorofourcodequicklyandverifiably.Withoutthem,wereallydon'tknowifourcodeisgettingbetterorworse.
Unittestingisafundamentalaspectofcomputersciencethatisoftenignored.WenevertalkedaboutitincollegeandIdidn'tstarthearingmuchaboutituntilafewyearsintomycodingcareer.
Iamafairlyrecentconverttounittesting.AtfirstIdidn'tseethevalue.Itfeltlikeextrawork.Afewyearsago,IspentthreemonthsofintensepairingwithanotherAndroiddeveloperanditchangedmywholeoutlook!Seeinghowmuchwewroteeachdayandhowmuchconfidenceweendedupwithinourdesignwasrefreshing.ItwasadeparturefromothergroupsIhadworkedwiththatonlyvaluedquickcode.Thismentalityencouragesgunslinging,cowboycoders.
Manylanguagesandframeworkshighlyvaluetesting,butit'sanareathatAndroidoverlooked.TherearesometestingcapabilitiesinAndroid,buttheyrelyontheemulatororanattacheddevicesandaretooslowtouseastheprimarymeansoftestingduringthedevelopmentphase.Thistypeoftestingisbettersuitedforfunctionaland/orintegration-basedtestingoffeaturesinyourapplication.
Whennotusingtesting,thealternativeistobuildtheapplicationandseewhathappens,lookatapptoverifyexpectedbehavior,andreadlogs.It'snotterriblyefficient!
Unittestingisabestpractice,buthasbeenparticularlydifficultinAndroid.OnelibrarythatmakesthisprocessmuchsimplerisRobolectric.
Robolectricallowsyoutofocuscloselyontheapplicationyouarebuildingasyoubuildoutpiecebypiece.Youwritejustenoughcodetopassthetests.Itallowsyoutodotargetedandbroadrefactoringwithoutworryingaboutbreakingtherestofthesystem.Ithelpsuswritebettercodeandhelpskeepusontrack.
RobolectricwascreatedtoruncoreAndroidcomponentsontheJVMandallowdeveloperstoverifyaspectsoftheircodeastheyaredevelopinginsteadofafterthefeaturehasbeendeployedtoanemulatorordevice.
RunningtestsonanAndroidemulatorordeviceisslow!Building,deploying,andlaunchingtheappoftentakesaminuteormore.That'snowaytodoTDD.Theremustbeabetterway.
Wouldn'titbenicetorunyourAndroidtestsdirectlyfrominsideyourIDE?Perhapsyou'vetried,andbeenthwartedbythedreadedjava.lang.RuntimeException:Stub!?
Robolectricisaunittestframeworkthatde-fangstheAndroidSDKjarsoyoucantest-drivethedevelopmentofyourAndroidapp.TestsruninsidetheJVMonyourworkstationinseconds.
Chapter2:TDDwithRobolectric
Android
Robolectric
ThislabwillwalkyouthroughusingIntelliJtogeneratetheprojectandmaventomakeintegrateRobolectric.
AftercreatinganAndroidprojectwiththewizard,youmovethesourcefilesintoamvn-likestructure.ThenyouconfiguremodulesettingsinIntelliJ.ToinstallRobolectric,youwilladdapomfile(mavendependencyfile)intotheproject.Finally,youwillwriteyourfirsttestandrunitinsidetheIDE.
Integrationcanbetricky,especiallywhencreatingaprojectfromscratch.I'mahugefanoflivinginIDE-landasmuchaspossible,sothisapproachminimizescommandlineworkandmanualprojectconfiguration.
AversionofthisCalculatorprojectcanbefoundhere:CalculatorLab.
Ithastagsforallthemajorstepstohelpyouasyouworkthroughthelabs.Ifyouwantedtofollowalongfromthebeginning,startwiththetag2.2-step1.Eachtagmatchesupwiththechapter'ssectionnumbers.
YouhaveinstalledIntelliJ(CEedition).YouhaveinstalledtheAndroidSDKandconfiguredIntelliJtouseit(tutorialhere).Youhavemaveninstalled.Youhaveinstalledmaven-android-sdk-deployeranddeployedatleastoneSDK,butpreferablyall,toyourlocal~/.m2/repository.
Adaptedfrom:Latislaw,C.August3,2012.IntegratingRobolectricwithIntelliJ.Retrievedfromhttp://chariotsolutions.com/blog/post/integrating-robolectric-with-intellij/.
LabBackground
github
Prerequisites
References
UsetheIntelliJAndroidwizardtocreateaHelloWorldproject.First,choosethestoragelocationandplatform.
Onthenextscreen:
NameyourapplicationCalculatorCreatea"Hello,World!activity"andnameitCalculatorActivitySetthepackagenametocom.mobiquity.calculatorChoose"USBdevice"asthe"TargetDevice"
RobolectricIntegration
Step1:CreateAndroidproject
UseIntelliJorthecommandlinetomovefilesintothefollowingstructure:
src/main/java/...src/test/java/...
Note:IntelliJmightnotlikeitwhenyouaddsubdirectoriestothefoldermarkedassource.Ifyouarehavingtroublesettingupthedirectorystructure,openthescreenshowninthenextstepandremovetheoldsourcefolderbeforeaddingnewsubfolders.
UpdatemodulesettingsinIntelliJtorecognizethesourceandtestdirectories(below:bluefolderissourceandtestfolderisgreen).
Step2:Setupdirectoriesformaven
Step3:ConfigureIntelliJsourceandtestfolders
Afteryouaredone,yourprojectshouldlooksomethinglikethis:
Copythissamplepom.xmlintoliveintherootofyourproject.ChangethegroupIdtosuityourproject(e.g.com.mobiquity.calculator).Ifdesired,alsoedittheartifactId,version,andnamevalues.
Check"MavenProjects"viewinIntelliJtoensurethatitlookssomethinglikethis:
Step4:IntegrateRobolectric
Step5:Maven
Ifyouseeerrors,youmayjustneedtorefreshandwaitforittofinishindexing/importingyourlibraries.ItmayhelptorunmvninstallonthecommandlineandrestartIntelliJ.
Ifyouarestillhavingissues,yourAndroidfacetmaybetheproblem.OpentheAndroidfacetforyourprojectandchangeto"GeneratebyIDE."
Adaptedfrom:Latislaw,C.August3,2012.IntegratingRobolectricwithIntelliJ.Retrievedfromhttp://chariotsolutions.com/blog/post/integrating-robolectric-with-intellij/.
References
Let'swriteourfirsttest!
IusetheIDEtogenerateatestinthecorrectfolder.OpenCalculatorActivity.javaandplaceyourcursoronthenameoftheclass.
UsetheMackeycombinationCommand+Shift+Ttocreatethetestforthisclass.
Lab:FirstTest
Step1:Createtestfile
WeneedRobolectric'shelptorunourtests.Addthislineabovethetestclassnameandimportassociatedclasses.
@RunWith(RobolectricTestRunner.class)
Step2:Testrunner
Addafieldfortheactivityundertestsothatwecanaccessitinallofthetestsinthisclass.
CalculatorActivityactivity;
ThenusesetUp()topopulateourfield.
@BeforepublicvoidsetUp()throwsException{activity=Robolectric.buildActivity(CalculatorActivity.class).create().start().resume().get();}
WeusetheRobolectriclifecyclemanagementfunctionstobuildandstartanactivity.Thelastfunctioncall,get(),returnsatestinstancethatyoucanusetoverifyvariousaspectsoftheactivity'sviewandbehavior.
Note:Thecallstocreate(),start(),andresume()referencethedifferentphasesofAndroid'sactivitylifecycle.ThiswillbecoveredindetailinChapter6:ManagingtheLifecycle.
Writeatestfortheactivity.
@TestpublicvoidshouldNotBeNull()throwsException{assertNotNull(activity);}
Youcouldruneachtestindividuallyasyouworkwithnewclasses,howeveritshouldbeacommontasktorunalltheunittests(e.g.priortocommit).Icreatearunconfigurationforthewholeproject.Let'screatearunconfigurationthatwillrunallthetestsatonce.
First,choose"EditConfigurations..."fromthe"Run"dropdownmenu.
Then,hitthe+buttonandchooseJUnit.
Step3:Setup
Step4:Test
Step5:Createarunconfigforalltests
Thenselect,"Allinpackage"andgiveyourconfigurationadescriptivename.
Usetherunconfigurationcreatedintheprevioussteptoensureourtestspass.
Ifyouforgotstep2,you'llseethiserrormessage:
java.lang.RuntimeException:Stub!atandroid.content.Context.(Context.java:4)atandroid.content.ContextWrapper.(ContextWrapper.java:5)atandroid.view.ContextThemeWrapper.(ContextThemeWrapper.java:5)atandroid.app.Activity.(Activity.java:6)...
Inthefuture,youcanrightclickonthetestfilenameoramethodnametorunatest,useakeyboardshortcut,orrunthemfromthecommandlinewithmvncleaninstall.
Ifyouarestillseeingissues,rebuildyourprojectafewtimestoconvinceIntelliJtogeneratetheR.javafile(whichlinkstoallyourapplicationsresources)and/orrunmvninstallfromthecommandline.
WecanuseIntelliJ'stoolsorthecommandlinetocommitourchangestoagitrepository.Thisstepshowsyoudetailsfor
Step6:Run
Step7:IntelliJgitintegration
theIDEroute.
FirstwewanttotellIntelliJthatwewillbeworkinginagitrepository.UsethedropdownmenuVCS->ImportintoVersionControl->CreateGitRepositorytocompletethisstep.
TODO:Insertimage
Afterwehaveintegratedgit,let'sviewourcurrentchangeset.UsethedropdownmenuVCS->ShowChangesViewtoseeourcurrentchangeset.
TODO:Insertimage
Beforewecommit,weneedtomakesurethatwe'rehappythefileslistedinourchangeset.Thereareseveralfilesweshouldignore,includingIntelliJ'sprojectfileslocatedinthe.idea/folder,the.imlfileforyourproject,andthegen/directory(usedbehindthescenesduringthebuildprocess).Let'suseIntelliJ'stoolstodothiswithintheIDE.
TODO:Insertimage
Note:TheIntelliJwizardaddsafewfileswewon'tneedsincewe'renotusingtheantbuildtool.WecansafelydeletethesefilesinsidetheIDEbyrightclickingonthefileandselectingdelete.Thesefilesareant.properties,build.xml,project.properties,local.propertiesandthebin/directory.
Note:Wealsoremoveproguard-project.txtforthetimebeing.Ifproguardisdesiredforyourproject,youcanconfigureitusingthisfile.
Oncewe'rehappywiththechangeset,let'scommit.Youshouldalwaysreviewthefilesandchangesyou'reabouttocommitafterpassingallprojecttests.
TODO:Insertimage
Nowlet'stalkaboutwhattotest!
Adaptedandexpanded:Latislaw,C.August3,2012.IntegratingRobolectricwithIntelliJ.Retrievedfromhttp://chariotsolutions.com/blog/post/integrating-robolectric-with-intellij/.
References
Inthissection,we'llcoversomeofthemostcommontypesoftestcasesandbestpracticestoconsiderwhendeterminingyourtestingstrategy.
Youshouldfocusyourunittestingonbusinesslogic,basicviewvalidation,andfunctionality.Youcanvalidatecertainrequirementsverywellwithunittesting(e.g."whenIclickthisbellimage,itwhistles"or"allactivitieshavealogoonthescreen").
Herearesomecommonexamples:
Ensuretheactivityandviewelementsarenotnull.Ensureexpectedfragmentandviewelementsarevisibleonthescreen.Ensurethattheproperresourcesareusedforviewelements.Ensureitemsarehiddenwhenexpected.Ensuretoastsareshown.Ensurethatyourintentstartsthecorrectthing.
Idon'trecommendinvestingmuchtimeinverifyinglessimportantstylingdetailsandXMLattributes.Youruserinterfaceislikelytochangemanytimesaweek,buttypicallythebasicviewelementsandtheirbehaviorremainthesame.Ifyouupdatedatesteachtimeabuttonhadnewpadding,thatwouldgetverytediousindeed!
Theapplogois250dphighwithaproportionalwidth,thefilenameismain_logo.png,ithasa20dpleftmarginand12dprightmargin,hasacontentdescriptionof"Text",andiscenteredverticallyoneveryscreen.
ReturnsstartdiminishingprettyquicklywhenyouverifyeverypossibleXMLattribute!Yourtimeisbestspentonitemsthatarerelevanttobusinessobjectives.Fromthisexample,likelythemostbangforyourbuckwillcomefromtestingthattheproperimageisusedandmakingsurethatitappearsonallexpectedscreens.
Rememberanyoftheattributesyoudon'ttestcanbecaughtbydesigners,qualityassurance,business,product,and/ortheengineers.Asolidstrategyistosweeptheappneardeploymentwithadesignertomakesuretheappappearsasexpectedonawiderangeofdevices.
SimpleAnimation
Latislaw,C.August7,2012.AndroidUnitTestingWithRobolectric.Retrievedfromhttp://chariotsolutions.com/blog/post/android-unit-testing-with-robolectric/.
TestingConsiderations
WhatToTest
WhatNotToTest
Example
AdditionalExamples
References
Aswithmostobjectorientedrealms,attempttosimplifythearchitectureasmuchaspossible.Dothisbycreatingabstractorbaseobjectsorinterfaces.Thiswayyoucantestsharedbehaviorinoneplaceinsteadofseveral,whichsimplifiestestsandreducescodeduplication.
Oftenwewanttoensurethatacertainactionwasperformedbutnotactuallyrunthecode.Todothis,youcreateatestclasswhichextendstheclassundertestandoverride/mockout/trackthataparticularfunctionwascalled.
Forexample,ifyouwantaparticularclicktomakeanAPIcall,thereisnoneedtomaketheactualcall(sincethiswouldbeanintegrationleveltestanyway).Youcanusethisstrategytotrackthatthefunctionthatinvokesthecallhasbeencalled,butavoidmakingtheactualcall.
Thisiscanalsobehelpfulwhenanoperationcrashestheunittestingframework(e.g.specialtylibrarythatcausesfunkysideeffects),doesn'tplaynice,orisotherwiseunnecessarytoinvokedirectly.
Icreateseveralutilityclassestoimprovethereadabilityofmycode.Theseliveinmyteststructureunderthepackagesupport.We'lladdthesefilesinthenextlab.
Androidstronglyencouragestheuseofabstractingstringresourcesintooneplaceoverusinghard-codedstringconstants.Iliketofollowasimilarpatternanduseatestconstantsclasswhenyouhavelotsoftestdata.ThiscanbereallyhelpfulwhencreatingauserwithlotsoffieldstomockoutaJSONresponse.
Ifyoufindyourselfwritingsomethingmorethanonce,that'sanexcellenttimetoreassess.LuckilysinceyouwillhavealargebaseofunittestsatyourdisposalaswellaspowerfulIDEtools,therefactoringwillhaveminimalimpactontherestofthesystem!
Finally,youshouldn'trelysolelyonunitteststoensuretheproperbehaviorofyourapp.Thesetests,thoughquiteuseful,onlygiveyouasmallwindowintoyourappandit'sbehavior.Atminimum,youshouldincludeintegrationleveltestsandhavesomelevelofmanualQAintheprocesstoensureyourappiseverythingthatyouwantittobe.
Latislaw,C.August7,2012.AndroidUnitTestingWithRobolectric.Retrievedfromhttp://chariotsolutions.com/blog/post/android-unit-testing-with-robolectric/.
BestPractices
SimplifyYourArchitecture
Mock/StubFunctionality
UtilityFunctions
CentralizeTestConstants
Don'tRepeatYourself(DRY)
RobustTestingStrategy
References
Let'saddutilityfunctionstooursupportpackage.It'llhelpreducethesomeoftheboilerplatewhenweworkthroughlaterlabs.
TechnicallywithTDDyou'dwaituntiltheexactmomentyouneedthecodetowriteit.Ipreferpracticalityoverbeingpedantic.
publicclassAssert{publicstaticvoidassertViewIsVisible(Viewview){assertNotNull(view);assertThat(view.getVisibility(),equalTo(View.VISIBLE));}}
publicclassResourceLocator{publicstaticStringgetString(intstringId){returnRobolectric.application.getString(stringId);}
publicstaticDrawablegetDrawable(intdrawableId){returnRobolectric.application.getResources().getDrawable(drawableId);}}
WiththeversionofRobolectricwe'reusing,weneedtomakeourownversionofafragmentstarter.
Robolectrichasoneforsupportfragments,butdoesn'thaveonefor"normal"platformfragments.Thisshouldbeinanupcomingrelease.We'vecopiedtheirframeworkversionhereandmodifiedtousenormalfragments.YoucanfindthelatestsourceforFragmentTestUtilongithub.
publicclassFragmentUtil{publicstaticvoidstartFragment(Fragmentfragment){Activityactivity=createActivity();
FragmentManagerfragmentManager=activity.getFragmentManager();fragmentManager.beginTransaction().add(fragment,null).commit();}
privatestaticActivitycreateActivity(){returnRobolectric.buildActivity(Activity.class)
Lab:UtilityFunctions
CreateAssert.java
CreateResourceLocator.java
CreateFragmentUtil.java
.create().start().resume().get();}}
Therearemanyotherformsoftestingthatyoucanincorporateintoyourdevelopmentlifecycle.Theseothertoolsareoutsidethescopeofthisbook,butarelistedhereforeasyreferenceandfutureexploration.
HerearetheAndroidsanctionedwaystotest.
YouuseJunitstyletestsandcreateatestapplicationthatrunswithyournormalapplication.Thetestapplicationexercisestheuserinterface.
Itcanbegreatforfunctionalorintegrationtesting,butsinceitreliesonanemulator,it'sjusttooslowforas-you-are-building-a-featuretesting.
http://developer.android.com/tools/testing/testing_android.html
Thistestingframeworkrunsonthedeviceandusesaccessibilityfeaturestoconductfunctionaltesting.
http://developer.android.com/tools/help/uiautomator/index.html
ThisframeworkallowsyoutoscripttestinPythonandrunsyourtestsonanemulator.http://developer.android.com/tools/help/monkeyrunner_concepts.html
Therearemanytoolsoutthere.Eachapplicationmayleadtoadifferentselection!
Calabash:http://calaba.sh/Robotium:https://code.google.com/p/robotium/Appium:http://appium.io/
OtherTesting
Android
InstrumentationTesting
uiautomator
monkeyrunner
OtherTools
NowthatyouknowwhyAndroidissuchacompellingsystem,let'slookathowthesystemisconstructed.AlotofpainandsufferingcanbesparedifwefollowAndroid'sconventionsandlooselycoupledmodel.Writingcodethiswaymakesiteasiertowriteandmaintain.Weshouldstrivenotonlytomakebeautifulcode,butalsoengagingpersonal,andfastexperiencesforourusers.
TherearemanylayersofdecouplingintheAndroidsystem.Theapplicationsareindependententitiesthatcansendmessages,butneverknowtoomuchabouteachother.
Themodelisabstractedawayfromthedisplayofthedataandaccessedbycontentprovidersandothermechanisms.
ViewsareabstractedfromthebusinesslogicandintoXMLfilesthatmakeiteasytochangetheappearanceoftheviewwithoutchangingthewaythattheviewworks.
Viewsarealsodecoupledfromtheresourcesthattheyuseandthelogicfromchoosingwhichviewisrightfortheparticulardeviceitisrunningon.
Assetsandothercontentareabstractedfromtheviewandbusinesslogicsothatthecontentcanchangewithoutrequiringanupdateinthecodetosupportsmallcopychanges.
Chapter3:Architecture
AndroidisanopensourcesoftwareandhardwaresystemthatsitsontopofaLinuxkernel.ItalsoincludesdevicesandthesetofapplicationsthatrunontheOS.
YoucanbrowsethesourceAndroidOpenSourceProject(AOSP)atsource.android.com.
Android'sarchitecturehasmanylayers.
Ifyou'dlikedetailedinformationaboutthestackandAndroid'ssecurityfeatures,youcanreadmorehere:http://source.android.com/devices/tech/security/index.html
Thetopofthestackiswhereallthebuiltinapplications,3rdpartyapplications,andyourapplicationslive.Allappsherearecreatedequalandhavethesameaccesstotherestofthestack.
Android
ArchitectureLayers
Thesecondlayerincludestheapplicationframework,whichgivesyouthetoolstowriteapplications,suchastheSDK,activitymanagers,locationmanagers,notificationmanagers,andtheviewsystem.
ThehardwareaccesslayeriswherelibrariesarelocatedforinteractingwithGPS,Wi-Fi,Bluetooth,NFC,andotherhardwarefeatures.Theruntimeisalsoatthislayer.
Eachapplicationrunsinit'sownvirtualmachine(VM)instance,whichmeansthatapplicationscannotdirectlyinvadeeachother'sprocessspace.ThesystemprovidesLinux-stylepermissioncontrolswhilemaintaininganopensystemthroughIntentsandotherinterprocesscommunicationcapabilities.
Atit'slowestlevel,theLinuxkernelhandlesdrivers,powermanagement,andotherlowlevelprocesses.
ThecompilationphasesincludeturningyourJavafilesinto.dexbytecodefiles,whichisAndroid'sversionofJavabytecode.AnR.javafileiscreatedsothatJavacanrefertotheXMLcomponentsandotherapplicationresources.
Theoutputofcompilationisan.apk,whichatit'sheartisbasicallya.zipfile.
Here'smoredetailhereaboutthestagesofcompilation:http://developer.android.com/tools/building/index.html
DEXbytecodeisrunonavirtualmachine(muchlikeJavarunsontheJVM),calledtheDVM,orDalvikVirtualMachine.TheDVMwaswrittentobeoptimizedformobiledevices.
Getallthelowleveldetailshere:https://source.android.com/devices/tech/dalvik/index.html
InthefuturetheDVMwillbereplacedwiththenewAndroidRunTime(ART).
Yourapplication'sresourcesareboundatruntimewhenAndroiddetermineswhichdeviceitisrunningonandchoosesthebestresourcesforthatparticulardevice.
Intentsarealsoaruntimebinding.Youissuearequestandanyappthatcanrespondtotherequestwill.Theuserchooseswhichactiontotakebasedonaparticulartypeofrequestorthesystemusesuser'sdefaults.
Applicationsaresignedwithakey.Thiscombinedwiththeuniquepackagenameiswhatidentifiesanapplicationonthesystem.
Bydefault,whenyoucreatedevelopmentbuilds,youareusingadefaultkeytosignyourapplication.Youwilluseadifferentkeywithapasswordwhenyouprepareforrelease.
Note:Onceyoudeployyourapplicationwiththisreleasekeyyouareforeverstuckwiththekeyandpackagename.That'swhyit'ssoimportanttodeterminewhatyou'dliketouseforyourpackagenameandtoalwayskeepyourreleasekeysafe!
Note:It'spossibletohavebothadebugandreleasesignedversionofthesameapplicationonyourdevicesincethepackagenameandsignatureareusedtogethertoidentifyanapplication.
Compilation
Runtime
Signing
Thereareabstractionsateveryleveltohelpyouseparateconcerns,maintaincodeeasier,andsupportthemultitudeofdevicesandformfactorsinthewild.Androidgivesyoutoolstotodecouplethepresentationlayerfromthebusinesslogic.
AlthoughsomearguethatAndroidisnotatrueMVCsystem,it'shelpfultoapproachitinthisway.
ModelViewController
Theviewandresourcesystemallowsustobreakoutvisualcomponents.Androidautomaticallyhandlesmostofthelogic
View
aboutchoosingwhichcomponenttouseforwhichformfactor.YouspecifythisinXMLandputinspecialfolders.Thisenablesscalingtodifferentformfactorsaswellasinternationalization.
TheJavalayeriswhereyoutiethevisualcomponentstothebusinesslogicofyourapplicationandwhereyouwouldaccessthemodelordataofyoursystem.Serviceswouldalsofallintothislayer.
Finally,themodellayeriswhereyouwouldstorethedatathatpowerstheapplication.ContentprovidersallowyoutoabstractSQLqueriesawayfromyourmodel'susersandsurfacedatathroughouttheapplicationandsystemwide,ifyoudesire.
Controller
Model
Anapplicationismadeupofaseriesofactivityscreens.Thesearestrungtogetherwithintentstostartupthenextactivity.Activitiesarebuildofviewsandfragments.Fragmentsarebuiltfromviews.
Activitiesarethemajorbuildingblocksofyourapplicationandareroughlythescreensthatyouseeinanapplication.Theyusefragmentsandviewstoconstructtheuserinterfacethatyousee.
Activitiesarethemajorbuildingblocksofyourapplicationandarethepresentationlayer,orscreensyouseeinanapplication.Activitiesarecomposedofviewsandfragmentsandseveralactivitiesarecombinedtomakeanapplication.
Fromtheactivityyouhaveaccesstoalltheviews,resources,systemstate,andthemodel.
Servicesareusedforlongrunningapplications,suchasnetworkoperations.
Thisisanapplicationwithtextviewsandbuttons.Whenweclickonthebuttonitlaunchesanactivity.
BuildingBlocks
Example:
We'llgooveralloftheseingreaterdetailinlaterchapters.
Intentsallowmessagepassingandlateruntimebindingbetweencomponents.Basicallyyoubroadcastadesire,suchasopeningawebbrowseroraspecificActivityyoucreated.Androidhandlestherest.
Agoodexampleiswhensharingapictureyousnappedwithasocialnetwork.Youhaveoptions,suchasTwitter,Instagram,etc.dependingonwhatyouhaveinstalled.Ifyouarewritingacameraapplication,youdon'thavetocareabouthowsomeoneplanstosharethepicture,justthattheyareabletodoitinthemannertheywish.
MessagePassing
Intents
Usingintentsfreesyoutofocusoncreatingthecontentthatisimportanttoyourapplication,notimplementingorforcingpeopletouseaparticularmethod.Itmakesyourappaparticipantinthesysteminsteadofaself-containedappthatmust
handleeverythingbyitself.You'repartofthecommunity!
Youhaveseveraloptionswithwheninvokinganintent:
Startoneofyourapplication'sowncomponents(e.g.byusingstartActivity()withaninternalclass).Thiskeepstheintentwithinthecurrentprocess'boundaries.Sendanintentforanactivityfromanotherapplicationthatcrossesprocessboundaries.Broadcastasystem-wideintent,suchasopeningawebbrowserorsharingapieceofcontent.Thisalsocrossesprocessboundaries.Thesystempresentstheuserwithanoptionofhowtoreacttotherequest.
Inthisexample,wearegettingareferencetoabuttonandsettingaclicklistenerthatstartsaninternalactivity.
findViewById(R.id.activity_button).setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){startActivity(ViewSystemActivity.createIntent(LooselyCoupledActivity.this));}};)
Eventbusesareagreatwaytodecoupleourcomponentswithoutusingainterfaceorlistenerpatternthatcanproducealotofboilerplatecode.Youcanuseanapplication-widebus,suchasOtto,topassmessages.
CodeExample
EventBus
Androidisaneventdrivensystem.ThemainUIthreadloopsindefinitelywaitingforaneweventoruserinput.Whensomethingisreceived,itisprocessed.
Ifadditionalprocessingisrequiredforaparticulareventthatincludesalongrunningoperation,itshouldbedoneinanotherthread.Examplesoflongrunningprocessesarenetworkdownloads,databaselookups,orfileI/O.
Ifyouattempttodolongrunningprocessingonthemainthread,it'slikelyyouwilleithergetanexceptionoractivitynotrespondingdialog(ANR).Thisshouldbeavoidedatallcostssinceit'sawfuluserexperience!
Ourfirstapplicationdoesn'tdoanyofthissortofprocessing,sowewilllookatthosetopicsingreaterdetaillater.
Youcandoallthenormalthreadingthingsyou'reusedtowithJava.YouuseThreadandHandlerclassestopostinformationbacktothemaincallingthread.
Thesetasksareusedtodobackgroundprocessing,butshouldn'tbeusedforlongrunningtasks.TheyhaveconveniencemethodsthatallowyoutointeractwiththeUIthreadbefore,during,andafteryourprocessiscomplete.ThesetasksaretiedtotheActivity'slifecycle.
Thisiswhereyouconductlongrunningprocessesthateitherhandlenetworking,streaming,updatingwidgets,oravarietyofothertasks.ServiceslivewithinyourApplication'sprocessboundaries.
Youcanalsouseafragmentwithoutaviewasabackgroundworker.Whenyouinflatetheview,yousettheviewtonull.ThisistiedtothelifecycleoftheActivity.
ThreadingModel
UIThread
JavaThreads
AsyncTask
Service
BackgroundFragments
Inthischapter,we'llgooverthefoundationalbuildingblocksofAndroidandextendourfirstapplication!
Forthischapter,we'llbereferringthisexampleandstartingourownproject!
Chapter4:AndroidFundamentals
Calculator
ActivitiesarewritteninJavaandregisteredinthemanifest.Theyliveinthepackagestructurethatyoudefineinthemanifestfile.Youcancreatesubdirectoriestobetterorganizeyourfiles.
publicclassLooselyCoupledActivityextendsActivity{@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loosely_coupled);}}
Whereverpossible,youshouldstrivemakeyouractivitiesasdumbaspossible,essentiallyanemptyshellforyourfragments.You'dalsodoworklikeconfiguringtheactionbarandmenushere.
IdeallymostofthebusinesslogicwouldbemovedtoPlainOldJavaObjects(POJOs)forunittestingpurposes,butinpracticesomeofthatlogicendsupinthesubviewsorfragments.
OftenActivitiesareusedasanintermediarybetweencomponents(e.g.Fragments)becauseyoudon'twantthemtalkingdirectlytoeachother.Byusingthelistenerpatternorasystembus,suchasOtto,thecomponentscanpostamessageandtheActivitywillreaditandrespond.Thiskeepstheconcernsseparateandeasiertomaintaintheindividualcomponents.
Youcanstartanactivityinsideahostingactivityandgetresultsfromthatactivity.
YouusestartActivityForResult()tostarttheactivity.Intheactivitythatwasstarted,youusesetResult()tosettheresultthatwillbereturned.Whenbackinthecallingactivity,youchecktheresultcodeandrespondappropriately.
Agreatexampleofthisisinvokingthesystemcameraandthenprocessingwhetherthepicture-takingeventwassuccessful:http://developer.android.com/guide/topics/media/camera.html
Activities
CodeExample
Activity'sRole
ActivityResults
Thelooselycoupledcomponents(e.g.activitiesandservices)arestitchedtogetherbytheAndroidManifest.xmlfileatruntime.Thisfiledescribeseachofyourcomponentsandhowtheyworktogether.Youdon'tregisterfragmentsherebecausetheyaretransientandtiedtotheactivitythathoststhem.
Inthisfileyouspecifywhichactivity(oractivities)thatarelaunchable.Youcanspecifyhowthingsarelaunched,howtohandleorientations,testingapplicationinformation(whenusinginstrumentation),andhowtohandletheSDcard.Finally,youspecifymetadataabouttheapplicationlikethename,versionname,versioncode,icon,andtheme.
Thepackagespecifiesthepackagestructureforyourapplicationandisusedtouniquelyidentifyyourapplicationinthemarket.
Theapplicationlabelreferstoastringresourcethatwillbeshownonthelaunchgridofthedevice.Usingastringresourceallowsyoutocustomizeforinternationalization.We'llcoverresourcesmoreindepthlater.
TheversionNameisapublic-facingnamefortheversionoftheapplication.TheversionCodeisanintegervalue.Youshouldincreaseitforeachreleasetothemarketandgenerallywhendevelopingtheapplicationanddoinginternalreleases.TheversioncodecombinedwiththesignatureandpackagenameiswhattellsAndroiddeviceusersthatthereisanupdatefortheirphone.
Insidethetag,youspecifytheactivitiesandservicesthatyouwilluseintheapplication.
Ifyoucreateanactivityanddon'tregisteritinthemanifest,youwillgetacrashwithasurprisinglyhelpfulerrormessage.
ThisfileisalsousedasafilterbytheGooglePlaystore.Youcanspecifyapplicationpermissions,whathardwarefeaturesyourequire,andwhatOSversionsyousupport.
Iftheuser'sdevicedoesn'tsupportoneofyourrequirements,thenitwon'tbeshowninsearchresultswhentheysearchonthedevice.Iftheysearchontheweb,theywillfindyourapp,butwon'tbeabletoinstallondevicesthatdon'tsupportyourapplication'srequirements.
Youcanfindmoreaboutfilteringinthestorehere:http://developer.android.com/google/play/filters.html
AndroidManifest.xml
Example
ManifestFiltering
LayoutsarewhereyoudefinetheviewofyourapplicationusingbuiltinAndroidviews,viewgroups,and/oryourowncustomviewsbasedonthem.TheseXMLfilesliveinyourres/directory.Writinglayoutsthiswayallowsustodecouplethepresentationlayerfrombusinesslogic.
AlthoughyoucouldwriteallyourviewsinJava,thatmakesitalothardertoleveragethefullpowerofresourcesystem.Plusitoftenbecomesamaintenanceissue.
Thereisalwaysoneparentattherootofthelayoutandthelayoutmaycontainmanyviews.
...
Therearemanyprebuiltitemsthatyoucanuse,includingButton,TextView,ImageView,grids,andmore!
YougiveeachviewanidsothatyoucanwireuptologicintheJavaclassthatpointstothisview.ThesystemgeneratesanR.javafilebehindthescenesthatmapsyourresourcesandviewstoaJava-accessibleconstruct.Thisisgeneratedatcompiletime,butthedecisionofwhichviewtoshowisdeterminedatruntime.
Note:SometimestheR.javafilesgetsoutofsyncwithyourviewsandresources.Thisoftenhappensifyouchangealotinasmallamountoftime.Ifyoustartseeingweirdclasscastexceptions,thenthismaybeyourculprit.
Inthisexample,theviewactivity_buttonisdefinedinactivity_loosely_coupled.xmlwithanid:
Intheactivity,youusesetContentView()tospecifywhichlayouttouseandAndroidbringsittolife.Afterthat,youcanaccessitssubviewswiththeidyougaveitintheXMLfile.
findViewById(R.id.activity_button).setOnClickListener(newView.OnClickListener(){
Layouts
Example:activity_loosely_coupled.xml
XMLviews
Referencingintheactivity
@OverridepublicvoidonClick(Viewv){startActivity(createViewSystemIntent());}};}
InthisexamplelayoutwecanmaketheactivitybuttondosomethingbyreferencingitinonCreate().Hereweattachaclicklistenerthatwillopenanotheractivity.
Youcanchangeallmannerofinformationabouttheviews.Goodexamplesaresettingthetextorcolorstodisplay,animatingviews,and/orattachinguseractions.
TheXMLgetsturnedintoJavacomponentsatruntimewhentheAndroidsystem"inflates"theview.
Asshownabove,withanActivitytheinflationoccursinthelifecyclemethodonCreate()withthesetContentView()function.
It'salittledifferentinFragment'sbecausetheinflationoccursinthelifecyclemethodonCreateView()byusingtheinflate()function.
Whenviewsareinflated,theyareaddedtotheviewhierarchy.Anytimethatyouaddsubviewsorviewgroups,youaredeepeningthehierarchytreethatrepresentsyourviews.YoucanusetheHierarchyViewertooltooptimizeviewsthatareloadingslowly.
AlloftheviewcomponentsareJavaclasses,whichmeanstheycanbeextended!
Youcanaddcustombehaviorwhenabuiltincomponentsprovidesome,thoughnotallofthebehavioryou'dlike.Youcanalsocreatecustomviewsthatarecollectionsofthebasicviewtypes.
Forexample,sayyouwantedtocreateadateandtimeclock.YoucouldcreateaviewthatcombinesaTextViewforthedateandandimageorothercontroltoshowananalogversionofthetime).
Theseviewsareonlylimitedbyyourimagination!Wewon'tbecoveringthemindepthinthisclass,butthere'sanexcellentpresentationbyChiu-KiChan:CustomComponents.
Inflation
Customviews
AwaytoorganizeandsimplifyyourXMLlayoutsistouseviewgroups.Youcanusethemtoholdchildrenviewsandmakereusablecomponents.Youcanalsoextendthemtoaddyourownbehavior.
Herearesomeofthemostcommonlyusedoptions.
Thisisthesimplestoftheviewgroups.It'sdesignedtoholdonechildview.Thislayoutisoftenusedasaholderfordynamicfragments.
Asthenameimplies,withthisnameyoulayviewitemsoutinaline,eitherverticallyorhorizontally.
ViewGroups
FrameLayout
LinearLayout
Withthisviewgroup,youcanlayoutelementsinarelativefashion.Forexample,placethestartotherightofthecircleandtheheartbelowthecircle.
RelativeLayout
Withthisviewgroup,youcanlayoutsimilarelementsinagridfashion.ThisavailableinlaterOSversionsandhasbeenbackportedforolderOSversions.
GridLayout
ViewStubs
Whenyourviewsstarttogetcomplicated,youcanbreakitupusingviewstubs.Thiscanbeusedtolazilyinflateviewsatruntime.
Moreinformationhere:http://developer.android.com/reference/android/view/ViewStub.html
Anactivityisthestartingpointforascreen,butifweputalltheviewsandtheirlogictogetheritquicklydissolvesintoahugemess!Amuchbetterwaytoconstructyourviewsiswithfragmentstofurtherencapsulatetheviewlogicintoself-containedpieces.
Itbreaksthelogicoftheactivityupintoself-containedpiecesthathandleuserinput.Thisisgreatforalotofreasons.Itletsyoureusethesecomponentsinotherlayoutstosupportdifferentformfactorswithoutchangingcode,justconstructinganewlayoutwithadifferentarrangementoffragmentsandviews.
Activitiesholdfragments,whichcan'tliveoutsideahost.Theactivityreactstonotificationsfromthefragmentthattheviewshouldbealtered.ThefragmentholdsareferencetothehostingactivityandcanaccessitbycallinggetActivity().
Considertheexampleapplicationabove.Thetabletversionhasalistofarticlesontheleftsideofthescreenandadetailpaneontheright.Thephonesusestwoseparateactivitiestoshowtheseviews.
Whenauserselectsanewarticletoview,thefragmentontherightshouldupdate.Youwouldn'twantthearticledetail,suchasanarticleaboutDoctorWho,toberesponsibleforupdatingtheviewtoshowanarticleaboutcats.
Italsodoesn'tmakemuchsenseforthelisttoknowalotofinformationaboutthedetailit'sgoingtoshow.HereyouwouldusetheActivitytodeterminewhichdetailviewnext.Thisbecomesimportantwhenyoualsohaveaphoneimplementationthatwouldappearintotallydifferentactivities.
So,howdowedoit?Whentheusertapsanarticleinthelist,aneventistriggeredandtheActivityrespondstothisreceivedevent.Inthecaseofthetablet,itwillsimplyupdatetherightpane.Inthecaseofthephone,itwouldstartanewactivity.
Fragmentsweren'talwaysaround.TheyintroducedafewyearsagowiththefirsttabletsandHoneycomb(Android3.x).
Fragments
MasterDetailPattern
TheGreatSchism
Dashboard,July2014:https://developer.android.com/about/dashboards/index.html
ItmakesitcomplicatedtosupportthefullrangeofOSversions,butit'sbecomingmoreandmorecompellingtosunsettheolderversionsastheirpercentagecontinuestodrop.Asofthewritingofthisbook,thepercentageofOSesinthewildthatdon'tincludeFragment'sisonly14%(combinedpercentagesofFroyoandGingerbread).
However,ifyoudointendtosupportolderversions,theyhavebackporteditallthewaybackto1.6usingthesupportlibrary.
InthislabwewilllearnabouttheAndroidvisualparadigmsbyexploringthedesignsofexistingapplications.Thiswillhelpusdevelopaprocessforbreakingdownadesignintoimplementablepieces.Thiswillcomeinhandywhenstartingnewscreens.
Afterwefinishthislab,we'llbereadytostartbuildingourapplication.
Pleaserefertotheclasshandoutforparts1,2,&3.Asolutionhandoutdetailshowthedesignscouldbebrokendown.
Let'sgetfamiliarwiththeAndroiddesignsite:
http://developer.android.com/design/building-blocks/index.html
Thisexcellentresourceliststheitemsyoucanuseaswellasbestpracticesfortheplatform.Wewon'tbecoveringAndroiddesignindetail,butthisresourceisagreatstartingplaceforunderstandingthedesignlanguageoftheplatform.
MakesuretocheckoutMaterialDesignresourcestoseewhatiscomingwiththeLreleaselaterthisyear!CheckoutthisvideoformoreinformationontrainsitioningfromHolotoMaterial.
Note:Seetheappendixformoredesignresources.
Whatdoyoufindinterestingaboutthedesignlanguage?Howdoesitdifferfromotherplatforms?Canyouthinkofotherplatformfeaturesthatdon'tfeelathomeonAndroid?Doyoufindthenavigationparadigmsintuitive?WhatdoyouthinkoftheevolutionofAndroid'sdesignthroughtheages?WhatdoyouthinkofMaterialDesign?Hadyouheardanythingaboutitbeforetheclass?
We'llbreakdownthedesignoftheGoogleMusicappasaclass.
Pleasepairup,analyzetheview,andidentifyviewcomponentstheymayhaveusedtoconstructthisview.
Let'sstartourcalculator!
WorkwithyourpartnertoidentifyatleasttwodifferentwaystoyoucouldbreakdownthisviewintoXMLcomponents.We'llstartimplementingsoon!
Thenexttimeyou'rebreakingdownadesign,thinkabouthowyoucansegmentitintoviewsandfragmentstobestsupporttheuserexperienceyouaregoingfor.
Lab:DesignChunking
AndroidDesign
DiscussionQuestions
Part1:ClassDesign
Part2:PairDesign
Part3:ClassProject
We'llworkthroughthisexercisetogetherasaclass.
Handout:DesignChunking
Part1:GoogleMusic
Pleasepairup,analyzetheview,andidentifyviewcomponentstheymayhaveusedtoconstructthisview.
Part2:Twitter
WorkwithyourpartnertoidentifyatleasttwodifferentwaystoyoucouldbreakdownthisviewintoXMLcomponents.
Chooseyourfavoriteapplicationandbreakdownseveraloftheirscreensintodesignchunks.It'sagreatwaytolearnfromothers!
Part3:Calculator
ExtraCredit
TheyuseActionBar(transparent),withatitleofthealbumandoneicon(search).
Solution:DesignChunking
Part1:GoogleMusic
TheactionbaroverlaysanImageViewfortheartist.Belowthatisanimageofthealbumwe'reviewing.TotherightofthealbumisalbuminformationdisplayedinTextView'sandseveraloptionsavailablejusttotherightofthealbumcover(eitherButton'sorImageView's).ThisislikelyaRelativeLayoutsincethingsarelaidoutrelativetootheritemsonthescreen.
UnderthealbuminfoisthelistofsongsforthisalbuminaListView.EachlistviewitemisfairlysimplecollectionofTextView'sandanImageViewforalbumoptions.There'sanImageViewthatshowsonarowonlyifthesongiscurrentlyplaying.
Note:Whenscrollingdowninthelistofsongs,thealbumandartistinformationispushedoffthescreensothatyoucanfocusonthemostrelevantinformation.Thiswouldbeacustomimplementationtoaddthisbehavior.
Attheverybottomofthescreen,thereisacustomviewthatallowsyoutoplay/pausethecurrentsongoropenthefullsongviewthathasahostofotheroptions.
Note:Thisviewispersistentthroughouttheapplicationevenifyoubrowseotheralbums.
There'salotgoingoninthisdesign!
Twitteralsousesanactionbarwithicons,notitle,andanoverflowmenu.Theyuseatabcontrollerjustbelowtheactionbarforthedifferenttweetstreams,whichhasaindicatorforthecurrenttab.
Part2:Twitter
YourtweetstreamisdisplayedinaListView.Eachtweetishasseveralpiecesofdata,suchastextviewsandimagesthatrepresentretweets,authors,timesinceposting,etc.
Atthebottomofthescreen,theyhaveacustomviewthatcombinestwobuttonsforpostingimagesandanEditText(customimplementation)forenteringanewtweet.
Clickingonmostoptionstakesyoutoanotheractivity.
Therearemanyvalidwaystobreakdownadesign.Eachchoicehasconsequencesorbenefitswhenwebuildouttheapplication.
Inourclassimplementation,we'llbeusingtwoFragmentslaidoutinaLinearLayoutwithandroid:orientation="vertical".
Part3:Calculator
TheDisplayFragmentwillhandlethedisplay.We'lluseanEditTexttodisplaythenumbersenteredintothecalculatoraswellascalculations.
TheButtonFragmentwillcontainandcontrolthecalculatorbuttons.We'lluseaRelativeLayouttopositionmanyButton'sforoperationsandnumbers.
Whatwasyourdesign?Howdoesitdiffer?Howdoyouthinkthatwillimpactimplementation?
DiscussionQuestions
Ensuretheactivityandviewelementsarenotnull.Ensureexpectedfragmentandviewelementsarevisibleonthescreen.Ensurethattheproperresourcesareusedforviewelements.Ensureitemsarehiddenwhenexpected.Ensuretoastsareshown.Ensurethatyourintentstartsthecorrectthing.
Lab:ConstructTheView
TestingReminder
Let'sdothistogetherasaclass.
publicclassDisplayFragmentextendsFragment{@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){Viewlayout=inflater.inflate(R.layout.display,container,false);returnlayout;}}
TheXMLviewdoesn'texist,sowe'llcreateafilecalleddisplay.xmlinthesrc/layout/folder.We'lladdthespecificsoftheviewlater.
@RunWith(RobolectricTestRunner.class)
publicclassDisplayFragmentTest{@TestpublicvoidshouldNotBeNull()throwsException{DisplayFragmentfragment=newDisplayFragment();startFragment(fragment);assertNotNull(fragment);}}
Atthispointweshouldbeabletorunthetestsuccessfully.
Let'saddourfragmenttomain.xml(layoutfilespecifiedinsetContentView()oftheCalculatorActivity).
android:name="com.mobiquity.calculator.DisplayFragment"android:layout_width="match_parent"android:layout_height="wrap_content"/>
@TestpublicvoidshouldHaveDisplayFragment()throwsException{assertNotNull(activity.getFragmentManager().findFragmentById(R.id.display_fragment));}
Makesuretorunthetestsandthencommityourworktoyourrepository.
Testpresenceintheactivity
Test&commit
Yourturn!Pleasecompletethistaskwithyourpartner.
publicclassButtonFragmentextendsFragment{@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){Viewlayout=inflater.inflate(R.layout.buttons,container,false);returnlayout;}}
TheXMLviewdoesn'texist,sowe'llcreateafilecalledbuttons.xmlinthesrc/layout/folder.We'lladdthespecificsoftheviewlater.
@RunWith(RobolectricTestRunner.class)
publicclassButtonFragmentTest{@TestpublicvoidshouldNotBeNull()throwsException{ButtonFragmentfragment=newButtonFragment();startFragment(fragment);assertNotNull(fragment);}}
Let'saddourfragmenttomain.xmlbelowtheDisplayFragment.
Lab:AddButtonFragment
CreateButtonFragment.java
Createtheview
CreateButtonFragmentTest.java
Addtoview
@TestpublicvoidshouldHaveButtonsFragment()throwsException{assertNotNull(activity.getFragmentManager().findFragmentById(R.id.buttons_fragment));}
Makesuretorunthetestsandthencommityourworktoyourrepository.
Testpresenceintheactivity
Test&commit
ReplacetheLinearLayoutfrompreviousstepswiththisEditTextindisplay.xml.
Wecandothissinceeachviewexpectsonlyoneviewattheroot,butmayhavemore.Sinceourviewissosimple,thereisnoneedtohaveanenclosingviewgroup.
HereI'veaddedmanyXMLattributes!Theattributesaremostlyselfexplanatory,butI'dbehappytoansweranyquestionsonparticularattributes.
We'lllearnmoreaboutabstractingsomeofthehardcodedvaluesoutlaterintodimensionsandstyles.
ForthebackgroundcolorI'musingabuiltinAndroidresource:
android:background="@android:color/white"
ForthetextcolorIdefinedanewcolorinres/values/colors.xml:
#ff313131
Wegoingtorefactorabitheretomakeiteasiertotestnewitems.First,makeafield,fragment,forthefragmentundertest.Then,movethefragmentinitializationandfragmentstartingtothesetUp()function.
publicclassDisplayFragmentTest{privateDisplayFragmentfragment;
@BeforepublicvoidsetUp()throwsException{
Lab:DisplayView
Addtheview
Addcolors.xml
AddtesttoDisplayFragmentTest.java
fragment=newDisplayFragment();startFragment(fragment);}
@TestpublicvoidshouldNotBeNull()throwsException{assertNotNull(fragment);}}
Nowwe'rereadytoaddthenewtest:
@TestpublicvoidshouldHaveDefaultDisplay()throwsException{EditTextdisplay=(EditText)fragment.getView().findViewById(R.id.display);assertViewIsVisible(display);assertThat(display.getText().toString(),equalTo(""));}
Inthislabwe'lladdthebuttonstotheviewcompletewithtests.
Note:Theywon'tbeprettyandtheywon'tdoanything!
AsIbuildeachkey,Iwriteatest.ThenIaddthenextkey.Itypicallydon'tstartlayingouttheviewsormakingthemprettyuntiltheyareallpresentintheviewandthetestsarepassing.Icommitaftertheviewsarepresent.ThenIdoastylingcommitafterward(we'lldothatasaseparatestep).
Lastwesawthisfile,wehadalltheinitializationcodeinthethetestthatwewrote.Let'smakeafieldforthefragmentandmovetheinitializationtothesetUp()function:
privateButtonFragmentbuttonFragment;
@BeforepublicvoidsetUp()throwsException{buttonFragment=newButtonFragment();startFragment(buttonFragment);}
Nowwecanaddanewtest.
WeusegetView()togetareferencetotheviewandthenfindthespecificid.
@TestpublicvoidshouldHaveOneKey()throwsException{assertViewIsVisible(buttonFragment.getView().findViewById(R.id.key1));}
Nowweaddthebuttontotheview.
It'sbestpracticetomoveyourstringstothestrings.xmlfileinsteadofleavingthemhardcodedintheview.Italsomakesiteasiertotestthatthecorrectstringisconfiguredforaview.
1
Lab:AddButtons
Testing
Addatest
Addabutton
Addastring
Thelinttoolwillrecommendthisforyoubyshowingyellowbarsandalightbulbintheview.
Let'sextendourtesttoensurethatthecorrectstringisconfiguredfortheview.We'lluseourResourceLocatorclasstogettheresourcestringandcompareittoTextView'sgetText()returntoensuretheyareequal.
Ourfinaltestlookslikethis:
@TestpublicvoidshouldHaveOneKey()throwsException{TextViewkey1=(TextView)buttonFragment.getView().findViewById(R.id.key1);assertViewIsVisible(key1);assertThat(key1.getText().toString(),equalTo(ResourceLocator.getString(R.string.key1)));}
Addeachnumberandoperatorkeyinturnandmakesurethetestspassalongtheway.Afteryou'redonewiththebuttons,commit.
Let'sreplaceourparentLinearLayoutwithaRelativeLayoutsothatwecandefinethepositionofthebuttonsrelativetotheotherbuttons.
Pleaserefertothescreenshotoftheexampleprojecttodeterminewhereeachbuttonshouldbepositioned.
android:id="@+id/key4"android:layout_width="60dp"android:layout_height="60dp"android:layout_margin="5dp"android:layout_below="@id/key1"android:text="@string/key4"/>...
Note:Therearemanywaysthisviewcouldbelaidout.RelativeLayoutisn'tthemostintuitivechoice,butitisquiteusefulandmasteryofitearlyinyourAndroidcareerwillleadtogreatthings.
AccordingtoMeieratKindlelocations2459-2461,youdefineyourownapplicationimplementationwhenyouneedto:
RespondtoapplicationleveleventsbroadcastbytheAndroidruntimesuchaslowmemoryconditions.Transferobjectsbetweenapplicationcomponents.Manageandmaintainresourcesusedbyseveralapplicationcomponents.
Youdeclareyourapplicationinthemanifestandtheapplicationclasswillbeautomaticallyinstantiatedwhentheapplicationisrun.
It'sbestpracticetodeclareyourapplicationasasingleton.
Application
Declaration
Let'saddthefollowingattributetoourtagofourAndroidManifest.xml.
CreateafilecalledCalculatorApplication.javainthepackagestructure.YoucanusetheIDEtocreateitforyouordoitmanually.
It'sbestpracticetosetitupasasingleton.
publicclassCalculatorApplicationextendsApplication{privatestaticCalculatorApplicationinstance=newCalculatorApplication();
publicstaticCalculatorApplicationgetInstance(){returninstance;}}
CreateafilecalledCalculatorApplicationTest.javainyourtestpackagestructure.YoucanusetheIDEtocreateitforyouordoitmanually.
Let'saddthebasicnon-nulltest:
publicclassCalculatorApplicationTest{@TestpublicvoidshouldNotBeNull()throwsException{assertNotNull(CalculatorApplication.getInstance());}}
That'sit!Nowwecanaddmoreitemstothisclassasweneedthem.
Let'scommitourchanges.
Lab:AddApplication
Addtothemanifest
Createclass
WriteTest
Eventbusesareagreatwaytodecoupleourcomponentswithoutusingainterfaceorlistenerpatternthatcanproducealotofboilerplatecode.
Ottoisasystem-widenotificationsystem.Acomponent(e.g.anActivityorFragment)postsanevent,withanoptionalmessage,toOtto.Othercomponentsthathaveregisteredforeventswillreceivetheeventandreactasappropriate.
Let'saddanOttoBus!
Ifnotalreadypresent,addthemavendependencytoyourpom.xmlfilesothatwecanreferenceOttothroughoutourproject.
com.squareupotto1.3.4
NowaddtheselinestoourCalculatorApplication.javaclass.
privateBusbus;
publicBusgetBus(){returnbus;}
publicstaticvoidpostToBus(BaseEventevent){//Note:AutoGeneratingBaseEventnextgetInstance().getBus().post(event);}
@OverridepublicvoidonCreate(){super.onCreate();instance.bus=newBus();}
ThefunctionpostToBus()givesusaconvenientwayposttothebusfromanyactivityorfragmentinourapplication.IfwebuildallofoureventstoextendtheBaseEventthenwecanusethisforalleventsintheapplication.
CreateafilecalledBaseEvent.java.Isuggestcreatingapackagecalledeventstoholdeventsandcreatefurtherpackagesasneededtokeepyourcodeorganized.
Theeventcanbequitesimple,oryoucanincludedatawithyourevents.Inthiscase,wewillmakeitasbasicaspossible:
publicclassBaseEvent{}
Lab:EventBus
IntegrateOtto
Applicationbus
CreateBaseEvent
Let'smakesurethattheBusexistsforourapplication.Firstwe'llneedtomigrateourapplicationtoafieldandinitializeinsetUp().Thenwecanaddthistest:
@TestpublicvoidshouldHaveBus()throwsException{assertNotNull(application.getBus());}
Onceallthetestspass,committoyourrepository.
Addatest&commit
Meierputsitwell,"usinglayoutresourcesdecouplesyourpresentationlayerfromtheapplicationlogic,providingtheflexibilitytochangethepresentationwithoutchangingcode.Thismakesitpossibletospecifydifferentlayoutsoptimizedfordifferenthardwareconfigurations,evenchangingthematruntimebasedonhardwarechanges(suchasscreenorientationchanges)."
I'veseenatoomanyduplicatedlayouts,hardcodedvalues,andhardcodedJavaviewsclutteringAndroidapplications!Allofthesepracticesleadtodifficulttomaintainappsandmakesithardertoscaletonewerdevicesandformfactors.However,ifyouleverageAndroidsystemfromthestartandletitdotheheavingliftingforyou,youcanavoidalotofpaindowntheroad.
AlthoughIfindXMLapaintoreadandwrite,I'vegrowntolovetheresourcesystem.Itisoneofthemostpowerfultoolsyouhavewhenconstructingyourapplication,butisoftenmisunderstoodanddefinitelyunderratedandunderutilized.
Youplaceyourlayouts,drawables,andvalues(e.g.strings,colors,dimensions)inthisfolder.
Thebasicfolderstructurelookslikethis:
res/drawable/values/layout/
Oneannoyingthingaboutthesefoldersisthatyoucan'tcreatesubfolders.Thisisespeciallyannoyinginthelayoutfoldersinceyouendupwithlotsofviewsinyoursystem.Youcanhowever,makeupyourownfilenamesandgroupresourcesthatbelongtogether.
There'slotsofgreatinformationonAndroid'ssiteabouthowtosuportmutipleformfactors:http://developer.android.com/guide/practices/screens_support.html
Meier,Reto(2012).ProfessionalAndroid4ApplicationDevelopment(Loc.2816-2818).JohnWileyandSons.KindleEdition.
Chapter5:ResourceSystem
res/
Resources
InAndroid,youcreatestyles(whichisanalogoustoCSS),externalizeyourresources,andusewhatAndroidcallsresourcequalifierstoadaptyourdesigntodifferentformfactors.
Ifyouhaveawebprogrammingbackground,thiswillfeelfamiliar.Ifnot,theideaisthatyourviewautomaticallyscalestosuittheamountofspaceithasandyoudefinehowthatviewshouldadapttonewsizes.
Don'tbaseyoudesignsonspecificdevicesordevicecategories,ratherthinkaboutthenaturalseparationorbreakinglinesforyourviews.Thereisno"phone"or"tablet",theyarejustdevicesinacontinuum.
Responsivedesign,asopposedtopixel-perfectdesigns,fromthestartwillmakeitaloteasiertoscaleyourviews.
Androiddynamicallyselectsresourcesatruntimethatarebestsuitedtothedevicerunningtheapplication.Youcansetupalternativesforthingslikeorientations,hardware,languages,locations,viewsizes,andmore.ItfreesyoufromtheburdenoffiguringoutincodewhatresourceyoushouldbeshowingifyouuseAndroid'ssystemtodoitforyou.
Externalizingresources,suchasimages,strings,dimensions,styles,themes,andlayoutmakesitmucheasiertomaintainandscaleyourviews.
ThisistheheartoftheAndroid-therearenoguaranteesofwhatyourappwillrunon,soyouneedtocreatethemostflexibleappandviewspossibletoavoidheadachesfromhardcodedvalues.
TheActivityclassprovideshelpermethodstogettheseresourcessuchasgetString(R.string.name)andgetDrawable(R.drawable.name).There'salsoamethodgetResources().SomeoftheseareavailableintheFragmentclassandyoucanalwaysaskfortheactivity'sresourcesbycallinggetActivity().getResources().
Userelativepositioningwhenlayingoutyourviewssothattheyadaptwellwhenrunningondifferentscreensizes.RelativeLayoutandLinearLayoutaregreatchoices.
Usewrap_contentandmatch_parentwheneverpossiblewhendefiningthelayout_heightandlayout_widthofyourviews.wrap_contenttellsthesystemtomeasuretheviewatinflationandrenderthewidgetwithjustenoughspacetocontainit.Ontheotherhand,match_parentsaystakeupalltheavailablewidthandheightwhenrenderingthisview.
DesignPrinciples
Thinklikeawebprogrammer
LetAndroiddotheheavylifting
ExternalizeResources
ScalableLayouts
Stylesandthemesarespecifiedinres/styles.xml.Themesareusedfortheoverallappearanceoftheapplication,whilestylesareappliedtospecificviews.
Inmostcases,youwon'tneedmorethanonestylefile.Ifyouuseabstracteddimensionsandimageassetsinyourstyles(asopposedtohard-codedvalues)combinedwiththequalifiersystem(allofwhichwillbecoveredindepthinthischapter),itmakesyourviewsscalable.
Youcaninheritfromotherstylesandthemes.Youcanoverrideattributesandaddnewonesinderivedstylesorwhenspecifyingviewattributesinthelayoutfile.
Stylesallowyoutoabstractoutviewattributesintoacentralizedlocationtoenablereuse.
Inthisexample,I'vedefinedastylecalledSquareButtonthatconfiguresaheightandwidth.
50dp50dp
Note:Thesyntaxisabitdifferentfromhowyouspecifyviewattributesinyourlayouts,buttheybothusethesameXMLattributes.
Afteryoudefineastyle,youcanreferenceitintheXMLlayoutbyusingthestyleattribute:
Note:styledoesn'tusetheandroidnamespace.
ThemesprovideaconvenientwaytoapplystyletoanentireapplicationorjustanActivity.
Thisisusefulbecauseyoucanrapidlyreskinyourapplicationbychangingjustafewlinesofcode.
Touseathemeinyourapplication,youspecifyitintheAndroidManifest.xml.YoucaneitheruseAndroid'sbuiltinthemes(examplebelow)orcreateyourown.
Styles&Themes
Styles
Definingstyles
Usingstyles
Themes
Ifyouwanttocustomizeatheme,youcanextendanexistingAndroidthemeandaddingattributesoroverrideattributesasdesired.
AndroidManifest.xml
styles.xml
Athemeisjustastyle.Whatmakesitdifferentiswhereyouapplyit!
...
MyapproachtodimensionsandstyleshasevolvedovertimeasIgetexposedtonewteamsandnewdesigners.I'llshowyouwhatittookmeawhiletodiscoverformyselfinhopesofsavingyousomeheadachesdowntheroad.
WhenIstartedwithAndroid,theteamandIgleefullythrewhard-codedvaluesallovertheplace,oftenduplicatingvaluesinthesamefile!Notonlydidthislitterthecode,butitmadedebuggingviewissuesmoredifficult.
ThroughoutthischapterI'llshowyouascalablewaytomanagetheseresources.
It'sstraightforwardtocreateadimension.You'llneedadimens.xmlfileinres/values/:
25dp
Youcanreferencetheminstyles:
@dimen/my_dimen
OrinlineinyourXML:
OreveninJava:
floatdimen=getResources().getDimension(R.dimen.my_dimen);
Itmightnotbeimmediatelyapparent,butusingdimensionswithresourcequalifiers(coveredindepthlater)allowyoutocreateresponsivecomponents.You'llseethisinactioninthe"FlexibleDimensions"lab.
Abstractingcolorsgivesyouaconvenientplacetostoreandnameyourcolorsinsteadofusinghardcodedhexvaluesallovertheplace.Havingnamesassociatedwiththecolorsmakesiteasiertomaintainviewchanges.
Plusyouhaveanaddedbonusofpreviewsofyourcolorswatchesandacolorpicker(includingdropper!)whenyouareopencolors.xmlinIntelliJ.
Dimensions&Colors
Dimensions
Benefit
Colors
Youcanabstractmanytypesofvalues.Checkoutthisarticleformoreinformation:http://developer.android.com/guide/topics/resources/available-resources.html
Let'smakeourcalculatorlooknice!Bytheendofthislabwewillcreateandapplystylestoallofourbuttons.We'llalsocreateastyleforthedisplay.
ColorScheme
Numberbutton:#876D13(Brown)Operatorbutton:#668113(Green)Equalsbutton:#268474(Blue)Clearbutton:#B0281A(Red)
First,createafilecalledstyles.xmlinres/values/.Thisiswhereallofourstylesandthemesliveintheapplication.
Ifyouanalyzethedesign,you'llnoticethatthebuttonsarebasicallyvariationsonatheme.Theonlyvariantsinthestylearedifferentcolorsandsomebuttonsarewiderthanothers.Sincethesebuttonsaresosimilar,itmakessensetocreateabasicstylethateachbuttontypewillinherit.
Let'saddthisbasebuttonstyletostyles.xml.
@dimen/button_dimensions@dimen/button_dimensions@dimen/button_margin@dimen/key_text_size@android:color/white
Herewe'vespecifiedtheheightandwidthsoftheview,themarginbetweenthebuttons,thecolorofthetext,andthesizeofthefont.Allbutthelastuseabstracteddimen's.We'lladdtheseinthenextsection.Forthefinalitem(textcolor),weuseanAndroidsuppliedcolorinsteadofcreatingourown.
Nowit'stimetostartusingdimensions!
Lab:ViewStyles
Createstyles
Basebutton
Createdimensions
Startbycreatingthedimens.xmlfileinres/values/.Thenaddthebaselinevaluesfortheview.We'lladddifferentversionsofthisfileinalaterlabtoscaletodifferentscreensizes.
5dp60dp30sp
NowthatwehaveBaseButtonandallthedimensionsneededtomakeitareality,let'suseittocreateourNumberstyle.
Youcaninheritattributesfromparentstylesandaddyourownconfigurationsforthenewlyderivedstyle.
@color/brown
Fornowwe'llsetthebackgroundtoaflatcolor.Inalaterlabwe'llextendthisstyletoprovidevisualfeedbackuponuserinteraction.
Note:Youcanalsoinheritfrommultiplestyles:http://developer.android.com/guide/topics/ui/themes.html#Inheritance
Let'saddcolorstocolors.xmlforthenewbuttons.TheNumbercolorbrownisshownbelow:
#876D13
AnotherbenefitofcreatingstylesisthatitwillcleanupourXMLfiles.Removeanyattributethatiscoveredbythestyle.Here'stheupdated1key:
Muchcleaner!ImoveasmuchaspossibletostylestokeepmyXMLfileslean.IgenerallyleaveattributesthesourceXMLfilethatrelatetopositioningintheview(e.g.RelativeLayoutpositioning),textforabuttonortextview,andtheid.
Usingtheinformationabove,createandusestylesforeachofthesekeytypes.Whenyoufinish,theviewshouldlooklikethescreenshot.
Numberstyle
Createcolors
Removeextraattributes
Operators,Equals,andZero
Display
Finally,cleanupthedisplayviewindisplay.xmlusingastyle.
Tosetupalternativelayoutsandresourcestoberesolvedatruntime,youuseresourcequalifiers.
Qualifierscoverthingslikescreensize(widthandheight),languagesandregions,aspectration,orientation,andOSversionamongothers.
Checkoutthecompletelistingofqualifieroptionsaswellasdetaileddocumentationonhowresourcesareselected:http://developer.android.com/guide/topics/resources/providing-resources.html
Inthisexampleres/folder,wehaveanumberofdirectories.QualifiedfolderscanberecognizedbythedashintheirnameandtellsAndroidtousespecificresourcesforspecificinstances.
res/drawable/values-sw600dp/values-fr/layout/layout-land/
-frstandsforFrench,-sw600dpmeanssmallestwidthofthedeviceis600dpandhigher,and-landiswherethelandscapelayoutslive.Youcouldcombineseveralqualifiersintoonefolderbyusingadashbetweeneachqualifier.
There'sabitofAndroidmagicthatselectsthebestversionofyourvieworresourceforthecurrentdevice.Ifyousetuptheparallelfolderstructuretosupportdifferentconfigurations,Androidwillhandletherest.Androidchoosesthebestresourcesatruntimebasedonthedevicethatishostingtheapplication.
Androidtriestomatchwiththemostspecificresourcequalifiersfirstandthenfallsbacktomoregenericoptions.Ifnoneoftheresourcequalifiersinyourapplicationmatchthehostdevice,thebasicvaluesspecifiedinlayout/,values/,anddrawable/willbeused.
Makesuretohaveasanedefault!Ifyoudefinesomethinginaspecificqualifiedfolder,suchasanid,andthenruntheapponadevicewithdifferentspecifications,itwillcrashbecauseitwon'tbeabletofindthedefaultvalueatruntime.
Youmightnotcatchthisduringdevelopmentsinceyouarelikelyusingthesamedevice.It'sgoodpracticetovaryyourtestdevicesandtestingsituationstoexploreunhappypaths.
Inthecaseoflayouts,ifyouwanttooverridetheviewforaspecificconfiguration,youwillneedtocreateanotherversionoftheviewinaqualifiedfolder,butyouusethesamenameforbothfiles.That'showtheresourcequalificationsystemworks!
Inthecaseofstrings,dimens,drawables,andotherresources,makesuretousethesamenameinthedefaultandqualifiedpathstooverridethevalueforyournewconfiguration.
Invalues/strings.xmlIhavestringsforawelcomescreen.
Qualifiers
Folderstructure
Resolution
Naming
Example:Internationalization
HelloDutchMobileConference!ProgrammedbyCoreyLeighLatislaw
Invalues-nl/strings.xmlIdefinedthesamename,butputthefileinthequalifiedstructureandchangedthetext.
HalloDutchMobileConference!GeprogrammeerdedoorCoreyLeighLatislaw
Inthislab,we'llusethequalifiersystemanddimensionstoscaleourviewfordifferentformfactors.
Ifyoudon'thaveaccesstoaNexus5,pleasecreateaninstanceusingGenymotion.
TheActionBarinthiscasedoesn'thelpourapplicationsincewe'llonlybeshowingonescreenanddon'thaveanyconfigurationornavigationoptions.It'sjusttakingupvaluablescreenrealestate!
OnnewerOSesyougetitbydefaultunlessyouexplicitlyexcludeitinthemanifestfile:
Let'screateafoldercalledvalues-w350dpandadimens.xmlinthatfolder.Hereiswhereyou'dputyourvaluesyou'dliketouseonscreenswithatleast350dpinscreenwidth.
78dp4dp50sp
164dp
250dp
8dp40sp
Youdon'thavetocopyallthedimensionsoverfromvalues/dimens.xml-justtheonesthatyouareinterestedinoverwriting.
Iadjustedmydisplaymarginsafteradjustingallmybuttonstomaketheedgeslineupbetter.
Lab:FlexibleDimensions
RemoveActionBar
Alternatedimens.xml
Adjustdisplay&commit
Let'saddJapanesenumbers!
Createafoldervalues-jaandastringsfileunderthisdirectory.
Copythecharactersfromhereintoyourstrings.xmlfolderforkeys0-9:http://en.wikipedia.org/wiki/Japanese_numerals
Robolectricallowsyouconfigurethequalifiersforaspecifictest:
@Test@Config(qualifiers="ja")publicvoidshouldHaveJa0Key(){verifyKey(R.id.key0,R.string.key0,"");}
Ihaveahelperfunctiontoreducetheduplicatedcodeforeachkey.Youcouldrefactorthisevenfurtherintoanarraythatyouloopthroughtoverifyeachbutton.
Buttonkey=(Button)buttonFragment.getView().findViewById(id);assertViewIsVisible(key);
StringresourceString=getString(stringId);assertThat(key.getText().toString(),equalTo(resourceString));assertThat(expectedString,equalTo(resourceString));
Buildandchangeyourdevice'slanguagetoJapanesetovisuallyverifytheinternationalizationworked.
Lab:Internationalization
Addtests
Drawablesaretheimagesinyourapplication.Theseimagescanbein.png,.jpg,.gif,orspecifiedinXML.
YousavethefilesindrawableoraqualifiedversionofthedrawablefolderandthenreferenceinXMLwithouttheextension.
Insteadofincludinganimagewithdifferentdensities,youcouldspecifyresourcesinXMLandevenJava.
Forexample,todrawaredrectangle,youcouldcreateitusingXML.
You'dsavethefileinthedrawable/folderandgiveitadescriptivenamelikerectangle.xml.Torefertoitincode,youusethesamemethodofreferencing:
Thisisaspecialfilethatscalestofillaview.Youareabletospecifyhowcertainregionsstretchandwhatregionsshouldstaythesame.
Drawables
ColorDrawable,ShapeDrawable,GradientDawable
9-patch
Youcanfindmoreinformationaboutusingandcreatingthesefileshere:http://developer.android.com/tools/help/draw9patch.html
YoucanalsospecifyhowviewsappearindifferentstatesviaXML.Acommonusageissettingbuttoninteractionstates.Youcandefinewhatitlookslikenormally,whatitlookslikewhenyoupressthebutton,whatitlookslikewhenfocused(e.g.throughakeyboardormouseinteraction).We'llbedoingthisnextinthelab!
StateListDrawables
Startbycreatingthedrawable/folderunderres/.
Createnumber_key.xmlinres/drawable/.
Eachitemherecorrespondstoadifferent
You'refreetochooseyourowncolorsandcustomizethedesign!I'veaddedmycolorsforthedifferentstatestores/colors.xml:
#ffafb315#ff604613
Tomakethisallwork,youneedtoassociateitwiththenumberkeys.EdittheNumberstyletoincludethisnewdrawableasourbackgroundimage.
@drawable/number_key
Nowourbuttonsrespondtotouches!
Lab:ButtonState
Selector
Colors
Applyinstyle
Dothisforeachtypeofbuttonandcommit.
Let'screateaniconforourapplication!
OpenAndroidAssetStudioandchoose"Launchericons".
Createanimageofyourchoiceanddownloadthezipfile.Openingthefileyouwillseethatthere'sseveralimagesinsidequalifiedfolders.Moveeachoftheseimagesintothecorrectfoldersandaddqualifiedfoldersthatdon'tcurrentlyexit.Overridetheexistingiconswhenprompted.
Note:Thetooldoesn'tprovidearesourcefordrawable-ldpi.
Wealreadyhavethisfilenamespecifiedinthemanifest,sowewon'tneedtoupdatethefile.Ingeneral,Ifyouwanttoaddanicon,addittothetag:
Commit!
Lab:AppIcon
Anapplication'slifecyclecanbeinterruptedbymanyevents,suchasauseransweringaphonecall.Itisimperativetounderstandwhathappenswhenausernavigatesawayfromyourphoneandthencomesbacksincethiswilllikelyhappenoften.
It'srarethatauserwillspendsignificanttimeinyourapplicationandprogressthroughthescreensexactlythewayyouenvision.Auseristypicallyquicklyconsumingorsharingcontentandthenmovingontothenextthing.It'slikelythattheuserwillexitandcomebacktoyourapplicationmanytimesaday.Dependingonhowtheyleftyourapplicationandhowyoumanagethelifecycle,itcouldleadtosomesurprisingresultswhentheylaunchyourapplicationthenexttime!
Weoftenoverlookthisfactwhenwearewritingapplicationsbecausewestareatitforalongtimeandworkthroughtheapplicationinaparticularway(asitwasdesigned).Weenduponlythinkingaboutthehappypathandmissmanybugsthatarisefromimproperlifecyclemanagement.Onlybyinteractingwithyourapplicationasanormaluserwouldwillyoustarttoseethesequirks.
Anapplicationhasalifecycle.It'sactivitieshavealifecycle.Theactivitymayhostoneormorefragmentsthatalsohavetheirownlifecycles.
We'llgothelifecyclesofthesecomponentsinfurtherdetailinthischapterandendwithalabtosolidifytheseconcepts.
Chapter6:ManagingtheLifecycle
Calledwhentheapplicationisstarting,beforeanyactivity,service,orreceiverobjects(excludingcontentproviders)havebeencreated.Makeitfast,thisaffectsstartupperformance.
Whentheoverallsystemisrunninglowonmemory,youusethistotrimmemoryusage.Releaseanycachesorotherunnecessaryresourcesyoumaybeholdingonto.Thesystemwillperformagarbagecollectionforyouafterreturningfromthismethod.
Calledwhentheoperatingsystemhasdeterminedthatitisagoodtimeforaprocesstoclearupunneededmemory.Thiscanhappenwhentheapplicationgoesinthebackgroundandthereisnotenoughmemorytokeepasmanybackgroundprocessesrunningasdesired.
Calledbythesystemwhenthedeviceconfigurationchangeswhileyourcomponentisrunning.
Atthetimethatthisfunctionhasbeencalled,yourResourcesobjectwillhavebeenupdatedtoreturnresourcevaluesmatchingthenewconfiguration.
ApplicationLifecycle
onCreate()
onLowMemory()
onTrimMemory()
onConfigurationChanged()
Therearemanystates,butinpracticeyouuseonCreate(),onResume(),onPause(),andonDestroy()mostoften.Theactivitygoesthroughthecreationflowwhenstartingupandthenfollowsasimilar(butreverse)teardownflowwhenmovingtothebackground.
WhenonCreate()iscalled,theactivityisbeingcreated,butnotyetvisibletotheuser.Youcangetreferencestoviewelementsandconfigurelongrunningprocesses.
WhenonStart()iscalled,theactivityisbeingcreatedandmaybevisibletotheuser,buttheuserwon'tbeabletointeract.
WhenonResume()iscalled,theactivityisvisibletotheuserandreadyforuserinput.
WhenonPause()iscalled,theactivityisstillpartiallyvisible.TheusermayhavebeenshownadialogorotheritemthatbrieflytakesthefocusawayfromtheactiveActivity.It'spossiblethattheymayresumetheactivityshortly,butyoushouldstartpreparingfortheteardown.
WhenonStop()iscalled,theactivityishiddenandmaybecleanedupifresourcesareneededforthenew(andcurrentlydisplayed)activitythatauserisinteractingwith.
ActivityLifecycle
ActiveStates
Created
Started
Resumed
Inactive
Stopped
Destroyed
onDestroy()iscalledrightbeforeyouractivityisdestroyed.
Thiscanhappeneitherbecausetheactivityisfinishing(someonecalledfinish()onit,orbecausethesystemistemporarilydestroyingthisinstanceoftheactivitytosavespace.YoucandistinguishbetweenthesetwoscenarioswiththeisFinishing()method.
AFragment'slifecycleistiedtoitshostingactivity,buthasindependentmethodsaswell.
ManyoftheselifecyclemethodsaresimilartotheActivity'smethodsandareintertwinedwiththeActivity'sstate.
Ifyou'dlikemoreindepthinformationaboutthefragmentlifceycle,checkoutAndroid'sdocumentation:FragmentLifecycleandCoordinatingwiththeactivity.
Fragment
Thisiswhereyouconfigureviewcomponents.
Afterthisphase,youhaveaccesstotheActivity.
onCreateView()
onActivityCreated()
Let'saddloggingtothelifecyclemethodstoseewhat'shappeningbehindthescenesinCalculatorActivity,CalculatorApplication,ButtonFragment,andDisplayFragment.
Sothatwecaneasilyidentifyourlogmessages,addaconstantfieldtoeachclass:
privatestaticfinalStringTAG="Lifecycle"+[ClassName].class.getSimpleName();
Makesuretoreplace[ClassName]withthenameoftheclass(e.g.CalculatorApplication).
UseOtooverridethelifecyclefunctions.
Addalogcallineachmethod.Forexample,youronCreate()shouldlooklikethis:
@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);Log.d(TAG,"onCreate()");...}
YoucanfiltertheIntelliJlogstoshowonlyaspecifictag(thefirststringprovidedtoLog.d()):
Lab:VisualizingtheLifecycle
Tagging
Instrumenting
Run
Youcannavigateforwardsandbackwardsinanapplication.
Thebackstackkeepstrackofallnewactivitiesandfragmentsthatwereeitherimplicitlyorexplictlyadded.
WhenyouusestartActivity()withanintent,itisautomaticallyaddedtothebackstackforyou.Withfragments,youcanexplicitlyaddthefragmenttothebackstackwhencommittingaFragmentTransaction.
YoucaninterceptbackclicksinanActivity,thoughbecarefulbecauseyoushouldn'tviolateauser'sexpectations.
@OverridepublicvoidonBackPressed(){...}
Backstack
Backbutton
WhenFragment'sareaddedtotheviewinanXMLfile,theyarestaticandalwaysvisibletotheuser.Youcan'tmanagethestatedirectly,itistiedtothestateoftheactivity.
WhenyoucreateFragment'sincode,youcandynamicallymanagethemwiththeFragmentManager.Youmanuallyshow,hide,andreplacefragments.
TypicallyyoudeclareanXMLplaceholdertohouseyourfragment.ApopularchoiceisFrameLayoutwithanid.IfyouplantouseaFragmentwithoutaview(discussedlaterinthischapter),youdon'tneedaplaceholderlocation.
FragmenttransactionsoperateonFragments.YoucanbeginonebygettingareferencetotheFragmentManagerandthechangeswilltakeeffectwhenyouusecommit().
Usingadd(),yousupplytheidofyourfragmentholderandareferencetothefragmentyou'dlikecreated.
getSupportFragmentManager().beginTransaction().add(R.id.holder,newMyFrag()).commit();
Insteadofusingfragmentstoencapsulateviewfragments,youcancouldusethemtohandlebackgroundprocessing.
Todothis,youreturnnullfromonCreate()andaddthefragmentmanually(notinXML)inthehostingactivityusingtheFragmentManager.It'sessentialtouseastringtagtoidentifythefragmentsinceyoudon'thaveanidassociatedwithit.
Note:YounormallyusethiswithsetRetainInstance(true)toensurethattheFragmentisnotdestroyedonconfigurationchanges.
Backgroundfragmentsdon'tprovideaviewandarenotattachedaaholderinyourlayout.Whenaddingabackgroundfragmenttothebackstack,youmustgiveita"tag"soyoucanrefertoitagain.Otherwiseyouhavenowaytoretrievethefragmentoncethetransactioniscomplete.
getFragmentManager().beginTransaction().add(newMyFrag(),"tag").commit();
Youcanaddfragmentstothebackstack.Todoso,justaddacalltoaddToBackStack(true)beforethecommit()inyourtransaction.
FragmentManager
FragmentTransaction
Addingfragment
Backgroundfragments
Backstack
CreateCalculatorStateFragment.java.Thisfragmentwillbeabackgroundframentthatwillmanagethestateofourcalculator.Noticethatwearereturninganullviewwhencreatingtheview.
publicclassCalculatorStateFragmentextendsFragment{@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){returnnull;}}
Addthenormalfirsttesttoourfragmentfile:
@RunWith(RobolectricTestRunner.class)
publicclassCalculatorStateFragmentTest{@TestpublicvoidshouldNotBeNull()throwsException{assertNotNull(newCalculatorStateFragment());}}
NowaddatesttoCalculatorActivitytoensurethatthefragmentispresent.Itshouldfail!
@TestpublicvoidshouldHaveCalculatorStateFragment()throwsException{assertNotNull(activity.getFragmentManager().findFragmentByTag("calculatorstate"));}
We'reusingfindFragmentByTag()sincethisisabackgroundfragment.Whenweaddthefragmenttotheactivity,we'lluseatagsothatwecanreferencethefragment.
Nowwehaveareasontowritecodeintheactivity.FirsttimethisisstartingtofeellikerealTDD!
AddanewinstanceofthefragmenttoourActivity'sFragmentManagerviaaFragmentTransactioninonCreate().
getFragmentManager().beginTransaction().add(newCalculatorStateFragment(),
Lab:AddCalculatorStateFragment
Createfragment
Testfragment
Testactivity
AddCalculatorStateFragmenttoCalculatorActivity
CALCULATOR_STATE_FRAGMENT_TAG).commit();
Auto-generateaTAGforthecalculatorstatefragmentusingtheIDE.
Nowretest-everythingshouldpass.
Yay,timeforacommit!
Commit
Whenyouwanttosavethestateofviewcomponentsorotherthingsthatarenotstoredinmorepermanentstorage,youwouldusethesaveandrestoreinstancestate.
Let'ssayyou'rebuildinganapplicationthatsearchesforyourfavoritecity'scuisineandyouhaveanEditTextthatallowsthemtoenterasearchterm.Ifyourotatethedevice,theactivityisdestroyedandrecreatedtherebyusingthetermthattheyhave