แนวคิดและสถาปัตยกรรมของ Remote Compose

Remote Compose เป็นไลบรารี Jetpack ที่ช่วยให้คุณสร้าง UI ด้วย API สไตล์ Compose ในแอปและแสดงในกระบวนการของระบบ เช่น วิดเจ็ตแอปหรือวิดเจ็ต Wear OS แอปจะบันทึก UI เป็นเอกสารขนาดกะทัดรัด และโปรแกรมเล่นในกระบวนการโฮสต์จะแสดงผลและจัดการการโต้ตอบ การเปลี่ยนแปลงสถานะ และภาพเคลื่อนไหวในเครื่องโดยไม่ต้องเรียกกลับไปยังแอป

คู่มือนี้จะอธิบายสถาปัตยกรรม Remote Compose และความแตกต่างจาก Jetpack Compose มาตรฐาน คู่มือนี้มุ่งเน้นที่การสร้าง UI ด้วยคอมโพเนนต์

กรณีการใช้งาน Remote Compose

คุณใช้ Remote Compose ได้ในทุกแพลตฟอร์มที่มีเพลเยอร์ที่รองรับ ใน Android วิดเจ็ตนี้จะขับเคลื่อนวิดเจ็ตแอปและวิดเจ็ต Wear OS

วิธีการทำงาน: สถาปัตยกรรม 3 บล็อก

ความแตกต่างทางสถาปัตยกรรมพื้นฐานระหว่าง Remote Compose กับ Jetpack Compose มาตรฐานอยู่ที่การแยกคำจำกัดความของ UI ออกจากการดำเนินการในบล็อกระดับสูง 3 บล็อก ได้แก่

  • สร้างเอกสาร: แอปจะเรียกใช้ฟังก์ชัน @RemoteComposable เพื่อบันทึกเอกสาร ซึ่งเป็นคำอธิบายแบบย่อและเรียงลำดับของ UI รวมถึงเลย์เอาต์ สถานะระยะไกล และการดำเนินการ เมื่อข้อมูลมีการเปลี่ยนแปลง แอปจะบันทึกและส่งเอกสารใหม่ได้
  • ส่งเอกสารไปยังโฮสต์ระยะไกล: แอปของคุณจะส่งเอกสารไปยังโฮสต์ ซึ่งเป็นกระบวนการที่แสดงเอกสาร เช่น Launcher หรือ Wear OS
  • เล่นเอกสาร: โปรแกรมเล่น Remote Compose ในโฮสต์จะแสดงผลเอกสารและจัดการเลย์เอาต์ อินพุต การเปลี่ยนแปลงสถานะ UX และภาพเคลื่อนไหวในเครื่องโดยไม่ต้องเรียกกลับไปยังแอปของคุณ

สถาปัตยกรรมนี้มีประโยชน์หลักๆ ที่ช่วยลดเวลาในการตอบสนองโดยตรง ดังนี้

  • เอกสารขนาดเล็ก: สแนปชอตเอกสารที่เรียงลำดับแล้วจะยังคงมีขนาดกะทัดรัดและใช้ทรัพยากรน้อย
  • ลดการส่งข้อมูลไปกลับ: เนื่องจากโปรแกรมเล่นโฮสต์ระยะไกลจะจัดการการโต้ตอบและการเปลี่ยนแปลงสถานะในเครื่อง จึงช่วยลดการสื่อสารไปกลับไปยังแอปพลิเคชันหรือเซิร์ฟเวอร์ได้

การเปรียบเทียบกับหน้าเว็บ/HTML: Remote Compose ทำงานคล้ายกับการแสดงหน้าเว็บ เซิร์ฟเวอร์แอปจะสร้างและส่งโครงสร้าง HTML/เอกสารเพียงครั้งเดียว จากนั้นโฮสต์เบราว์เซอร์จะแสดงผลและจัดการการโต้ตอบในเครื่องโดยไม่ต้องค้นหาแบ็กเอนด์อย่างต่อเนื่อง

การสื่อสารระหว่างกระบวนการของแอปกับกระบวนการของโฮสต์ระยะไกลสำหรับ Remote Compose
รูปที่ 1 บล็อกทั้ง 3 ของสถาปัตยกรรม Remote Compose

คอมโพเนนต์

Remote Compose มีคอมโพเนนต์ UI ระดับสูงเพื่อจัดโครงสร้างเลย์เอาต์ ใช้คอมโพเนนต์ Remote Compose และ RemoteModifier แทนคอมโพเนนต์ Compose มาตรฐานที่เทียบเท่า ซึ่งรวมถึงคอนเทนเนอร์เลย์เอาต์พื้นฐานและคอมโพเนนต์แบบปรับเปลี่ยนได้ที่ออกแบบมาเพื่อจัดการขนาดหน้าจอแบบไดนามิกโดยเฉพาะ ดังนี้

  • คอมโพเนนต์เลย์เอาต์พื้นฐาน: องค์ประกอบเลย์เอาต์ที่คล้ายกับ Compose ทั่วไป เช่น RemoteBox, RemoteRow และ RemoteColumn
  • คอมโพเนนต์เลย์เอาต์แบบปรับอัตโนมัติ: คอมโพเนนต์เฉพาะทาง เช่น RemoteFitBox, RemoteCollapsibleRow และ RemoteCollapsibleColumn ที่ออกแบบมาให้ปรับเปลี่ยนได้อย่างราบรื่นในแพลตฟอร์มระยะไกล
  • การกำหนดธีม Material Design: การกำหนดธีมทำงานในลักษณะเดียวกันสำหรับวิดเจ็ต Wear OS โดยมีลำดับชั้นของสีและการพิมพ์ที่ได้จาก RemoteMaterialTheme ซึ่งจะช่วยให้การสร้างแบรนด์และการใช้ระบบการออกแบบมีความสอดคล้องกันในแอปและวิดเจ็ต

ภาพวาดที่กำหนดเองด้วย RemoteCanvas

สำหรับกราฟิกที่กำหนดเองและภาพเคลื่อนไหวตามเวลา ให้ใช้ RemoteCanvas ซึ่งจะบันทึกคำสั่งการวาดที่โปรแกรมเล่นเรียกใช้บนโฮสต์ คู่มือนี้มุ่งเน้นที่การสร้าง UI ด้วยคอมโพเนนต์

ความแตกต่างที่สำคัญ

โปรดอ่านแนวคิดหลักต่อไปนี้เพื่อทำความเข้าใจวิธีที่ Remote Compose จัดการสถานะ ตรรกะ และการดำเนินการ

การอ้างอิงสถานะเชิงสัญลักษณ์

ใน Compose มาตรฐาน คอนเทนเนอร์สถานะจะเก็บค่าที่ใช้งานอยู่และอ่านได้ในหน่วยความจำของแอปในเครื่องซึ่งเปลี่ยนแปลงโดยโค้ดแอป (Lambda) เมื่อเกิดเหตุการณ์ต่างๆ ในการเขียนระยะไกล การประกาศสถานะจะทำหน้าที่เป็นข้อมูลอ้างอิงเชิงสัญลักษณ์ แทนที่จะเก็บค่าที่ใช้งานอยู่ในหน่วยความจำของแอปในเครื่อง ค่าเหล่านี้จะประกาศการเชื่อมโยงที่เพลเยอร์ระยะไกลจัดการและอัปเดตในเครื่องขณะรันไทม์ โปรดคำนึงถึงข้อควรพิจารณาต่อไปนี้เมื่อประกาศสถานะใน Remote Compose

  • ใช้ฟังก์ชันโรงงานของ Remote Compose เพื่อประกาศสถานะ เช่น rememberMutableRemoteInt, rememberMutableRemoteFloat หรือ rememberMutableRemoteString
  • โค้ดแอปของคุณไม่สามารถตรวจสอบหรืออ่านค่าของตัวแปรสถานะระยะไกลได้โดยตรงในระหว่างการคอมโพสิชัน
  • โปรแกรมเล่นจะจัดเก็บและอัปเดตค่าเหล่านี้ในเครื่องเมื่อผู้ใช้โต้ตอบกับเอกสาร

สถานะระยะไกลเทียบกับโฟลว์ควบคุม Kotlin

โค้ด Kotlin จะทำงานเมื่อแอปสร้างเอกสารเท่านั้น คำสั่ง Kotlin เช่น if, when และ for สามารถกำหนดรูปร่างเอกสารตามค่าที่ทราบในขณะนั้น เช่น การทำซ้ำแถวสำหรับแต่ละรายการในลิสต์ แต่ไม่สามารถตอบสนองต่อสถานะระยะไกลที่เปลี่ยนแปลงในภายหลังได้ โปรดคำนึงถึงสิ่งต่อไปนี้เมื่อทำงานใน Remote Compose

  • ตรรกะการแยกสาขา: การสลับ UI แบบไดนามิกทำได้โดยใช้ RemoteStateLayout โดยการแมปสถานะกับช่อง RemoteComposable ต่างๆ
  • การประเมินข้อความ: หลีกเลี่ยงการใช้การแทรกสตริง Kotlin มาตรฐาน ("$remoteValue") ซึ่งจะประเมินเมื่อสร้างเอกสารเท่านั้น แต่ให้ส่ง RemoteString ไปยัง RemoteText แทน

การจัดสไตล์แบบไดนามิกโดยใช้ RemoteModifier

การจัดสไตล์แบบไดนามิกในโฮสต์จะไม่เรียกใช้ Composition ซ้ำ แต่จะส่งตัวแปรสถานะระยะไกลไปยังตัวแก้ไขโดยตรง เช่น RemoteModifier.background(remoteColor)

บริบทของระบบระยะไกล

ผู้ให้บริการ CompositionLocal เช่น LocalConfiguration หรือ LocalDensity จะแสดงเฉพาะสภาพแวดล้อมของแอปในเครื่อง ณ เวลาที่บันทึกเอกสารเท่านั้น โดยจะไม่ปรับเปลี่ยนแบบไดนามิกบนโฮสต์ระยะไกลเมื่อพื้นผิวปรับขนาด เปลี่ยนสถานะการแสดงผล หรือเวลาผ่านไป แต่ให้ใช้ค่าที่โปรแกรมเล่นแก้ไขในโฮสต์ขณะรันไทม์แทน เช่น ขนาดปัจจุบันของคอมโพเนนต์ RemoteConfiguration หรือ RemoteDensity

การดำเนินการเชิงประกาศ

ใน Compose มาตรฐาน ตัวแฮนเดิลการคลิกคือ Lambda ที่ทำงานในแอปของคุณ โฮสต์ไม่สามารถเรียกใช้โค้ดของแอปได้ ดังนั้นใน Remote Compose คุณจึงแนบการดำเนินการแทน เช่น ด้วย RemoteModifier.clickable(action) การดำเนินการสามารถอัปเดตสถานะระยะไกลบนโฮสต์ได้โดยตรงด้วย valueChange หรือส่งต่อไปยังแอปหรือโฮสต์ด้วย pendingIntentAction หรือ hostAction หากต้องการเรียกใช้การดำเนินการหลายรายการจากการคลิกเพียงครั้งเดียว ให้ใช้ combinedAction

การเปรียบเทียบกระบวนทัศน์ระดับสูง

โดเมนฟีเจอร์

Jetpack Compose มาตรฐาน

การเขียนจากระยะไกล

เหตุการณ์การคลิกและการโต้ตอบแบบสัมผัส

แลมบ์ดาแบบซิงโครนัสในกระบวนการ

ออบเจ็กต์ Action ที่เรียงลำดับแบบประกาศ

ตรรกะแบบมีเงื่อนไข

ควบคุมโฟลว์ if และ when ของ Kotlin

Kotlin if/when มาตรฐานจะทำงานตามปกติสำหรับสถานะคงที่ที่ทราบเมื่อสร้างเอกสาร

การแยกสาขาแบบไดนามิกใช้ RemoteStateLayout (สำหรับโครงสร้าง UI)

ลูปโฟลว์ควบคุม

ลูป for และ while ของ Kotlin มาตรฐาน

ลูป Kotlin มาตรฐาน (repeat, for, forEach) จะทำงานเมื่อสร้างเอกสารเท่านั้น ไม่สามารถวนซ้ำสถานะระยะไกลบนโฮสต์ได้

โฮสต์การดำเนินการ

กระบวนการของแอป

Launcher (AppWidget), วิดเจ็ต Wear OS หรือรูปแบบของอุปกรณ์ใดก็ได้ที่มีเพลเยอร์ที่รองรับ

วงจรของกระบวนการ

กระบวนการต้องทำงานอยู่เสมอเพื่อจัดองค์ประกอบใหม่และแสดงผล

เอกสารสแนปชอต UI ของบันทึกกระบวนการ โดยเครื่องมือ Remote Player จะแยกวิเคราะห์โครงสร้างคอมโพเนนต์ ติดตามการเปลี่ยนแปลงสถานะ และวาดใหม่ในเครื่องโดยไม่ต้องเรียกกลับไปยังแอป

ผลข้างเคียง

วงจรของ Coroutine (LaunchedEffect)

ไม่พร้อมใช้งานในโฮสต์ Composition จะทำงานในแอปเพื่อสร้างเอกสาร ดังนั้นเอฟเฟกต์ Coroutine จึงไม่สามารถขับเคลื่อน UI ระยะไกลได้ เว้นแต่การผสานรวมจะเปิด Composition ไว้

กระบวนทัศน์ของรัฐ

ค่าสถานะหน่วยความจำในเครื่อง

ฟังก์ชัน Factory (rememberMutableRemoteInt(), rememberNamedRemoteColor()) ที่แสดงผลการอ้างอิงสถานะเชิงสัญลักษณ์แทนค่าดิบ