android 101 for ios developers - android - objc
DESCRIPTION
Android Introduction for iOS DevelopersTRANSCRIPT
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 1/10
GetourbookaboutFunctionalProgramminginSwift
AboutContributorsSubscribeSnippets
AperiodicalaboutbestpracticesandadvancedtechniquesforiOSandOSXdevelopment.
Android101foriOSDevelopers
Issue#11Android,April2014
ByStephenBarnes
Asthemobilesoftwareindustryevolves,itisbecomingincreasinglyimpracticaltotargetonlyiOSforamobileproduct.Androidmarketshareisapproaching80percentforsmartphones,1andthenumberofpotentialusersthatitcanbringtoaproductcanhardlybeignored.
Inthisarticle,IwillintroducethecoreconceptsofAndroiddevelopmentwithinthecontextofiOSdevelopment.AndroidandiOSworkonsimilarproblemsets,buttheyapproachmanyoftheseproblemsindifferentways.Throughoutthearticle,Iwillbeusingacompanionproject(availableonGitHub)toillustratehowtoaccomplishthesametaskswhendevelopingforbothplatforms.
InadditiontoaworkingknowledgeofiOSdevelopment,IassumethatyouhaveaworkingknowledgeofJavaandareabletoinstallandusetheAndroidDevelopmentTools.Furthermore,ifyouarenewtoAndroiddevelopment,readingthroughthetutorialbyGoogleaboutbuildingyourfirstappcouldbeveryhelpful.
ABriefWordonUIDesign
ThisarticlewillnotdelvedeeplyintotheuserexperienceanddesignpatterndifferencesbetweeniOSandAndroid.However,itwouldbebeneficialtounderstandsomeofthekeyUIparadigmsinuseonAndroidtoday:theactionbar,theoverflowmenu,thebackbutton,theshareaction,andmore.IfyouareseriouslyconsideringAndroiddevelopment,IhighlyrecommendinglookingintotheNexus5fromtheGooglePlayStore.Makeityourfulltimedeviceforaweekandforceyourselftotrytheoperatingsystemtoitsfullestextent.Adeveloperwhodoesntknowthekeyusepatternsofhisorheroperatingsystemisaliabilitytotheproduct.
LanguageApplicationStructure
Java
TherearemanydifferencesbetweenObjectiveCandJava,andwhileitmaybetemptingtobringsomeofObjectiveCsstylingintoJava,itcanleadtoacodebasethatheavilyclasheswiththeprimaryframeworkthatdrivesit.Inbrief,hereareafewgotchastowatchfor:
LeaveclassprefixesathomeonObjectiveC.Javahasactualnamespacingandpackagemanagement,sothereisnoneedforclassprefixeshere.Instancevariablesareprefixedwithm,not_.
TakeadvantageofJavaDoctowritemethodandclassdescriptionsforasmuchofyourcodeaspossible.Itwillmakeyourlifeandthelivesofothersbetter.Nullcheck!ObjectiveCgracefullyhandlesmessagesendingtonilobjects,butJavadoesnot.Saygoodbyetoproperties.Ifyouwantsettersandgetters,youhavetoremembertoactuallycreateagetVariableName()methodandcallitexplicitly.Referencingthis.objectwillnotcallyourcustomgetter.Youmustusethis.getObject.Similarly,prefixmethodnameswithgetandsettoindicategettersandsetters.Javamethodsaretypicallywrittenasactionsorqueries,suchasgetCell(),insteadofcellForRowAtIndexPath:.
ProjectStructure
Androidapplicationsareprimarilybrokenintotwosections,thefirstofwhichistheJavasourcecode.ThesourcecodeisstructuredviatheJavapackagehierarchy,anditcanbestructuredasyouplease.However,acommonpracticeistousetoplevelcategoriesforactivities,fragments,views,adapters,anddata(modelsandmanagers).
Thesecondmajorsectionistheresfolder,shortforresourcefolder.Theresfolderisacollectionofimages,XMLlayoutfiles,andXMLvaluefilesthatmakeupthebulkofthenoncodeassets.OniOS,imagesareeither@2xornot,butonAndroidthereareanumberofscreendensityfolderstoconsider.2Androidusesfolderstoarrangeimages,strings,andothervaluesforscreendensity.TheresfolderalsocontainsXMLlayoutfilesthatcanbethoughtofasxibfiles.Lastly,thereareotherXMLfilesthatstoreresourcesforstring,integer,andstyleresources.
OnelastcorrelationinprojectstructureistheAndroidManifest.xmlfile.ThisfileistheequivalentoftheProjectInfo.plistfileoniOS,anditstoresinformationforactivities,applicationnames,andsetIntents3(systemlevelevents)thattheapplicationcanhandle.FormoreinformationaboutIntents,keeponreading,orheadovertotheIntentsarticle.
Activities
ActivitiesarethebasicvisualunitofanAndroidapp,justasUIViewControllersarethebasicvisualcomponentoniOS.InsteadofaUINavigationController,theAndroidOSkeepsanactivitystackthatitmanages.Whenanappislaunched,theOSpushestheappsmainactivityontothestack.Notethatyoucanlaunchotherapps'activitiesandhavethemplacedontothestack.Bydefault,thebackbuttononAndroidpopsfromtheOSactivitystack,sowhenauserpressesback,heorshecangothroughmultipleappsthathavebeenlaunched.
ActivitiescanalsoinitializeotheractivitieswithIntentsthatcontainextradata.StartingActivitieswithIntentsissomewhatsimilartocreatinganewUIViewControllerwithacustominitmethod.BecausethemostcommonwaytolaunchnewactivitiesistocreateanIntentwithdata,agreatwaytoexposecustominitializersonAndroidistocreatestaticIntentgettermethods.Activitiescanalsoreturnresultswhenfinished(goodbyemodaldelegates!)byplacingextradataonanIntentwhentheactivityisfinished.
OnelargedifferencebetweenAndroidappsandiOSappsisthatanyactivitycanbeanentrancepointintoyourapplicationifitregisterscorrectlyintheAndroidManifestfile.SettinganIntentfilterintheAndroidManifest.xmlfileforamediaintentonanactivityeffectivelystatestotheOSthatthisactivityisabletobelaunchedasanentrypointwithmediadatainsideoftheIntent.Agoodexamplemightbeaphotoeditingactivitythatopensaphoto,modifiesit,andreturnsthemodifiedimagewhentheactivityfinishes.
Asasidenote,modelobjectsmustimplementtheParcelableinterfaceifyouwanttosendthembetweenactivitiesandfragments.ImplementingtheParcelableinterfaceissimilartoconformingtotheprotocoloniOS.AlsonotethatParcelableobjectsareabletobestoredinanactivitysorfragmentssavedInstanceState,inordertomoreeasilyrestoretheirstatesaftertheyhavebeendestroyed.
Letsnextlookatoneactivitylaunchinganotheractivity,andalsorespondingtowhenthesecondactivityfinishes.
LaunchingAnotherActivityforaResult
//ArequestcodeisauniquevalueforreturningactivitiesprivatestaticfinalintREQUEST_CODE_NEXT_ACTIVITY=1234;
protectedvoidstartNextActivity(){//Intentsneedacontext,sogivethiscurrentactivityasthecontextIntentnextActivityIntent=newIntent(this,NextActivity.class);startActivityForResult(nextActivityResult,REQUEST_CODE_NEXT_ACTIVITY);}
@OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){switch(requestCode){caseREQUEST_CODE_NEXT_ACTIVITY:if(resultCode==RESULT_OK){//ThismeansourActivityreturnedsuccessfully.Fornow,Toastthistext.
//Thisjustcreatesasimplepopupmessageonthescreen.Toast.makeText(this,"ResultOK!",Toast.LENGTH_SHORT).show();
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 2/10
Toast.makeText(this,"ResultOK!",Toast.LENGTH_SHORT).show();}return;}super.onActivityResult(requestCode,resultCode,data);}
ReturningaResultonActivityFinish()
publicstaticfinalStringactivityResultString="activityResultString";
/**Oncompletion,placetheobjectIDintheintentandfinishwithOK.*@paramreturnObjectthatwasprocessed*/privatevoidonActivityResult(ObjectreturnObject){Intentdata=newIntent();if(returnObject!=null){data.putExtra(activityResultString,returnObject.uniqueId);}
setResult(RESULT_OK,data);finish();}
Fragments
TheFragmentconceptisuniquetoAndroidandcamearoundsomewhatrecentlyinAndroid3.0.Fragmentsareminicontrollersthatcanbeinstantiatedtofillactivities.Theystorestateinformationandmaycontainviewlogic,buttheremaybemultiplefragmentsonthescreenatthesametimeputtingtheactivityinafragmentcontrollerrole.Alsonotethatfragmentsdonothavetheirowncontextsandtheyrelyheavilyonactivitiesfortheirconnectiontotheapplicationsstate.
Tabletsareagreatfragmentusecaseexample:youcanplacealistfragmentontheleftandadetailfragmentontheright.4FragmentsallowyoutobreakupyourUIandcontrollerlogicintosmaller,reusablechunks.Butbeware!Thefragmentlifecycle,detailedbelow,ismorenuanced.
FragmentsarethenewwayofstructuringappsonAndroid,justlikeUICollectionViewisthenewwayofstructuringlistdatainsteadofUITableviewforiOS.5Whileitisinitiallyeasiertoavoidusingfragmentsandinsteadusenothingbutactivities,youcouldregretthisdecisionlateron.Thatsaid,resisttheurgetogiveuponactivitiesentirelybyswappingfragmentsonasingleactivitythiscanleaveyouinabindwhenwantingtotakeadvantageofintentsandusingmultiplefragmentsonthesameactivity.
LetslookatasampleUITableViewControllerandasampleListFragmentthatshowalistofpredictiontimesforasubwaytrip,courtesyoftheMBTA.
TableViewControllerImplementation
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 3/10
@interfaceMBTASubwayTripTableTableViewController()
@property(assign,nonatomic)MBTATrip*trip;
@end
@implementationMBTASubwayTripTableTableViewController
(instancetype)initWithTrip:(MBTATrip*)trip{self=[superinitWithStyle:UITableViewStylePlain];if(self){_trip=trip;[selfsetTitle:trip.destination];}returnself;}
(void)viewDidLoad{[superviewDidLoad];
[self.tableViewregisterClass:[MBTAPredictionCellclass]forCellReuseIdentifier:[MBTAPredictionCellreuseId]];[self.tableViewregisterNib:[UINibnibWithNibName:NSStringFromClass([MBTATripHeaderViewclass])bundle:nil]forHeaderFooterViewReuseIdentifier:[MBTATripHeaderViewreuseId]];}
#pragmamarkUITableViewDataSource
(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView{return1;}
(NSInteger)tableView:(UITableView*)tableViewnumberOfRowsInSection:(NSInteger)section{return[self.trip.predictionscount];}
#pragmamarkUITableViewDelegate
(CGFloat)tableView:(UITableView*)tableViewheightForHeaderInSection:(NSInteger)section{return[MBTATripHeaderViewheightWithTrip:self.trip];}
(UIView*)tableView:(UITableView*)tableViewviewForHeaderInSection:(NSInteger)section{MBTATripHeaderView*headerView=[self.tableViewdequeueReusableHeaderFooterViewWithIdentifier:[MBTATripHeaderViewreuseId]];[headerViewsetFromTrip:self.trip];
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 4/10
[headerViewsetFromTrip:self.trip];returnheaderView;}
(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath{UITableViewCell*cell=[tableViewdequeueReusableCellWithIdentifier:[MBTAPredictionCellreuseId]forIndexPath:indexPath];
MBTAPrediction*prediction=[self.trip.predictionsobjectAtIndex:indexPath.row];[(MBTAPredictionCell*)cellsetFromPrediction:prediction];
returncell;}
(BOOL)tableView:(UITableView*)tableViewcanEditRowAtIndexPath:(NSIndexPath*)indexPath{returnNO;}
(void)tableView:(UITableView*)tableViewdidSelectRowAtIndexPath:(NSIndexPath*)indexPath{[tableViewdeselectRowAtIndexPath:indexPathanimated:YES];}
@end
ListFragmentImplementation
publicclassTripDetailFragmentextendsListFragment{
/***TheconfigurationflagsfortheTripDetailFragment.*/publicstaticfinalclassTripDetailFragmentState{publicstaticfinalStringKEY_FRAGMENT_TRIP_DETAIL="KEY_FRAGMENT_TRIP_DETAIL";}
protectedTripmTrip;
/***Usethisfactorymethodtocreateanewinstanceof
*thisfragmentusingtheprovidedparameters.**@paramtripthetriptoshowdetails*@returnAnewinstanceoffragmentTripDetailFragment.*/publicstaticTripDetailFragmentnewInstance(Triptrip){TripDetailFragmentfragment=newTripDetailFragment();
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 5/10
TripDetailFragmentfragment=newTripDetailFragment();Bundleargs=newBundle();args.putParcelable(TripDetailFragmentState.KEY_FRAGMENT_TRIP_DETAIL,trip);fragment.setArguments(args);returnfragment;}
publicTripDetailFragment(){}
@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){Prediction[]predictions=mTrip.predictions.toArray(newPrediction[mTrip.predictions.size()]);PredictionArrayAdapterpredictionArrayAdapter=newPredictionArrayAdapter(getActivity(),predictions);setListAdapter(predictionArrayAdapter);returnsuper.onCreateView(inflater,container,savedInstanceState);}
@OverridepublicvoidonViewCreated(Viewview,BundlesavedInstanceState){super.onViewCreated(view,savedInstanceState);TripDetailsViewheaderView=newTripDetailsView(getActivity());headerView.updateFromTripObject(mTrip);getListView().addHeaderView(headerView);}}
Inthenextsection,letsdeciphersomeoftheuniqueAndroidcomponents.
CommonAndroidComponents
ListViewsandAdapters
ListViewsaretheclosestapproximationtoUITableViewonAndroid,andtheyareoneofthemostcommoncomponentsthatyouwilluse.JustlikeUITableViewhasahelperviewcontroller,UITableViewController,ListViewalsohasahelperactivity,ListActivity,andahelperfragment,ListFragment.SimilartoUITableViewController,thesehelperstakecareofthelayout(similartothexib)foryouandprovideconveniencemethodsformanagingadapters,whichwelldiscussbelow.OurexampleaboveusesaListFragmenttodisplaydatafromalistofPredictionmodelobjects,similartohowthetableviewsdatasourceusesanarrayofPredictionmodelobjectstopopulatetheUITableView.
Speakingofdatasources,onAndroidwedonthavedatasourcesanddelegatesforListView.Instead,wehaveadapters.Adapterscomeinmanyforms,buttheirprimarygoalissimilartoadatasourceandtableviewdelegateallinone.AdapterstakedataandadaptittopopulateaListViewbyinstantiatingviewstheListViewwilldisplay.Letshavealookatthearrayadapterusedabove:
publicclassPredictionArrayAdapterextendsArrayAdapter{
intLAYOUT_RESOURCE_ID=R.layout.view_three_item_list_view;
publicPredictionArrayAdapter(Contextcontext){super(context,R.layout.view_three_item_list_view);}
publicPredictionArrayAdapter(Contextcontext,Prediction[]objects){super(context,R.layout.view_three_item_list_view,objects);}
@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){Predictionprediction=this.getItem(position);ViewinflatedView=convertView;if(convertView==null){LayoutInflaterinflater=(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);inflatedView=inflater.inflate(LAYOUT_RESOURCE_ID,parent,false);}
TextViewstopNameTextView=(TextView)inflatedView.findViewById(R.id.view_three_item_list_view_left_text_view);TextViewmiddleTextView=(TextView)inflatedView.findViewById(R.id.view_three_item_list_view_middle_text_view);TextViewstopSecondsTextView=(TextView)inflatedView.findViewById(R.id.view_three_item_list_view_right_text_view);
stopNameTextView.setText(prediction.stopName);middleTextView.setText("");stopSecondsTextView.setText(prediction.stopSeconds.toString());
returninflatedView;}}
YoullnotethattheadapterhasanimportantmethodnamedgetView,whichisverysimilartocellForRowAtIndexPath:.Anothersimilarityyoullnoticeisapatternforreusingviews,similartoiOS.ReusingviewsarejustasimportantasoniOS,andthissubstantiallyhelpsperformance!Thisadapterisrathersimple,becauseitusesabuiltinsuperclass,ArrayAdapter,foradaptersworkingwitharraydata,butitillustrateshowtopopulateaListViewfromadataset.
AsyncTasks
InplaceofGrandCentralDispatchoniOS,onAndroidwehaveaccesstoAsyncTasks.AsyncTasksisadifferenttakeonexposingasynchronoustoolsinamorefriendlyway.AsyncTasksisabitoutofscopeforthisarticle,butIhighlyrecommendlookingoversomeofthedocumentation.
ActivityLifecycle
OneoftheprimarythingstowatchoutforcomingfromiOSdevelopmentistheAndroidlifecycle.LetsstartbylookingattheActivityLifecycleDocumentation:
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 6/10
Inessence,theactivitylifecycleisverysimilartotheUIViewControllerlifecycle.TheprimarydifferenceisthattheAndroidOScanberuthlesswithdestroyingactivities,anditisveryimportanttomakesurethatthedataandthestateoftheactivityaresaved,sothattheycanberestoredfromthesavedstateiftheyexistintheonCreate().ThebestwaytodothisisbyusingbundleddataandrestoringfromthesavedInstanceStateand/orIntents.Forexample,hereisthepartoftheTripListActivityfromoursampleprojectthatiskeepingtrackofthecurrentlyshownsubwayline:
publicstaticIntentgetTripListActivityIntent(Contextcontext,TripList.LineTypelineType){Intentintent=newIntent(context,TripListActivity.class);intent.putExtra(TripListActivityState.KEY_ACTIVITY_TRIP_LIST_LINE_TYPE,lineType.getLineName());returnintent;}
publicstaticfinalclassTripListActivityState{publicstaticfinalStringKEY_ACTIVITY_TRIP_LIST_LINE_TYPE="KEY_ACTIVITY_TRIP_LIST_LINE_TYPE";}
TripList.LineTypemLineType;
@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);mLineType=TripList.LineType.getLineType(getIntent().getStringExtra(TripListActivityState.KEY_ACTIVITY_TRIP_LIST_LINE_TYPE));}
Anoteonrotation:thelifecyclecompletelyresetstheviewonrotation.Thatis,youractivitywillbedestroyedandrecreatedwhenarotationoccurs.Ifdataisproperlysavedinthesavedinstancestateandtheactivityrestoresthestatecorrectlyafteritscreation,thentherotationwillworkseamlessly.Manyappdevelopershaveissueswithappstabilitywhentheapprotates,becauseanactivitydoesnothandlestatechangesproperly.Beware!Donotlockyourappsrotationtosolvetheseissues,asthisonlyhidesthelifecyclebugsthatwillstilloccuratanotherpointintimewhentheactivityisdestroyedbytheOS.
FragmentLifecycle
TheFragmentLifecycleissimilartotheactivitylifecycle,withafewadditions.
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 7/10
Oneoftheproblemsthatcancatchdevelopersoffguardisregardingissuescommunicatingbetweenfragmentsandactivities.NotethattheonAttach()happensbeforeonActivityCreated().Thismeansthattheactivityisnotguaranteedtoexistbeforethefragmentiscreated.TheonActivityCreated()methodshouldbeusedwhenyousetinterfaces(delegates)totheparentactivity,ifneeded.
Fragmentsarealsocreatedanddestroyedaggressivelybytheneedsoftheoperatingsystem,andtokeeptheirstate,requirethesameamountofdiligenceasactivities.Hereisanexamplefromoursampleproject,wherethetriplistfragmentkeepstrackoftheTripListdata,aswellasthesubwaylinetype:
/***TheconfigurationflagsfortheTripListFragment.*/publicstaticfinalclassTripListFragmentState{publicstaticfinalStringKEY_FRAGMENT_TRIP_LIST_LINE_TYPE="KEY_FRAGMENT_TRIP_LIST_LINE_TYPE";publicstaticfinalStringKEY_FRAGMENT_TRIP_LIST_DATA="KEY_FRAGMENT_TRIP_LIST_DATA";}
/***Usethisfactorymethodtocreateanewinstanceof*thisfragmentusingtheprovidedparameters.**@paramlineTypethesubwaylinetoshowtripsfor.*@returnAnewinstanceoffragmentTripListFragment.*/publicstaticTripListFragmentnewInstance(TripList.LineTypelineType){TripListFragmentfragment=newTripListFragment();Bundleargs=newBundle();args.putString(TripListFragmentState.KEY_FRAGMENT_TRIP_LIST_LINE_TYPE,lineType.getLineName());fragment.setArguments(args);returnfragment;}
protectedTripListmTripList;protectedvoidsetTripList(TripListtripList){Bundlearguments=this.getArguments();arguments.putParcelable(TripListFragmentState.KEY_FRAGMENT_TRIP_LIST_DATA,tripList);mTripList=tripList;if(mTripArrayAdapter!=null){mTripArrayAdapter.clear();mTripArrayAdapter.addAll(mTripList.trips);}}
@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);if(getArguments()!=null){mLineType=TripList.LineType.getLineType(getArguments().getString(TripListFragmentState.KEY_FRAGMENT_TRIP_LIST_LINE_TYPE));mTripList=getArguments().getParcelable(TripListFragmentState.KEY_FRAGMENT_TRIP_LIST_DATA);}}
NoticethatthefragmentalwaysrestoresitsstatefromthebundledargumentsinonCreate,andthatthecustomsetterfortheTripListmodelobjectaddstheobjecttothebundledargumentsaswell.Thisensuresthatifthefragmentisdestroyedandrecreated,suchaswhenthedeviceisrotated,thefragmentalwayshasthelatestdatatorestorefrom.
Layouts
SimilartootherpartsofAndroiddevelopment,thereareprosandconstospecifyinglayoutsinAndroidversusiOS.LayoutsarestoredashumanreadableXMLfilesintheres/layoutsfolder.
SubwayListViewLayout
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 8/10
HereisthesameviewoniOSwithaUITableViewandaUIButtonpinnedtothebottomviaAutoLayoutinInterfaceBuilder:
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 9/10
YoullnoticethattheAndroidlayoutfileismucheasiertoreadandunderstandwhatisgoingon.TherearemanypartstolayingoutviewsinAndroid,butwellcoverjustafewoftheimportantones.
TheprimarystructurethatyouwilldealwithwillbesubclassesofViewGroupRelativeLayout,LinearLayout,andFrameLayoutarethemostcommon.TheseViewGroupscontainotherviewsandexposepropertiestoarrangethemonscreen.
AgoodexampleistheuseofaRelativeLayoutabove.Arelativelayoutallowsustouseandroid:layout_alignParentBottom="true"inourlayoutabovetopinthebuttontothebottom.
Lastly,tolinklayoutstofragmentsoractivities,simplyusethatlayoutsresourceIDduringtheonCreateView:
@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){returninflater.inflate(R.layout.fragment_subway_listview,container,false);}
LayoutTips
Alwaysworkindp(densityindependentpixels)insteadofpixelsdirectly.Dontbothernudgingitemsforlayoutsinthevisualeditoroftenthevisualeditorwillputindividualpointsofspacingonobjectsinsteadofadjustingtheheightandwidthasyoumightlike.YourbestbetistoadjusttheXMLdirectly.Ifyoueverseethefill_parentvalueforalayoutheightorwidth,thisvaluewasdeprecatedyearsagoinAPI8andreplacedwithmatch_parent.
Seethetheresponsiveandroidapplicationsarticleformoretipsonthis.
Data
TheDataStorageOptionsavailableonAndroidarealsoverysimilartowhatisavailableoniOS:
SharedPreferencesNSUserDefaultsInmemoryobjectsSavingtoandfetchingfromfilestructureviatheinternalorexternalfilestoragesavingtothedocumentsdirectorySQLiteCoreData
-
2/27/2015 Android101foriOSDevelopersAndroidobjc.ioissue#11
http://www.objc.io/issue11/android_101_for_ios_developers.html 10/10
TheprimarydifferenceisthelackofCoreData.Instead,AndroidoffersstraightaccesstotheSQLitedatabaseandreturnscursorobjectsforresults.HeadovertothearticleinthisissueaboutusingSQLiteonAndroidformoredetails.
AndroidHomework
Whatwevediscussedsofarbarelyscratchesthesurface.ToreallytakeadvantageofsomeofthethingsthatmakeAndroidspecial,Irecommendcheckingoutsomeofthesefeatures:
ActionBar,OverflowMenu,andtheMenuButtonCrossAppDataSharingRespondtocommonOSactionsTakeadvantageofJavasfeatures:generics,virtualmethodsandclasses,etc.GoogleCompatibilityLibrariesTheAndroidEmulator:installthex86HAXMplugintomaketheemulatorbutterysmooth.
FinalWordsMuchofwhatwasdiscussedinthisarticleisimplementedintheMBTAsubwaytransitsampleprojectonGitHub.Theprojectwasbuiltasawaytoillustratesimilarconceptssuchasapplicationstructure,handlingdata,andbuildingUIonthesameapplicationforbothplatforms.
WhilesomeofthepureimplementationdetailsareverydifferentonAndroid,itisveryeasytobringproblemsolvingskillsandpatternslearnedoniOStobear.Whoknows?MaybeunderstandinghowAndroidworksjustalittlebitbettermightprepareyouforthenextversionofiOS.
1. Source
2. SeeGooglesdocumentationforsupportingmultiplescreensizeshere.
3. Intentsdocumentation
4. SeeGooglesdocumentationformultipanetabletviewformoreinformation.
5. Thanks,NSHipster.
Morearticlesinissue#11
Privacypolicy