Programmering

GraphLib: Et open source Android-bibliotek for grafer

Grafer og dataplott er fantastiske verktøy for å illustrere forhold, skildre datatrender og spore mål i Android-applikasjonene dine. Jeg så dette selv for flere år siden, da en tidligere student av meg vant førsteplassen i en mobilappkonkurranse for studenter sponset av Charleston Defense Contractors Association. Et sentralt trekk ved den vinnende appen, "Diabetes and Me", var muligheten til å tegne grafiske daglige sukkernivåer.

Som et annet eksempel kan du vurdere et vekt-sporingsprogram som planlegger fremgang mot en målvekt. Figur 1 illustrerer hvordan en slik applikasjon kan se ut på en Android-telefon. Figuren bruker en rød linjediagram for å vise gjennomsnittlige månedlige vekter for året 2017. Den viser målvekten som en grønn rett linje nær bunnen. (Selv om dataverdiene vist i linjediagrammet er hypotetiske, er de realistiske for forfatteren av denne artikkelen.)

John I. Moore

I denne artikkelen bruker jeg open source-biblioteket, GraphLib, for å demonstrere det grunnleggende om å tegne matematiske funksjoner i Android. Det er ikke det samme grafbiblioteket som studenten min brukte til applikasjonen sin. Faktisk er det mye enklere og enklere å bruke.

last ned Last ned GraphLib Få kildekoden til open source Android-grafbiblioteket introdusert i denne artikkelen. Skapt av John I. Moore.

Oversikt over GraphLib

GraphLib består av ett grensesnitt og åtte klasser. Tre av disse klassene er interne i biblioteket og har bare pakketilgang, så du trenger ikke å forstå dem for å kunne bruke GraphLib. To av de resterende klassene har veldig enkel funksjonalitet, og resten er ikke vanskelig å hente.

Nedenfor vil jeg beskrive GraphLib-grensesnittet og hver av de åtte klassene. Merk at jeg brukte Java 8-funksjoner som funksjonelle grensesnitt og lambda-uttrykk for å utvikle og teste biblioteket, men det er relativt greit å endre disse funksjonene for tidligere versjoner av Java.

GraphLibs funksjonelle grensesnitt

Som vist i Oppføring 1, grensesnitt Funksjon har bare en abstrakt metode og er derfor et funksjonelt grensesnitt. Merk at dette grensesnittet tilsvarer omtrent Java 8-er DoubleUnaryOperator, funnet i pakken java.util.funksjon. Forskjellen er at Funksjon bruker ikke andre Java 8-funksjoner enn kommentaren @FunctionalInterface. Å fjerne denne merknaden er den eneste endringen som er nødvendig for å gjøre Funksjon grensesnitt kompatibelt med tidligere versjoner av Java.

Oppføring 1. grensesnitt Funksjon

 pakke com.softmoore.android.graphlib; @FunctionalInterface public interface Funksjon {public double apply (double x); } 

Lære om lambdauttrykk

Lambda-uttrykk, også kjent som lukkinger, funksjonsbokstaver eller bare lambdas, beskriver et sett med funksjoner definert i Java Specification Request (JSR) 335. Mindre formelle introduksjoner til lambda-uttrykk er gitt i en del av den siste versjonen av Java Tutorial; i JavaWorld-artikkelen "Java-programmering med lambdauttrykk", og i et par artikler av Brian Goetz, "State of the lambda" og "State of the lambda: Libraries edition."

GraphLib-klasser

Klasser Punkt og Merkelapp er relativt enkle: Punkt innkapsler et par doble verdier som representerer et punkt i x, y-fly, og Merkelapp innkapsler en dobbel verdi og en streng, der dobbeltverdien representerer et punkt på en akse og strengen brukes til å merke det punktet. Eksemplet i figur 1 bruker punkter for å beskrive linjediagrammet og etikettene for aksen nederst, og viser forkortelser med en bokstav for månedene. Jeg vil gi flere eksempler som illustrerer bruken av disse klassene senere i artikkelen.

Klasser Graffunksjon, GraphPoints, og ScreenPoint er ikke bare veldig enkle, de er også interne i biblioteket og har bare pakke tilgang. Du trenger ikke egentlig forstå disse klassene for å bruke biblioteket, så jeg vil beskrive dem bare kort her:

  • Graffunksjon innkapsler en funksjon (dvs. en klasse som implementerer grensesnitt Funksjon) og en farge som brukes til å tegne den funksjonen.
  • GraphPoints innkapsler en liste over punkter sammen med en farge som brukes til å plotte dem. Denne klassen brukes internt til å tegne punkter og tegne linjediagrammer.
  • ScreenPoint innkapsler et par heltallverdier som representerer pikselkoordinater på skjermen til en Android-enhet. Denne klassen ligner på, men enklere enn Android-klassen Punkt i pakke android.graphics.

Jeg har gitt kildekoden for disse klassene i tilfelle du er interessert i detaljene.

De tre gjenværende klassene i GraphLib-biblioteket er Kurve, Graf.Bygger, og GraphView. Det er viktig å forstå hvilken rolle hver av dem spiller i en Android-applikasjon.

Klasse Kurve inneholder informasjon om farger, punkter, etiketter, grafer, etc., som skal tegnes, men er egentlig uavhengig av Android-grafikkdetaljer. Samtidig som Kurve har mange felt, de har alle standardverdier, og derfor er det fornuftig å bruke Builder-mønsteret til å lage forekomster av denne klassen. Klasse Kurve inneholder en nestet statisk underklasse med navnet Bygger, som brukes til å lage Kurve gjenstander.

De to klassene Kurve og Graf.Bygger gå sammen, fra en utviklers perspektiv, og bør forstås, i det vesentlige, som en. I sannhet trenger du bare å forstå hvordan du bruker den nestede klassen Bygger å lage en Kurve gjenstand. Utviklere gjør egentlig ikke noe direkte med en Kurve gjenstand etter at den er opprettet, annet enn å sende den til en GraphView objekt, som gjør jobben med å vise alt på en Android-enhet.

Oppføring 2 oppsummerer metodene som er tilgjengelige i klassen Graf.Bygger. Senere eksempler vil illustrere hvordan du bruker Builder-mønsteret til å lage Kurve gjenstander. For nå er det nok å merke seg at annet enn standardkonstruktøren (første linje i oppføring 2) og bygge() metode (siste linje i liste 2), returnerer alle andre metoder Bygger gjenstand. Dette gjør det mulig å kjede anrop til byggemetoder.

Oppføring 2. Oppsummering av metodene i klassen Graf.Bygger

 public Builder () public Builder addFunction (Function function, int graphColor) public Builder addFunction (Function function) public Builder addPoints (Point [] points, int pointColor) public Builder addPoints (List points, int pointColor) public Builder addPoints (Point [] poeng) public Builder addPoints (List poeng) public Builder addLineGraph (Point [] poeng, int lineGraphColor) public Builder addLineGraph (List poeng, int lineGraphColor) public Builder addLineGraph (Point [] poeng) public Builder addLineGraph (List poeng) public Builder setBackgroundColor (int bgColor) public Builder setAxesColor (int axesColor) public Builder setFunctionColor (int functColor) public Builder setPointColor (int pointColor) public Builder setWorldCoordinates (double xMin, double xMax, double yMin, double yMax) public Builder setAxes ) public Builder setXTicks (double [] xTicks) public Builder setXTicks (List xTicks) public Builder setYTicks (double [] yTicks) public Builder setYTicks (List yT icks) public Builder setXLabels (Label [] xLabels) public Builder setXLabels (List xLabels) public Builder setYLabels (Label [] yLabels) public Builder setYLabels (List yLabels) public Graph build () 

Du vil merke deg i oppføring 2 at mange av metodene er overbelastet for å godta enten matriser av objekter eller lister over objekter. Jeg foretrekker arrays fremfor lister for eksempler i denne artikkelen, rett og slett fordi det er mye lettere å initialisere arrays, men GraphLib støtter begge deler. Imidlertid vil Java 9 inneholde enkle fabrikkmetoder for samlinger, og dermed fjerne denne lille fordelen for matriser. Var Java 9 i utbredt bruk på tidspunktet for denne artikkelen, ville jeg foretrukket lister fremfor matriser i begge GraphLib og de senere eksemplene.

Byggmønsteret

For å lære mer om Builder-mønsteret, se den andre utgaven av Effective Java av Joshua Bloch eller JavaWorld-artikkelen "Too many parameters in Java methods, Part 3: Builder pattern" av Dustin Marx.

Brukergrensesnittklasser i Android kalles utsikt, og klasse Utsikt i pakke android.view er den grunnleggende byggesteinen for brukergrensesnittkomponenter. En visning opptar et rektangulært område på skjermen, og er ansvarlig for tegning og håndtering av hendelser. Fra et arveperspektiv, klasse Utsikt er en forfedre klasse ikke bare av brukergrensesnittkontroller (knapper, tekstfelt osv.), men også av oppsett, som er usynlige visningsgrupper som først og fremst er ansvarlige for å ordne sine underkomponenter.

Klasse GraphView utvider klassen Utsikt og er ansvarlig for å vise informasjonen innkapslet i a Kurve på skjermen til en Android-enhet. Dermed klasse GraphView er der all tegningen foregår.

Bruke GraphLib

Det er to tilnærminger for å lage brukergrensesnitt for Android: en prosessuell tilnærming (innenfor Java-kildekoden) eller en deklarativ tilnærming (i en XML-fil). Enten er gyldig, men konsensus er å bruke den deklarative tilnærmingen så mye som mulig. Jeg har brukt en deklarativ tilnærming for eksemplene mine.

Det er fem grunnleggende trinn for å bruke GraphLib bibliotek. Før du begynner, last ned den kompilerte Java-kildekoden for GraphLib-biblioteket.

last ned Last ned GraphLib.jar Få den kompilerte Java-kildekoden for GraphLib. Skapt av John I. Moore.

Trinn 1. Gjør graphlib.jar tilgjengelig for Android-prosjektet ditt

Opprett et nytt prosjekt ved hjelp av Android Studio og kopier JAR-filen graphlib.jar til libs underkatalog til prosjektets app katalog. Bytt mappestruktur fra i Android Studio Android til Prosjekt. Neste, i libs mappe (nestet i app mappe), høyreklikk på JAR-filen og klikk på Legg til som bibliotek. Denne siste handlingen vil legge til JAR-filen i avhengighetsdelen av appen din build.gradle fil. Se "Slik legger du til en krukke i eksterne biblioteker i Android Studio" hvis du trenger hjelp med dette trinnet.

Trinn 2. Opprett en Android-aktivitet som vil bruke GraphLib

I Android-applikasjoner, en aktivitet representerer en enkelt skjerm med et brukergrensesnitt. Aktiviteter defineres primært i to filer: en XML-fil som deklarerer UI-layout og komponenter, og en Java-fil som definerer kjøretidsfunksjonalitet som hendelsesbehandling. Når et nytt prosjekt opprettes, oppretter Android Studio vanligvis en standardaktivitet som heter Hoved aktivitet. Bruk denne aktiviteten eller lag en ny for applikasjonen din.

Trinn 3. Legg til en GraphView i oppsettet for aktiviteten

I XML-filen for aktivitetens oppsett, vil du erklære a GraphView objekt på omtrent samme måte som du erklærer en knapp eller en tekstvisning, bortsett fra at du må oppgi hele pakkenavnet for GraphView. Listing 3 viser et utdrag fra en layoutfil som erklærer a GraphView etterfulgt av en TextView som en del av et vertikalt lineært oppsett. Etter anbefalt praksis skal de faktiske verdiene for bredden og høyden på GraphView er definert i separate dimen ressursfiler, der forskjellige ressursfiler gir verdier for forskjellige skjermstørrelser / tettheter. (Merk: Jeg brukte 325 for begge verdiene i eksemplene nedenfor.)

Oppføring 3. Deklarere en GraphView og en TextView i en XML-fil

Trinn 4. Importer bibliotekstimene til aktiviteten

Oppføring 4 viser listen over importuttalelser for et program hvis biblioteklassene importeres individuelt. Listen over import kan forkortes til en enkelt linje som importere com.softmoore.android.graphlib. * hvis ønsket. Personlig foretrekker jeg å se den utvidede listen som vist i Listing 4.

Oppføring 4. Importer bibliotekstimene

 importere com.softmoore.android.graphlib.Function; importere com.softmoore.android.graphlib.Graph; importere com.softmoore.android.graphlib.GraphView; importere com.softmoore.android.graphlib.Label; importere com.softmoore.android.graphlib.Point; 

Trinn 5. Opprett et grafobjekt og legg det til i GraphView

Oppføring 5 viser opprettelsen av et enkelt grafobjekt - i dette tilfellet et grafobjekt som bruker alle standardverdiene. Den inneholder i hovedsak bare et sett med x- og y-akser, der verdiene på begge akser varierer fra 0 til 10. Oppføringen setter også en tittel for skjermen og tekst for tekstvisningen under grafen.

Oppføring 5. Opprett et grafobjekt og legg det til i GraphView

 Grafgraf = ny Graph.Builder () .build (); GraphView graphView = findViewById (R.id.graph_view); graphView.setGraph (graf); setTitle ("Tom graf"); TextView textView = findViewById (R.id.graph_view_label); textView.setText ("Graf av akser"); 

Figur 2 viser resultatet av å kjøre dette programmet på en Android-enhet.

John I. Moore

Bruke GraphLib i Android-applikasjoner

For resten av artikkelen vil jeg fokusere på den virkelige bruken av GraphLib-biblioteket i Android-applikasjonsutvikling. Jeg presenterer syv eksempler med korte beskrivelser og kildekodeutdrag. Merk at Java-kodelistene for disse eksemplene er fokusert på bruk Graf.Bygger for å lage det passende Kurve gjenstand. Ringer til findViewById (), setGraph (), setTitle (), etc., vil være lik de som vises i Listing 5 og er ikke inkludert i kodelistene.

$config[zx-auto] not found$config[zx-overlay] not found