GraphLib: ספריית אנדרואיד קוד פתוח לגרפים

גרפים ומגרשי נתונים הם כלים נפלאים להמחשת מערכות יחסים, לתיאור מגמות נתונים ומעקב אחר יעדים ביישומי Android שלך. ראיתי זאת בעצמי לפני מספר שנים, כאשר סטודנט לשעבר שלי זכה במקום הראשון בתחרות אפליקציות סלולר לסטודנטים בחסות התאחדות קבלני ההגנה של צ'רלסטון. מאפיין מרכזי של האפליקציה הזוכה, "סוכרת ואני", היה היכולת לשרטט את רמות הסוכר היומיות.

כדוגמה נוספת, שקול יישום למעקב אחר משקל המתכנן התקדמות מול משקל מטרה. איור 1 ממחיש כיצד יישום כזה עשוי להיראות בטלפון אנדרואיד. האיור משתמש בגרף קו אדום כדי להראות משקולות ממוצעות חודשיות לשנת 2017. הוא מראה את משקל היעד כקו ישר ירוק בסמוך לתחתית. (אף על פי שערכי הנתונים המוצגים בתרשים הקווים היפותטיים, הם מציאותיים ביחס למחבר מאמר זה.)

ג'ון הראשון

במאמר זה אשתמש בספריית הקוד הפתוח שלי, GraphLib, כדי להדגים את יסודות גרף הפונקציות המתמטיות באנדרואיד. זו לא אותה ספריית גרפים בה השתמש התלמיד שלי ליישום שלו. למעשה, זה הרבה יותר פשוט וקל לשימוש.

הורד הורד את GraphLib קבל את קוד המקור לספריית הגרפים של Android הפתוחה שהוצגה במאמר זה. נוצר על ידי ג'ון הראשון.

סקירה כללית של GraphLib

GraphLibמורכב מממשק אחד ושמונה כיתות. שלוש מהשיעורים הללו הם פנימיים בספרייה ויש להם גישה לחבילה בלבד, כך שלא תצטרך להבין אותם על מנת להשתמש ב- GraphLib. לשניים מהשיעורים הנותרים יש פונקציונליות פשוטה מאוד, ואת השאר לא קשה להרים.

להלן אתאר את ממשק GraphLib וכל אחת משמונה הכיתות שלה. שים לב שהשתמשתי בתכונות Java 8 כגון ממשקים פונקציונליים וביטויים למבדה כדי לפתח ולבדוק את הספרייה, אך זה פשוט יחסית לשנות תכונות אלה עבור גרסאות קודמות של Java.

הממשק הפונקציונלי של GraphLib

כפי שמוצג ברישום 1, לממשק Functionיש שיטה מופשטת אחת בלבד, ולכן הוא ממשק פונקציונלי. שים לב שממשק זה שווה בערך ל- Java 8 DoubleUnaryOperator, שנמצא בחבילה java.util.function. ההבדל הוא Functionשאינו משתמש בתכונות Java 8 מלבד ההערה @FunctionalInterface. הסרת הערה זו היא השינוי היחיד הדרוש בכדי להפוך את Functionהממשק לתואם לגרסאות קודמות של Java.

רישום 1. ממשק פונקציה

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

למידה על ביטויים למבדה

ביטויים למבדה, המכונים גם סגירות, מילולי פונקציה או פשוט למבדות, מתארים קבוצה של תכונות שהוגדרו בבקשת Java Specification (JSR) 335. הקדמות רשמיות פחות לביטויי למבדה ניתנות בחלק מהגרסה האחרונה של מדריך Java; במאמר JavaWorld "תכנות ג'אווה עם ביטויים למבדה", ובכמה מאמרים מאת בריאן גץ, "מצב הלמבה" ו"מצב הלמבה: מהדורת ספריות ".

שיעורי GraphLib

חוגים Pointו Labelהם פשוט יחסית: Pointמתמצת זוג הערכים כפול המייצג נקודה x, y -plane, ו Labelמתמצת בערך כפול מחרוזת, שבו הערך כפול מייצג נקודה על ציר ואת המחרוזת משמשת לאותה תווית נְקוּדָה. הדוגמה באיור 1 משתמשת בנקודות לתיאור גרף הקווים והתוויות של הציר בתחתית, ומציגות קיצורים באות אחת עבור החודשים. אביא דוגמאות נוספות הממחישות את השימוש בשיעורים אלה בהמשך המאמר.

חוגים GraphFunction, GraphPoints, ו ScreenPointהם לא רק פשוט מאוד, הם גם פנימיים לספרייה יש לארוז רק גישה. אתה לא באמת צריך להבין את השיעורים האלה כדי להשתמש בספרייה, אז אתאר אותם רק בקצרה כאן:

  • GraphFunctionמקפל פונקציה (כלומר, מחלקה המיישמת ממשק Function) וצבע המשמש לציור פונקציה זו.
  • GraphPointsעוטף רשימת נקודות יחד עם צבע המשמש לרישומן. מחלקה זו משמשת באופן פנימי הן לשרטוט נקודות והן לשרטט גרפים.
  • ScreenPointמקפל זוג ערכים שלמים המייצגים קואורדינטות פיקסל על גבי מסך מכשיר אנדרואיד. מחלקה זו דומה אך פשוטה יותר משיעור אנדרואיד Pointבחבילה android.graphics.

סיפקתי את קוד המקור לשיעורים אלה למקרה שאתה מעוניין בפרטים.

שלושת השיעורים הנותרים בספרייה GraphLib הם Graph, Graph.Builder, ו GraphView. חשוב להבין את התפקיד שכל אחד מהם ממלא ביישום אנדרואיד.

המחלקה Graphמכילה מידע על הצבעים, הנקודות, התוויות, הגרפים וכו 'שצוירו, אך למעשה אינה תלויה בפרטי הגרפיקה של Android. אמנם Graphיש הרבה שדות, אך לכולם יש ערכי ברירת מחדל, ולכן זה הגיוני להשתמש בתבנית Builder כדי ליצור מופעים של מחלקה זו. המחלקה Graphמכילה תת-מחלקה סטטית מקוננת בשם Builder, המשמשת ליצירת Graphאובייקטים.

שתי כיתות Graphו Graph.Builderללכת יחד, מנקודת מבט של המפתחים, וצריך להבין, למעשה, כאחת. למען האמת, אתה רק צריך להבין כיצד להשתמש בכיתה המקוננת Builderכדי ליצור Graphאובייקט. מפתחים לא באמת עושים שום דבר ישירות עם Graphאובייקט לאחר שנוצר מלבד להעביר אותו GraphViewלאובייקט, מה שעושה את העבודה של הצגת הכל במכשיר אנדרואיד.

רישום 2 מסכם את השיטות הקיימות בכיתה Graph.Builder. דוגמאות מאוחרות יותר ימחישו כיצד להשתמש בתבנית Builder ליצירת Graphאובייקטים. לעת עתה, מספיק לציין כי מלבד קונסטרוקטור ברירת המחדל (שורה ראשונה ברישום 2) build()והשיטה (שורה אחרונה ברשימה 2), כל שיטות אחרות מחזירות את Builderהאובייקט. זה מאפשר לשרשר שיחות לשיטות בנייה.

רישום 2. סיכום השיטות בכיתה Graph.Builder

 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[] points) public Builder addPoints(List points) public Builder addLineGraph(Point[] points, int lineGraphColor) public Builder addLineGraph(List points, int lineGraphColor) public Builder addLineGraph(Point[] points) public Builder addLineGraph(List points) 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(double axisX, double axisY) public Builder setXTicks(double[] xTicks) public Builder setXTicks(List xTicks) public Builder setYTicks(double[] yTicks) public Builder setYTicks(List yTicks) public Builder setXLabels(Label[] xLabels) public Builder setXLabels(List xLabels) public Builder setYLabels(Label[] yLabels) public Builder setYLabels(List yLabels) public Graph build() 

יציין ברישום 2 כי רבות מהשיטות עמוסות יתר על מנת לקבל מערכים של אובייקטים או רשימות של אובייקטים. אני מעדיף מערכים על פני רשימות לדוגמאות במאמר זה, פשוט כי הרבה יותר קל לאתחל מערכים, אך GraphLibתומך בשניהם. עם זאת, Java 9 יכיל שיטות מפעל נוחות לאוספים, ובכך תסיר יתרון קטן זה למערכים. אם Java 9 היה בשימוש נרחב בזמן מאמר זה, הייתי מעדיף רשימות על פני מערכים בשתי GraphLibהדוגמאות והמאוחרות.

דפוס הבנאי

למידע נוסף על תבנית Builder, עיין במהדורה השנייה של Java Effective מאת ג'ושוע בלוך או במאמר JavaWorld "יותר מדי פרמטרים בשיטות Java, חלק 3: תבנית Builder" מאת דסטין מרקס.

שיעורי ממשק משתמש באנדרואיד נקראים תצוגות , ומחלקה Viewבחבילה android.viewהיא אבן הבניין הבסיסית עבור רכיבי ממשק משתמש. נוף תופס שטח מלבני על המסך, ואחראי על ציור וטיפול באירועים. מנקודת מבט ירושה, מחלקה Viewהיא מחלקה קדומה לא רק של פקדי ממשק משתמש (כפתורים, שדות טקסט וכו '), אלא גם של פריסות, שהן קבוצות תצוגה בלתי נראות האחראיות העיקריות לסידור רכיבי ילדיהם.

מחלקה GraphViewמרחיבה את הכיתה Viewוהיא אחראית על הצגת המידע המצורף ב- Graphעל גבי מסך מכשיר אנדרואיד. לפיכך, השיעור GraphViewהוא המקום בו כל הציור מתרחש.

שימוש ב- GraphLib

ישנן שתי גישות ליצירת ממשקי משתמש עבור אנדרואיד: גישה פרוצדוראלית (בתוך קוד המקור של Java) או גישה הצהרתית (בקובץ XML). כל אחד מהם תקף, אבל הסכמה היא להשתמש בגישה ההצהרתית ככל האפשר. השתמשתי בגישה הצהרתית לדוגמאות שלי.

ישנם חמישה שלבים בסיסיים לשימוש GraphLibבספרייה. לפני שתתחיל, הורד את קוד המקור של Java עבור ספריית GraphLib. 

הורד הורד את GraphLib.jar קבל את קוד המקור של Java עבור GraphLib. נוצר על ידי ג'ון הראשון.

שלב 1. הפוך את graphlib.jar לזמין לפרויקט Android שלך

Create a new project using Android Studio and copy the JAR file graphlib.jar to the libs subdirectory of your project's app directory. In Android Studio, switch the folder structure from Android to Project. Next, in the libs folder (nested within the app folder), right-click on the JAR file and click on Add as library. This last action will add the JAR file in the dependencies section of your app's build.gradle file. See "How to add a jar in external libraries in Android Studio" if you need help with this step.

Step 2. Create an Android activity that will use GraphLib

In Android applications, an activity represents a single screen with a user interface. Activities are defined primarily in two files: an XML file that declares the UI layout and components, and a Java file that defines runtime functionality such as event handling. When a new project is created, Android Studio usually creates a default activity named MainActivity. Use this activity or create a new one for your application.

Step 3. Add a GraphView to the layout for the activity

In the XML file for the activity's layout, you will declare a GraphView object in much the same way that you declare a button or a text view, except that you need to provide the full package name for the GraphView. Listing 3 shows an excerpt from a layout file that declares a GraphView followed by a TextView as part of a vertical linear layout. Following recommended practice, the actual values for the width and height of the GraphView are defined in separate dimen resource files, where different resource files provide values for different screen sizes/densities. (Note: I used 325 for both values in the examples below.)

Listing 3. Declaring a GraphView and a TextView in a layout XML file

Step 4. Import the library classes into the activity

Listing 4 shows the list of import statements for an application if the library classes are imported individually. The list of imports can be abbreviated to a single line as import com.softmoore.android.graphlib.* if desired. Personally, I prefer to see the expanded list as shown in Listing 4.

Listing 4. Import the library classes

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

Step 5. Create a Graph object and add it to the GraphView

Listing 5 shows the creation of a simple graph object--in this case a graph object that uses all of the default values. It essentially contains only a set of x- and y-axes, where the values on both axes range from 0 to 10. The listing also sets a title for the screen and text for the text view below the graph.

Listing 5. Create a Graph object and add it to the GraphView

 Graph graph = new Graph.Builder() .build(); GraphView graphView = findViewById(R.id.graph_view); graphView.setGraph(graph); setTitle("Empty Graph"); TextView textView = findViewById(R.id.graph_view_label); textView.setText("Graph of Axes"); 

איור 2 מציג את התוצאה של הפעלת יישום זה במכשיר אנדרואיד.

ג'ון הראשון

שימוש ב- GraphLib ביישומי אנדרואיד

להמשך המאמר אתמקד בשימושים בעולם האמיתי בספריית GraphLib בפיתוח אפליקציות אנדרואיד. אציג שבע דוגמאות עם תיאורים קצרים וקטעי קוד מקור. שים לב כי רשימות קוד Java עבור דוגמאות אלה מתמקדות בשימוש Graph.Builderליצירת Graphהאובייקט המתאים . שיחות findViewById(), setGraph(), setTitle(), וכו ', תהיינה דומות לאלה שמוצג מודעה 5 ואינו כלול רישומי הקוד.