ในช่วงหลายปีที่ผ่านมาฉันได้เห็นการใช้งานรูปแบบการนำทางของ Android ที่แตกต่างกัน แอปพลิเคชันบางตัวใช้เฉพาะกิจกรรมในขณะที่กิจกรรมอื่น ๆ ผสมกับตัวอย่างข้อมูลและ / หรือมุมมองที่กำหนดเอง ( มุมมองที่กำหนดเอง ).
หนึ่งในการใช้งานรูปแบบแฟรกเมนต์ที่ฉันชอบคือตามปรัชญา“ หนึ่งกิจกรรม - หลายชิ้นส่วน” (“ หนึ่งกิจกรรม - หลายชิ้นส่วน ”) หรือเพียงแค่รูปแบบการนำทางส่วนย่อย ( รูปแบบการนำทางส่วนย่อย ) โดยที่แต่ละหน้าจอในแอปพลิเคชันเป็น Fragment แบบเต็มหน้าจอและส่วนทั้งหมดหรือส่วนใหญ่จะอยู่ในกิจกรรม
วิธีนี้ไม่เพียง แต่ทำให้การนำทางไปใช้งานง่ายขึ้นเท่านั้น แต่ยังมีประสิทธิภาพที่ดีขึ้นและมอบประสบการณ์การใช้งานที่ดีขึ้น
ในบทความนี้เราจะสำรวจการใช้งานรูปแบบการนำทางทั่วไปบน Android จากนั้นแนะนำรูปแบบการนำทางที่ใช้ Snippet ตัวอย่างแอปพลิเคชันที่ใช้รูปแบบนี้สามารถพบได้ใน GitHub .
แอปพลิเคชัน Android ทั่วไปที่ใช้เฉพาะกิจกรรมจะถูกจัดระเบียบในโครงสร้างประเภทต้นไม้ (ในกราฟกำกับอย่างแม่นยำ) ซึ่งกิจกรรมหลักเริ่มต้นโดย ตัวเรียกใช้งาน . ขณะเรียกดูแอปพลิเคชันจะมี“ กองหลัง 'ของกิจกรรมที่ดูแลด้วยระบบปฏิบัติการ
ตัวอย่างง่ายๆแสดงในแผนภาพต่อไปนี้:
กิจกรรม A1 เป็นจุดเริ่มต้นของแอปพลิเคชันของเรา (เช่นแสดงถึงหน้าจอเริ่มต้นหรือเมนูหลัก) และจากจุดนั้นผู้ใช้สามารถไปที่ A2 หรือ A3 ได้ เมื่อคุณต้องการสื่อสารระหว่างกิจกรรมต่างๆคุณสามารถใช้ได้ startActivityForResult () หรือคุณสามารถแบ่งปันวัตถุเชิงตรรกะทางธุรกิจที่สามารถเข้าถึงได้ทั่วโลกระหว่างทั้งสองกิจกรรม
เมื่อคุณต้องการเพิ่มกิจกรรมใหม่คุณต้องทำตามขั้นตอนต่อไปนี้:
แม้ว่าแผนภาพการนำทางนี้เป็นแนวทางที่ค่อนข้างง่าย แต่อาจซับซ้อนมากเมื่อคุณต้องการ จัดการกับ กองหลัง หรือเมื่อคุณต้องใช้กิจกรรมเดิมซ้ำหลาย ๆ ครั้งตัวอย่างเช่นเมื่อคุณต้องการให้ผู้ใช้นำทางผ่านหน้าจอการสอนที่แตกต่างกัน แต่แต่ละหน้าจอจะใช้กิจกรรมเดียวกันเป็นฐาน
โชคดีที่เรามีเครื่องมือสำหรับกรณีเหล่านี้ที่เรียกว่า เหลือเกิน และคำแนะนำสำหรับ การนำทางของ กองหลัง เหมาะสม .
ความแตกต่างระหว่าง s และ c corp llc
จากนั้นด้วย API ระดับ 11 ชิ้นส่วนก็มาถึง ...
Android แนะนำตัวอย่างข้อมูลใน Android 3.0 (API ระดับ 11) โดยหลักแล้วจะรองรับรูปแบบ UI แบบไดนามิกและยืดหยุ่นบนหน้าจอขนาดใหญ่เช่นแท็บเล็ต เนื่องจากหน้าจอของแท็บเล็ตมีขนาดใหญ่กว่าโทรศัพท์มากจึงมีพื้นที่ในการผสมผสานและจับคู่องค์ประกอบ UI มากขึ้น ตัวอย่างข้อมูลสนับสนุนเค้าโครงเหล่านั้นโดยไม่จำเป็นให้คุณจัดการการเปลี่ยนแปลงที่ซับซ้อนของลำดับชั้นมุมมอง ด้วยการแบ่งการออกแบบของกิจกรรมออกเป็นชิ้น ๆ คุณสามารถปรับเปลี่ยนลักษณะที่ปรากฏของกิจกรรมในเวลาดำเนินการและเก็บการเปลี่ยนแปลงเหล่านั้นไว้ในกองกิจกรรมที่จัดการโดยกิจกรรม - อ้างจาก Google Guide API สำหรับ Fragments .
ของเล่นใหม่นี้อนุญาตให้นักพัฒนาสร้างอินเทอร์เฟซผู้ใช้แบบหลายแผงและสามารถนำส่วนประกอบกลับมาใช้ในกิจกรรมอื่น ๆ ได้ นักพัฒนาบางคนชอบสิ่งนี้ในขณะที่คนอื่น ๆ ไม่มาก . การใช้ Snippets เป็นการถกเถียงที่ได้รับความนิยมหรือไม่ แต่ฉันคิดว่าทุกคนจะยอมรับว่าตัวอย่างข้อมูลมีความซับซ้อนเพิ่มขึ้นและนักพัฒนาต้องเข้าใจอย่างถูกต้องเพื่อที่จะใช้งานได้
ฉันเริ่มเห็นตัวอย่างมากขึ้นเรื่อย ๆ ที่ตัวอย่างข้อมูลไม่เพียง แต่แสดงถึงส่วนหนึ่งของหน้าจอเท่านั้น แต่ทั้งหน้าจอยังเป็นเพียงตัวอย่างข้อมูลภายในกิจกรรม กาลครั้งหนึ่งฉันเห็นเค้าโครงที่ทุกกิจกรรมมีตัวอย่างข้อมูลแบบเต็มหน้าจอเพียงชุดเดียวและไม่มีอะไรอื่นเลยและเหตุผลเดียวที่กิจกรรมเหล่านั้นมีอยู่คือการจัดเก็บตัวอย่างข้อมูล นอกเหนือจากข้อบกพร่องในการออกแบบแล้วยังมีปัญหาอีกประการหนึ่งในแนวทางนี้ ดูแผนภาพด้านล่าง:
A1 สื่อสารกับ F1 ได้อย่างไร? สิ่งที่เกิดขึ้นคือ A1 สามารถควบคุม F1 ได้อย่างเต็มที่เพราะมันสร้าง F1 ขึ้นมา A1 สามารถส่งผ่านแพ็คเกจตัวอย่างเช่นในการสร้าง F1 หรือสามารถเรียกใช้วิธีการสาธารณะได้ F1 สื่อสารกับ A1 ได้อย่างไร? มันซับซ้อนกว่านั้นมันสามารถแก้ไขได้ด้วยรูปแบบของ โทรกลับ / ผู้สังเกตการณ์ โดยที่ A1 สมัคร F1 และ F1 จะแจ้งเตือน A1
แต่ A1 และ A2 สื่อสารกันได้อย่างไร? ตามที่อธิบายไว้ข้างต้นพวกเขาสามารถสื่อสารผ่าน startActivityForResult () .
และตอนนี้คำถามจริง: F1 และ F2 สื่อสารกันได้อย่างไร? แม้ในกรณีนี้เราสามารถมีองค์ประกอบตรรกะทางธุรกิจที่สามารถเข้าถึงได้ทั่วโลกและสามารถใช้เพื่อส่งผ่านข้อมูลได้ แต่ส่วนประกอบนั้นไม่ได้ถือเป็นการออกแบบที่หรูหราเสมอไป จะเป็นอย่างไรหาก F2 ต้องการส่งข้อมูลไปยัง F1 โดยตรงมากกว่านี้ ในกรณีเช่นนี้มีรูปแบบ โทรกลับ F2 สามารถแจ้ง A2 จากนั้น A2 จะจบลงด้วยผลลัพธ์และผลลัพธ์นั้นสามารถจัดเก็บได้โดย A1 ซึ่งสามารถแจ้ง F1 ได้
แนวทางนี้ต้องใช้รหัสจำนวนมาก หม้อไอน้ำ และกลายเป็นแหล่งที่มาของ จุดบกพร่อง ความเจ็บปวดและความโกรธ
จะเป็นอย่างไรหากเราสามารถกำจัดกิจกรรมทั้งหมดและเก็บไว้เพียงหนึ่งกิจกรรมซึ่งจะทำให้ส่วนที่เหลืออยู่?
วิธีปรับปรุงประสิทธิภาพของฐานข้อมูล
เมื่อเวลาผ่านไปฉันเริ่มใช้รูปแบบ“ หนึ่งกิจกรรม - หลายชิ้นส่วน” ในแอปพลิเคชันส่วนใหญ่ของฉันและฉันก็ยังใช้มันอยู่ มีการอภิปรายมากมายเกี่ยวกับแนวทางหรือปรัชญานี้เช่น ที่นี่ ย ที่นี่ . สิ่งที่ฉันพลาดคือตัวอย่างเฉพาะที่ฉันสามารถดูและทดสอบด้วยตัวเอง
ลองดูแผนภาพต่อไปนี้สักครู่:
ตอนนี้เรามีกิจกรรมคอนเทนเนอร์เพียงรายการเดียวและเรามีชิ้นส่วนหลายชิ้นที่อยู่ในโครงสร้างประเภทต้นไม้อีกครั้ง การนำทางระหว่างกันจะถูกจัดการโดยไฟล์ FragmentManager นี้มี กองหลัง .
แนวทางปฏิบัติที่ดีที่สุดสำหรับการออกแบบฐานข้อมูล mysql
คุณจะรู้ว่าตอนนี้เราไม่มี startActivityForResult () แต่เราสามารถใช้รูปแบบได้ โทรกลับ / ผู้สังเกตการณ์ . ตอนนี้เรามาดูข้อดีข้อเสียของแนวทางนี้:
ตอนนี้เรามีเพียงกิจกรรมเดียวเราไม่จำเป็นต้องอัปเดตไฟล์ Manifest ทุกครั้งที่เพิ่มหน้าจอใหม่อีกต่อไป ไม่เหมือนกิจกรรมเราไม่ต้องประกาศเศษ
สิ่งนี้อาจดูเหมือนเป็นเรื่องเล็กน้อย แต่สำหรับแอปพลิเคชันขนาดใหญ่ที่มีกิจกรรมมากกว่า 50 กิจกรรมสิ่งนี้สามารถปรับปรุงความสามารถในการอ่านไฟล์ AndroidManifest.xml ไฟล์.
ดูไฟล์รายการสำหรับแอปพลิเคชันตัวอย่างซึ่งมีหลายหน้าจอ ไฟล์ Manifest นั้นง่ายมาก
package='com.exarlabs.android.fragmentnavigationdemo.ui' >
ในโค้ดตัวอย่างของฉันคุณจะสังเกตเห็นว่าฉันใช้ NavigationManager ซึ่งในกรณีของฉันจะถูกฉีดไปยังชิ้นส่วนแต่ละชิ้น ผู้จัดการนี้สามารถใช้เป็นจุดศูนย์กลางสำหรับไฟล์ การบันทึก , การจัดการ กองหลัง เพื่อให้พฤติกรรมการท่องเว็บถูกแยกออกจากตรรกะทางธุรกิจที่เหลือและไม่กระจายไปตามการใช้งานหน้าจอต่างๆ
ลองนึกภาพสถานการณ์ที่เราต้องการเริ่มหน้าจอซึ่งผู้ใช้สามารถเลือกบางรายการจากรายชื่อบุคคล นอกจากนี้คุณยังต้องการส่งผ่านข้อโต้แย้งในการกรองเช่นอายุอาชีพและเพศ
ในกรณีของกิจกรรมคุณจะต้องเขียน:
Intent intent = new Intent(); intent.putExtra('age', 40); intent.putExtra('occupation', 'developer'); intent.putExtra('gender', 'female'); startActivityForResult(intent, 100);
จากนั้นคุณต้องกำหนด onActivityResult ลงที่ไหนสักแห่งและจัดการกับผลลัพธ์
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); }
ปัญหาส่วนตัวของฉันเกี่ยวกับแนวทางนี้คืออาร์กิวเมนต์เหล่านี้เป็น 'ส่วนเสริม' และไม่จำเป็นดังนั้นฉันต้องตรวจสอบให้แน่ใจว่ากิจกรรมการรับนั้นจัดการกับกรณีต่างๆได้เมื่อไม่มีส่วนเกิน หลังจากนั้นเมื่อทำการ refactoring เสร็จและเมื่อไม่จำเป็นต้องใช้ส่วนเสริมเช่น 'age' อีกต่อไปฉันต้องดูโค้ดทั้งหมดที่กิจกรรมนี้เริ่มต้นและตรวจสอบให้แน่ใจว่าส่วนเสริมทั้งหมดนั้นถูกต้อง
นอกจากนี้จะดีกว่าไหมหากผลลัพธ์ (รายชื่อบุคคล) จะมาเป็น _List_ และไม่อยู่ในรูปแบบอนุกรมซึ่งจะต้องถูก deserialized
ในกรณีของการเรียกดูตามตัวอย่างข้อมูลทุกอย่างจะตรงไปตรงมามากขึ้น สิ่งที่คุณต้องทำคือเขียนวิธีการในไฟล์ NavigationManager เรียกว่า startPersonSelectorFragment () ด้วยข้อโต้แย้งที่จำเป็นและการดำเนินการ โทรกลับ .
mNavigationManager.startPersonSelectorFragment(40, 'developer', 'female', new PersonSelectorFragment.OnPersonSelectedListener() { @Override public boolean onPersonsSelected(List selection) { [do something] return false; } });
หรือด้วย RetroLambda
mNavigationManager.startPersonSelectorFragment(40, 'developer', 'female', selection -> [do something]);
ระหว่างกิจกรรมเราสามารถแชร์ได้เฉพาะแพ็กเกจที่มีข้อมูลดั้งเดิมหรือข้อมูลที่เป็นอนุกรมเท่านั้น ตอนนี้เราสามารถใช้รูปแบบด้วยชิ้นส่วน โทรกลับ โดยที่ตัวอย่างเช่น F1 สามารถฟัง F2 ที่ส่งผ่านวัตถุโดยพลการ โปรดดูตัวอย่างการใช้งานก่อนหน้านี้ของ โทรกลับ ซึ่งส่งคืน _List_
สิ่งนี้จะชัดเจนเมื่อคุณใช้ลิ้นชักที่มีรายการเมนูเช่น 5 รายการและในแต่ละหน้าลิ้นชักควรจะแสดงอีกครั้ง
ในกรณีของการเรียกดูกิจกรรมที่แท้จริงแต่ละหน้าควรขยายและเริ่มลิ้นชัก แต่แน่นอนว่ามีราคาแพง
ในแผนภาพที่แสดงคุณสามารถเห็นส่วนต่างๆของรูทหรือ เศษราก (FR *) ซึ่งเป็นชิ้นส่วนหน้าจอที่สามารถเข้าถึงได้โดยตรงจากลิ้นชักและยังสามารถเข้าถึงลิ้นชักได้เมื่อมีการแสดงชิ้นส่วนเหล่านี้เท่านั้น ทุกอย่างทางด้านขวาของเส้นที่ทำเครื่องหมายไว้ในแผนภาพจะมีเป็นตัวอย่างของรูปแบบการนำทางโดยพลการ
เนื่องจากกิจกรรมที่บรรจุมีลิ้นชักเราจึงมีเพียงหนึ่งอินสแตนซ์ของลิ้นชักดังนั้นแต่ละขั้นตอนการนำทางที่ลิ้นชักควรมองเห็นได้ คุณไม่จำเป็นต้องเริ่มต้นใหม่อีกครั้ง . ยังไม่มั่นใจว่าทุกอย่างทำงานอย่างไร? ลองดูตัวอย่างแอพของฉันที่สาธิตการใช้งานลิ้นชัก
ความกลัวที่ยิ่งใหญ่ของฉันคือถ้าฉันใช้รูปแบบการนำทางแบบแยกส่วนในโครงการเมื่อถึงจุดหนึ่งฉันจะพบปัญหาที่ไม่รู้จักซึ่งจะยากที่จะแก้ไขเกี่ยวกับความซับซ้อนของชิ้นส่วนไลบรารีบุคคลที่สามและระบบเวอร์ชันต่างๆ ปฏิบัติการ. จะเป็นอย่างไรถ้าฉันต้องหักเหทุกสิ่งที่ทำไปแล้ว?
ในความเป็นจริงคุณจะต้องแก้ปัญหาด้วย เศษที่ซ้อนกัน ไลบรารีของบุคคลที่สามที่ใช้ตัวอย่างเช่น ShinobiControls , ViewPagers ย FragmentStatePagerAdapters .
ฉันยอมรับว่าการได้รับประสบการณ์เพียงพอกับชิ้นส่วนเพื่อแก้ปัญหาเหล่านี้เป็นกระบวนการที่ยาวนาน แต่ในแต่ละกรณีปัญหาไม่ใช่ว่าปรัชญาไม่ดี แต่เขาไม่เข้าใจชิ้นส่วนมากพอ แต่ถ้าคุณเข้าใจชิ้นส่วนได้ดีกว่าที่ฉันทำในตอนนั้นคุณก็จะไม่มีปัญหา
สถาปนิกโซลูชันเว็บเซอร์วิสอเมซอน
ข้อเสียเพียงอย่างเดียวที่ฉันสามารถพูดถึงได้ในตอนนี้คือเราสามารถพบปัญหาที่ไม่สามารถแก้ไขได้เนื่องจากไม่มีไลบรารีสำหรับผู้ใหญ่ที่แสดงสถานการณ์ที่ซับซ้อนทั้งหมดของแอปพลิเคชันที่ซับซ้อนพร้อมการนำทางตามส่วน
ในบทความนี้เราได้เห็นทางเลือกอื่นในการใช้การนำทางในแอปพลิเคชัน Android . รูปแบบนี้ถูกเปรียบเทียบกับปรัชญาการนำทางแบบดั้งเดิมที่ใช้กิจกรรมและเราเห็นเหตุผลที่ดีบางประการว่าทำไมการใช้ชิ้นส่วนแทนแนวทางดั้งเดิมจึงเป็นประโยชน์
ในกรณีที่คุณยังไม่ได้ตรวจสอบให้ตรวจสอบแอปสาธิตในการปรับใช้ GitHub . อย่ากลัวที่จะนำเสนอตัวอย่างที่ดีที่สามารถแสดงให้เห็นถึงการใช้งานได้ดีขึ้น
ที่เกี่ยวข้อง: ข้อผิดพลาดทั่วไป 10 อันดับแรกที่นักพัฒนา Android ทำ