คำแนะนำที่ละเอียดเกินไปสำหรับไลบรารี Android ที่ใช้งานไม่ได้
เผยแพร่แล้ว: 2022-03-11นักพัฒนาที่มีประสบการณ์จะบอกคุณว่าโค้ดที่ดีที่สุดไม่ใช่โค้ดที่พวกเขาเขียน เป็นรหัสที่เอามาจากงานของคนอื่น
ใช่ นักพัฒนาของเราเป็นนักแก้ปัญหาที่สร้างสรรค์ แต่ปัญหามากมายที่เราพบได้รับการแก้ไขแล้ว—และการแก้ไขที่รวมอยู่ในไลบรารีที่ทุกคนสามารถใช้ได้ ทำไมต้องคิดค้นล้อใหม่เมื่อมีล้อฟรีอยู่ทุกหนทุกแห่ง?
แอนดรอยด์ก็ไม่มีข้อยกเว้น แหล่งที่มาที่ดีที่สุดสำหรับการนำโค้ดกลับมาใช้ใหม่คือ Android SDK เอง ซึ่งมาพร้อมกับโครงสร้างและบริการที่ยอดเยี่ยมที่จะทำงานให้คุณได้มากมาย
แต่ในกรณีที่ SDK ใช้งานไม่ได้ ชุมชน Android ได้สร้างไลบรารีระดับแนวหน้าขึ้นมาบางส่วน ซึ่งสามารถช่วยคุณประหยัดงานเขียนโค้ดได้มากมาย แทนที่ด้วยการใช้งานที่ได้รับการปรับแต่ง ตรวจสอบ และทดสอบอย่างเข้มงวด ฉันไม่ได้หมายถึงไลบรารี่ที่ชัดเจน—ไลบรารีสนับสนุน Android, ไลบรารีสนับสนุนการออกแบบ Android, Gson ฉันหมายถึงเครื่องมือที่คุณอาจไม่รู้ และถึงแม้ว่าคุณจะยังไม่ได้ใช้งานก็ตาม
ฉันได้พัฒนา ให้คำปรึกษา และเป็นผู้นำทีม Android มาหลายปีแล้ว และฉันได้ศึกษาและใช้เครื่องมือและไลบรารีภายนอกมากมาย (ฉันรู้ด้วยซ้ำว่าเคยอ่านโค้ดการนำไปใช้และพูดคุยเรื่องภายในกับนักพัฒนา) หลายคนช่วยให้ฉันทำงานให้สำเร็จลุล่วงได้อย่างมีประสิทธิภาพมาก แต่ความจริงก็คือ ส่วนใหญ่ไม่เป็นเช่นนั้น
นั่นเป็นเหตุผลที่ฉันได้รวบรวมคู่มือนี้ไว้ด้วยกัน อาศัยประสบการณ์ของฉัน เช่นเดียวกับนักพัฒนามือถือรายอื่นๆ เพื่อให้แน่ใจว่าคุณกำลังใช้ห้องสมุดที่ดีที่สุด ฉันเลือกเซเว่นแล้ว ฉันสงสัยว่าพวกเขาจะเป็นคนโปรดของคุณในไม่ช้าเช่นกัน
การเลือกห้องสมุด Android ที่เหมาะสม
เมื่อเลือกห้องสมุด ฉันมองหาคุณสมบัติหลักสี่ประการ:
- เป็นโซลูชันที่สม่ำเสมอและมีคุณภาพสูงสำหรับปัญหาจริงและไม่สำคัญ
- ใช้ API ที่เรียบง่ายที่สุด
- มันไม่ได้บังคับการเปลี่ยนแปลงใดๆ ในสถาปัตยกรรมโดยรวมของฉัน
- มีฐานผู้ใช้ขนาดใหญ่และควรเป็นชุมชนนักพัฒนาที่มีความกระตือรือร้น
คุณสมบัติสามประการแรกคือตัวทำลายข้อตกลง หากไม่มีอยู่ ฉันจะไปต่อหรือเริ่มเขียนโค้ดด้วยมือ
ห้องสมุดที่ฉันกล่าวถึงด้านล่างผ่านการทดสอบทั้งสี่แบบ พวกเขายังแก้ปัญหาด้านการพัฒนามือถือที่ท้าทายที่สุดบางส่วน
- ไลบรารีสองไลบรารีสำหรับการฉีดขึ้นต่อกัน การโยงเลย์เอาต์กับ Java วัตถุจำลอง
- รูปแบบข้อความผับ/ย่อยในแอป
- เลเยอร์การสื่อสาร HTTP ที่ปลอดภัย มีประสิทธิภาพ และกู้คืนได้เอง
- การจัดการรูปภาพ: ดาวน์โหลด แคช ปรับขนาด และโหลดลงใน RAM
- การสตรีมวิดีโอแบบเรียลไทม์
- การตรวจจับการรั่วไหลของหน่วยความจำ
ButterKnife: เครื่องมือฉีดพึ่งพาขั้นสูงสุด
นี่คือไลบรารีการแทรกการพึ่งพาขั้นสูงสุดสำหรับ Android เรียบง่าย แข็งแกร่ง เร็วสุด (ไม่มีการสะท้อน!) และสามารถขจัดโค้ดต้นแบบของแอป จำนวนมาก ได้
ไม่จำเป็นต้องผูกแต่ละมุมมองของคุณโดยตรงผ่านการเรียก findViewById()
; แต่มีมุมมองที่มีคำอธิบายประกอบซึ่งช่วยให้คุณเข้าถึงโค้ดได้โดยตรง ButterKnife ยังช่วยลดความจำเป็นในเหตุการณ์ UI ของสำเร็จรูป เช่น onClick
, onTouch
และอื่นๆ และแทนที่ด้วยโค้ดที่ฉีดอัตโนมัติ
แต่พอคุยเล่นๆมาดูโค้ดกัน
ดูการผูกฟิลด์:
class MyButterKnifeActivity extends Activity { @BindView(R.id.name) TextView name; @BindView(R.id.address) TextView address; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.bind(this); // MUST BE CALLED BEFORE ACCESSING UI FIELDS name.setText(“etc etc”); } }
การเชื่อมโยงทรัพยากร:
class ExampleActivity extends Activity { @BindString(R.string.username) String username; @BindDrawable(R.drawable.graphic) Drawable graphic; @BindColor(R.color.bg_color) int bgColor; @BindDimen(R.dimen.lower_padding) Float lowerPadding; // and no need for getResources().getString()/getDrawable/getColor() }
การเชื่อมโยงเหตุการณ์ UI:
@OnClick(R.id.my_button) public void clickHandler(View view) { // onClick logic goes here }
AndroidAnnotations: การพึ่งพาการฉีดไปสู่ระดับถัดไป
เป็นวินาทีที่ใกล้เคียงกับ ButterKnife เมื่อพูดถึงการพึ่งพาการฉีด AndroidAnnotations ใช้แนวทางที่แตกต่างออกไปเล็กน้อย: คลาสที่สร้างโดยอัตโนมัติซึ่งเมื่อคุณเข้าใจแล้วจะง่ายมาก มีประโยชน์มากกว่านั้นคือมันช่วยให้คุณฉีดการพึ่งพา "ตามชื่อ" ได้ ตัวอย่างเช่น @ViewById ListView myUserList;
สั่งให้ไลบรารีกำหนดฟิลด์นี้ด้วย layoutListView
โดยใช้ชื่อเดียวกัน
AndroidAnnotations นั้นเร็วมากเช่นกัน แต่ทำได้ในลักษณะที่แตกต่างจาก ButterKnife บ้าง แทนที่จะใช้การฉีดการพึ่งพาการเชื่อมโยงรันไทม์ AndroidAnnotations จะสร้างการจำลองเวลาของกิจกรรมที่ได้รับผลกระทบทั้งหมด และส่งลอจิกการเชื่อมต่อเข้าไป ดังนั้นช่วยให้คุณได้รับประสิทธิภาพเช่นเดียวกับตรรกะที่เข้ารหัสด้วยมือ
แต่ความสามารถในการฉีดของ AndroidAnnotations ทำได้มากกว่านั้น คุณสามารถใส่ทั้งสถานะและเลย์เอาต์ลงในกิจกรรมได้
การใช้งาน AndroidAnnotations:
@NoTitle @Fullscreen @EActivity(R.layout.my_layout) public class MyActivity extends Activity { @ViewById ListView customerList; // auto-binded to R.id.customerList @App MyApplication app; // auto-binded to app object @AminationRes Animation fadeoutAnimation; @UiThread void updateUI() { // main thread action } }
คำอธิบายประกอบสุดท้ายต้องการคำอธิบายเพิ่มเติมอีกเล็กน้อย: งานทั่วไปสำหรับแอป Android แบบมัลติเธรดคือการเปลี่ยนจากเธรดพื้นหลัง (หรือผู้ปฏิบัติงาน) เป็นเธรดไปข้างหน้า (หรือเธรดหลักหรือ UI) ซึ่งเป็นสิ่งเดียวที่อนุญาตให้เข้าถึงส่วนประกอบ UI . งานนี้แม้ว่าจะไม่ซับซ้อน แต่ก็มักจะต้องมีและเกี่ยวข้องกับการเข้ารหัสที่ยุ่งเหยิง:
new Handler(Looper.getMainLooper()).post(new Runnable() { logic goes here } ); // NO ANNOTATIONS
ใน AndroidAnnotations สิ่งที่คุณต้องทำคือใส่คำอธิบายประกอบให้กับฟังก์ชันของคุณด้วย @UiThread และตอนนี้ก็รับประกันว่าจะดำเนินการทุกครั้ง:
@UiThread void updateUI() {..} // WITH ANNOTATIONS
โปรดทราบว่าคำอธิบายประกอบนี้ใช้กับคลาสคอมโพเนนต์ Android มาตรฐาน (กิจกรรม บริการ และอื่นๆ) แต่จะเกิดอะไรขึ้นเมื่อฉันต้องการใส่คำอธิบายประกอบในชั้นเรียนของตัวเองด้วย
ที่นี่ AndroidAnnotations มาพร้อมกับแนวคิดใหม่ที่มาจาก EBean
สิ่งที่คุณต้องทำคือทำเครื่องหมายชั้นเรียนของคุณโดยใช้ @EBean
และคุณพร้อมแล้ว:
@EBean public class MyNonComponentClass { @SystemService NotificationManager notifManager; @Bean MyOtherClass dependency; @UiThread void updateUI() { // main thread work goes here } }
EventBus: การสื่อสารข้ามส่วนประกอบทำได้ง่าย
ห้องสมุด EventBus เปลี่ยนปัญหาที่หลอกหลอนนักพัฒนา Android มานานหลายปีให้กลายเป็นการเดินเล่นในสวนสาธารณะ การสื่อสารข้ามองค์ประกอบไม่เคยง่ายอย่างนี้มาก่อน—ใช้โมเดล pub/sub ที่เรียบง่ายเพื่อสื่อสารระหว่างสองส่วนใดๆ ของระบบของคุณ
บริการสำรวจพื้นหลังของคุณไม่จำเป็นต้องรับรู้ถึงชิ้นส่วนของคุณอีกต่อไปเพื่อป้อนด้วยเหตุการณ์การเปลี่ยนแปลง
การใช้งาน EventBus นั้นตรงไปตรงมา
ก. สร้างคลาสเหตุการณ์ การทำงานกับ POJO ที่นี่ดีที่สุด:
class NewUserEvent { String fullname; String address; String role; // add getters and setters }
ข. สร้างวิธีจัดการเหตุการณ์ในชั้นเรียน—ชั้นเรียนใดๆ ที่คุณต้องการสมัครเข้าร่วมกิจกรรมเหล่านี้:
class MySubscriber { @Subscribe public void newUserHandler(NewUserEvent event) { // handle NewUserEvent } @Subscribe public void newUserHandler(AnotherEvent event) { // handle AnotherEvent } }
แต่เดี๋ยวก่อน นักพัฒนา Android ที่มีประสบการณ์ครึ่งหนึ่งจะหยุดและถาม ณ จุดนี้: ตัวจัดการเธรดรุ่นใด และฉันสามารถบังคับตัวจัดการให้ปิดเธรดหลักได้หรือไม่ ถ้าพูด เกี่ยวข้องกับการเข้าถึงองค์ประกอบ UI คำถามที่ดี…
โดยค่าเริ่มต้น เมธอดตัวจัดการทั้งหมดจะทำงานบนเธรดของผู้ปฏิบัติงานที่นำมาจากพูลเธรดที่จัดสรรและดูแลโดย EventBus เอง หากคุณต้องการวิธีจัดการเพื่อรันบนเธรดหลัก ให้ขยายคำอธิบายประกอบการสมัครของคุณดังนี้:
@Subscribe(threadMode = ThreadMode.MAIN) public void runOnMainThreadHandler(AnotherEvent event) { … }
คำเตือน: อย่าใช้คุณสมบัตินี้มากเกินไป! ไม่ควรดำเนินการที่ใช้เวลานานบนเธรดหลัก และควรระมัดระวังแม้ในการดำเนินการที่รวดเร็ว การใช้เธรดหลักอย่างท่วมท้นเป็นวิธีที่แน่นอนที่สุดในการทำให้แอปของคุณทำงานช้า กระตุก และไม่สนุกสำหรับผู้ใช้ของคุณ
ค. จัดการวงจรการลงทะเบียน EventBus ของคลาสสมาชิกของคุณ—นั่นคือ เชื่อมต่อเมื่อใดและตัดการเชื่อมต่อจากบัสเมื่อใด ขั้นตอนการลงทะเบียนที่สมเหตุสมผลสำหรับกิจกรรมจะเป็น:
class MySubscriberActivity extends Activity { @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); // START RECEIVING EVENTS HERE } @Override public void onStop() { EventBus.getDefault().unregister(this); // NO MORE EVENTS super.onStop(); } }
แน่นอนว่าข้างต้นเป็นเพียงตัวอย่างเท่านั้น คุณสามารถดำเนินการ (ยกเลิก) การลงทะเบียนได้ทุกที่ที่คุณเลือก
ง. และสุดท้าย เริ่มเหตุการณ์จริง:
EventBus.getDefault().post(new MyEvent(“I'm here”));
มีอะไรอีกมากมายให้รู้เกี่ยวกับการใช้ EventBus: เหตุการณ์มัลติคาสต์ (พฤติกรรมเริ่มต้น) การใช้เหตุการณ์เหนียว เธรดการนำส่ง ลำดับความสำคัญ และอื่นๆ แต่ข้างต้นก็เพียงพอแล้วสำหรับคุณในการเริ่มต้นใช้เทคโนโลยีที่เรียบง่ายแต่ทรงพลังนี้
OkHttp: HttpClient ของ Android บนเตียรอยด์
นี่คือวิธีเขียน HttpClient ของ Android ง่ายมากฉลาดมาก ไลบรารี OkHttp ภายในดูแลลูปการลองใหม่ การบีบอัด payload อัตโนมัติ การสนับสนุน Http/2 การรวมการเชื่อมต่อ และการแคชการตอบสนอง คุณจึงหลีกเลี่ยงการเข้าถึงเครือข่ายที่ไม่จำเป็นได้
การใช้ OkHttp เป็นเรื่องง่าย
Http โพสต์:
OkHttpClient client = new OkHttpClient(); MediaType JSON = MediaType.parse("application/json; charset=utf-8"); RequestBody body = RequestBody.create(JSON, json_str); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string();
Http รับ:
OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(urls[0]) .build(); Response responses = client.newCall(request).execute(); String jsonData = responses.body().string();
OkHttp ยังรองรับคุณสมบัติที่มีประโยชน์ เช่น เครือข่ายอะซิงโครนัส ขอการสอบถามเส้นทางการเปลี่ยนเส้นทาง การสืบค้นแคชในเครื่อง และอื่นๆ รู้สึกอิสระที่จะใช้พวกเขาเมื่อจำเป็น นักพัฒนาส่วนใหญ่ใช้ OkHttp เพื่อทดแทน HttpURLConnection ไคลเอนต์ HTTP เริ่มต้นของ Android อย่างชาญฉลาด อันที่จริง โปรเจ็กต์ทั้งหมดนี้เริ่มต้นจากส้อมส่วนตัวสำหรับ HttpURLConnection
ฉันชอบความแข็งแกร่งของมัน—มันเพิ่มไปยังเลเยอร์เครือข่ายของคุณทันที
Picasso: มีเหตุผลที่ดีที่ Google ก็ใช้มันเช่นกัน!
Picasso เป็นวิธีที่ง่ายและมีประสิทธิภาพที่สุดในการจัดการการดาวน์โหลด การแคช การปรับขนาด และการครอบตัดรูปภาพ
คำสั่งนี้:
Picasso.with(context).load(url).resize(50,50).centerCrop().into(imageView)
จะทำสิ่งนี้ให้คุณ:
- เชื่อมต่อกับ URL ระยะไกล
- ดาวน์โหลดรูปภาพ
- เก็บไว้ในแคช LRU ในเครื่องซึ่งจะจัดการให้คุณด้วย
- ปรับขนาดภาพต้นฉบับก่อนโหลดลงในหน่วยความจำ
- เรียกใช้ทั้งหมดข้างต้นในพูลเธรดที่จัดการโดย Picasso
- ใช้รูปภาพที่ปรับขนาดเพื่อเติม imageView ของคุณ
- ก่อนดำเนินการใดๆ ในอนาคต ให้ตรวจสอบแคชในเครื่องเพื่อให้แน่ใจว่าเครือข่ายไปกลับมีความจำเป็นจริงๆ
การสร้างชุดงานข้างต้นต้องใช้เวลาหลายชั่วโมง แม้กระทั่งสำหรับนักพัฒนาระดับมาสเตอร์ และนั่นถือว่าคุณจำทุกอย่างได้ เกิดอะไรขึ้นถ้าคุณลืมพูดว่าส่วนการปรับขนาด

บนอุปกรณ์ Android โดยเฉลี่ย แอปจะได้รับ RAM ไม่เกิน 50 ถึง 60 เมกะไบต์ และปัจจัยพิกเซลต่อไบต์สำหรับอุปกรณ์ Android ส่วนใหญ่คือ 4 ซึ่งหมายความว่าพยายามโหลดภาพขนาด 13 เมกะพิกเซลจากการ์ด SD ต้องการ RAM 52 เมกะไบต์ กล่าวคือ แอปของคุณจะหยุดทำงานทันที
นี่เป็นเพียงตัวอย่างหนึ่งของความแข็งแกร่งของปิกัสโซ สิ่งแรกที่ฉันทำเมื่อทำการเพิ่มประสิทธิภาพ/ดีบักโปรเจ็กต์ดั้งเดิมที่เน้นสื่อมากคือสลับการโหลดรูปภาพทั้งหมดเป็น Picasso คุณจะแปลกใจกับผลกระทบที่ขั้นตอนง่ายๆ นี้ส่งผลต่อคุณภาพของแอป
หนึ่งในข้อพิสูจน์ที่แข็งแกร่งที่สุดเกี่ยวกับพลังของห้องสมุดนี้: ตัวอย่างโค้ด Android จำนวนมากของ Google ในช่วงสองปีที่ผ่านมาใช้ Picasso ในการโหลดรูปภาพ
ActiveAndroid: โอเวอร์เฮดประสิทธิภาพ ORM Sans
ORM ย่อมาจากการทำแผนที่เชิงสัมพันธ์ของวัตถุ ได้รับความนิยมในสมัยของ J2EE ช่วยให้คุณสามารถจัดเก็บ POJO ของคุณและดึงข้อมูลจากฐานข้อมูลโดยไม่ต้องแปลงเป็นฟิลด์แยกต่างหาก
มันมีประโยชน์หรือไม่? อย่างมาก เนื่องจากช่วยให้คุณสามารถเขียนแอปส่วนใหญ่ได้โดยไม่ต้องเข้ารหัสคำสั่ง SQL
มันยังมีประสิทธิภาพมาก ในสมัยก่อน แพลตฟอร์ม ORM อาศัยการไตร่ตรองอย่างหนาแน่นและขึ้นชื่อว่าทำงานช้า แพลตฟอร์มสมัยใหม่ ซึ่งรวมถึง ActiveAndroid นั้นเร็วกว่ามากและสำหรับความต้องการในทางปฏิบัติส่วนใหญ่ จะไม่ได้รับผลกระทบจากโอเวอร์เฮดของประสิทธิภาพเหนือการเข้ารหัส SQL แบบดิบ
การใช้งาน:
ก. เริ่มต้นในวัตถุแอปพลิเคชันโดยขยายคลาสแอปพลิเคชันที่กำหนดเอง:
public class MyApplication extends extends com.activeandroid.app.Application { … }
ข. สร้าง POJO ซึ่งได้รับมาจากคลาสโมเดล โดยมีคลาสสำหรับแต่ละเร็กคอร์ดที่คุณวางแผนจะจัดเก็บไว้ในฐานข้อมูล แต่ละ POJO ดังกล่าวสามารถอยู่ในตารางของตนเองได้ ควรใช้คำอธิบายประกอบเพื่อระบุชื่อฟิลด์ DB สำหรับสมาชิกที่เก็บไว้แต่ละคน:
@Table(name = "Categories") public class UserDetails extends Model { @Column(name = "Name") public String name; @Column(name = "Address") public String address; @Column(name = "Age") public int age; }
หากคุณต้องการตั้งค่าดัชนีสำหรับสมาชิก ให้ใช้คำอธิบายประกอบต่อไปนี้:
@Column(name = "ID", index = true) public String userID;
ค. เพื่อป้องกันไม่ให้ไลบรารีวนซ้ำในช่วงเวลาเริ่มต้นที่คลาสสิกที่สุดของคุณ ซึ่งเป็นพฤติกรรมเริ่มต้น ขอแนะนำเป็นอย่างยิ่งให้คุณระบุคลาสโมเดลทั้งหมดของคุณในส่วนรายการต่อไปนี้:
<meta-data android:name="AA_MODELS" android:value=“com.myapp.MyModelA, com.myapp.MyModelB" />
หมายเหตุ: ActiveAndroid ไม่รู้จักคลาสโมเดลที่ไม่ปรากฏในรายการนี้
ง. เขียนไปยังฐานข้อมูล:
UserDetails usr = new UserDetails(); usr.save(); // RUNS ON A BACKGROUND THREAD
หากจำเป็นต้องเขียนหลายรายการ วิธีที่มีประสิทธิภาพมากขึ้นคือการจัดชุดงานในธุรกรรมเดียว:
ActiveAndroid.beginTransaction(); try { for (UserDetails u: userList) item.save(); ActiveAndroid.setTransactionSuccessful(); } finally { ActiveAndroid.endTransaction(); }
อี อ่าน POJO จากฐานข้อมูล:
new Select() .from(UserDetails.class) .where("name = ?", usr.getName()) .orderBy("Age") .executeSingle();
ORM เป็นเครื่องมือที่ต้องมีในสมัยของฉันในฐานะนักพัฒนาฝั่งเซิร์ฟเวอร์ มีการเข้าสู่โดเมน Android ค่อนข้างช้า แต่สุดท้ายนี้ก็คือ การเขียนโปรแกรมฐานข้อมูลแบบง่ายๆ สนุกกับมัน.
LibStreaming: การสตรีมวิดีโอที่ไม่เจ็บปวด
การสตรีมวิดีโอแบบเรียลไทม์เคยเป็นปัญหาใหญ่เนื่องจาก API ที่ไม่มีเอกสาร ความแตกต่างของเวอร์ชันข้าม SDK การใช้การสะท้อน และอื่นๆ
โชคดีที่ libStreaming ได้เปลี่ยนแปลงทั้งหมดนี้โดยการห่อหุ้มความซับซ้อนของการสตรีมส่วนใหญ่ และเปิดเผย API ที่เรียบง่ายและเป็นมิตร ซึ่งช่วยให้คุณเขียนแอปสตรีมมิ่งพื้นฐานได้ภายในเวลาไม่กี่ชั่วโมง
ในการใช้งานกับ H.264 และ AAC คุณต้องทำสิ่งต่อไปนี้:
ก. เริ่มต้นวัตถุเซสชันที่วิธีการ onCreate ของกิจกรรมหลักของคุณ ออบเจ็กต์เซสชันแสดงถึงการสตรีมสื่อไปยังเพียร์:
protected void onCreate(Bundle savedInstanceState) { mSession = SessionBuilder.getInstance() .setCallback(this) .setSurfaceView(mSurfaceView) .setPreviewOrientation(90) .setContext(getApplicationContext()) .setAudioEncoder(SessionBuilder.AUDIO_NONE) .setAudioQuality(new AudioQuality(16000, 32000)) .setVideoEncoder(SessionBuilder.VIDEO_H264) .setVideoQuality(new VideoQuality(320,240,20,500000)) .build(); mSurfaceView.getHolder().addCallback(this); }
ข. เริ่มเซสชันจริง:
mSession.setDestination(destination_server_url); mSession.start();
ค. หยุดเซสชันเมื่อเสร็จสิ้น:
mSession.stop();
ตอนนี้โปรดอย่าเข้าใจผิด การสตรีมแบบเรียลไทม์นั้นยุ่งเหยิงโดยธรรมชาติ และ libStreaming ก็ไม่ได้ขจัดความซับซ้อนนี้ออกไป อย่างไรก็ตาม การซ่อนมันจากคุณเกือบตลอดเวลานั้นทำได้ดีมาก ในบางกรณี คุณจะต้องจัดการกับความซับซ้อน เช่น เมื่อเลือกนโยบายการส่งสัญญาณจากเพื่อน เลือกการเข้ารหัสกล้อง (โดยปกติคุณต้องการใช้ MediaCodec/surface-to-buffer) หรือการจัดการกับแพ็กเก็ต
ถึงกระนั้น คุณจะพบว่าผู้ที่อยู่เบื้องหลัง libStreaming ได้ก้าวไปอีกขั้นในการผสานความซับซ้อนเหล่านี้เข้ากับ API ที่ใช้งานง่ายอย่างราบรื่น
LibStreaming รองรับตัวเข้ารหัสส่วนใหญ่ที่ใช้โดยแอพ Android รวมถึง H.264, H.263, AAC และ AMR
ฉันได้เก็บเกี่ยวผลลัพธ์ที่ยอดเยี่ยมด้วยห้องสมุดนี้ แอพสตรีมมิ่งยอดนิยมหลายตัวใช้มันเป็นส่วนหนึ่งของโครงสร้างพื้นฐาน หากคุณเคยเจอความต้องการนี้ ฉันแน่ใจว่ามันจะทำให้ประสบการณ์การสตรีมสื่อของคุณราบรื่นยิ่งขึ้น
LeakCanary: ตรวจจับการรั่วไหลของหน่วยความจำในบรรทัดของรหัส
เริ่มต้นด้วยแรงจูงใจเบื้องหลังไลบรารีนี้: หน่วยความจำรั่ว แอป Android มักใช้โดยเฉพาะอย่างยิ่งหากคุณไม่ระมัดระวังในการเขียนโค้ด อันที่จริง การสร้างหน่วยความจำรั่วนั้นง่ายมาก สิ่งที่คุณต้องทำคือจัดเก็บข้อมูลอ้างอิงกิจกรรมนอกบริบท ที่จริงแล้ว แม้แต่การจัดเก็บการอ้างอิงไปยังอ็อบเจ็กต์มุมมองเดียวนอกบริบทของกิจกรรมก็ทำให้เกิดการรั่วไหล
ทำไม? เนื่องจากมุมมอง—ที่จริงแล้วมุมมองทั้งหมด—จัดเก็บการอ้างอิงบริบทภายในไปยังกิจกรรมที่มีอยู่ ตราบใดที่มีการเก็บการอ้างอิงถึงมุมมอง กิจกรรมที่ประกอบด้วย—พร้อมกับสิ่งที่อยู่ภายใน รวมถึง drawables ลำดับชั้นของมุมมอง และทรัพยากร—ไม่สามารถเรียกคืนได้โดยตัวรวบรวมขยะ
การเก็บการอ้างอิงถึงกิจกรรมที่รั่วไหลนั้นไม่ชัดเจนเสมอไปว่าเป็นพารามิเตอร์คงที่ เมื่อใดก็ตามที่คุณสร้างคลาสภายในหรือสร้างเธรดภายในกิจกรรม การอ้างอิงถึงกิจกรรมนั้นจะถูกสร้างขึ้นและกิจกรรมนั้นจะไม่สามารถเรียกคืนได้จนกว่าคลาสภายในหรือเธรดนั้นจะเสร็จสมบูรณ์
การรั่วไหลของการอ้างอิงถึงกิจกรรมที่ใช้ทรัพยากรมากเพียงครั้งเดียวก็เพียงพอแล้วที่จะทำให้แอปของคุณขัดข้องโดยมีข้อยกเว้น " หน่วยความจำ ไม่เพียงพอ"
คุณจะป้องกันพวกเขาได้อย่างไร? เริ่มต้นด้วย หลักการเขียนโค้ดที่เข้มงวด แน่นอน แต่ไม่ใช่พวกเราทุกคนที่เป็นนักพัฒนา Android ที่มีประสบการณ์ และแม้แต่นักพัฒนาที่มีประสบการณ์บางครั้งก็ลืมกฎเกณฑ์ไป
การตรวจสอบโค้ดเป็นระยะโดยเน้นที่หน่วยความจำรั่วอาจช่วยได้ แต่ต้องใช้เวลา นอกจากนี้ การรั่วไหลบางส่วนยังเป็นการลับๆ ล่อๆ และยากต่อการตรวจจับโดยการตรวจสอบโค้ดเพียงอย่างเดียว
การใช้เครื่องมือหน่วยความจำของ DDMS เป็นวิธีที่ดีในการรู้ว่าแอปของคุณรั่วไหลเมื่อเวลาผ่านไปหรือไม่ คุณควรใช้มันอย่างแน่นอน อย่างไรก็ตาม มันจะไม่บอกคุณว่าอะไรเป็นสาเหตุของการรั่วไหล
ที่นี่มารั่วนกขมิ้นเพื่อช่วยเหลือ เป็นเครื่องตรวจจับการรั่วไหลของหน่วยความจำที่ดีที่สุด และให้การตรวจจับการรั่วไหล โดยอัตโนมัติ เช่นเดียวกับในโค้ดหนึ่งหรือสองบรรทัดสำหรับกิจกรรมทั้งหมดของคุณ
ในการใช้งานเพียงแค่เริ่มต้น leakCanary ด้วยออบเจ็กต์ของแอปของคุณ onCreate()
:
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); // more initialisations } }
และคุณทำเสร็จแล้ว LeakCanary จะตรวจสอบการรั่วไหลของหน่วยความจำ และส่งการแจ้งเตือนหากตรวจพบ
LeakCanary บรรลุเวทย์มนตร์นี้โดยการฉีดวัตถุที่เรียกว่า ActivityRefWatcher
ลงในกิจกรรมทั้งหมดของคุณโดยอัตโนมัติและติดตามจำนวนผู้อ้างอิงหลังจาก onDestroy()
การนับผู้อ้างอิง > 0 ในกิจกรรมที่ถูกทำลายอาจหมายถึงการรั่วไหลเท่านั้น
สำคัญ: การตรวจจับการรั่วใช้ได้กับแอปพลิเคชันโหมดแก้ไขข้อบกพร่องเท่านั้น อย่าทดสอบการรั่วไหล (ไม่ใช่กับ LeakCanary) ใน APK ของโหมดเผยแพร่
แต่ถ้าฉันต้องการทดสอบส่วนอื่นๆ ของระบบเพื่อหารอยรั่วล่ะ ที่นี่ LeakCanary เสนอวัตถุที่เรียกว่า refWatcher ซึ่งอันที่จริงแล้วเป็นค่าส่งคืนของการเรียกการเริ่มต้น:
refWatcher = LeakCanary.install(this);
สามารถใช้เพื่อดูค่าที่จะถูกเรียกคืนในไม่ช้า แม่นยำยิ่งขึ้น ค่าที่ฉันคิดว่าเร็ว ๆ นี้จะถูกเรียกคืน โทร:
refWatcher.watch(my_soon_to_be_reclaimed_obj);
ห้องสมุดจะแจ้งให้คุณทราบหากวัตถุนี้ยังไม่ถูกปล่อยออกมาภายในระยะเวลาสั้นๆ หลังจากการเรียกนาฬิกา
ฉันไม่สามารถหาค่าของ "เวลาอันสั้น" นี้ได้ที่ไหน แต่มันคงไม่สำคัญขนาดนั้น ด้วยการรั่วไหล Canary สิ่งต่าง ๆ ก็ใช้ได้ ไม่มีค่า
สรุป
นักพัฒนาที่มีประสบการณ์จะตัดขั้นตอนการเขียนโปรแกรมและดีบักเป็นเวลาหลายวันและหลายสัปดาห์โดยใช้ไลบรารีเหล่านี้ ดังนั้นจึงไม่มีเหตุผลที่คุณไม่สามารถทำแบบเดียวกันได้
โดยสรุป นี่คือสิ่งที่ห้องสมุด Android ที่ฉันเลือกไว้สามารถช่วยคุณได้:
ButterKnife – โค้ดที่ฉีดอัตโนมัติจะช่วยคุณกำจัดโค้ดต้นแบบของแอปส่วนใหญ่ เป็นการแทรกโค้ดขั้นสุดยอดสำหรับ Android ฉันจำเป็นต้องพูดมากกว่านี้ไหม
AndroidAnnotations – ใช้คลาสที่สร้างอัตโนมัติอย่างรวดเร็วและการฉีดโค้ดตามชื่อเพื่อประหยัดเวลาโดยไม่มีการปรับประสิทธิภาพเหนือตรรกะที่เข้ารหัสด้วยมือ
EventBus – แยกส่วนประกอบสำหรับรหัสที่แข็งแกร่งยิ่งขึ้น การสื่อสารข้ามองค์ประกอบไม่เคยง่ายไปกว่านี้มาก่อน
OkHttp – การแทนที่อย่างชาญฉลาดสำหรับ HttpURLConnection ด้วยการสนับสนุนเครือข่ายแบบอะซิงโครนัส ขอการสืบค้นเส้นทางการเปลี่ยนเส้นทาง การสืบค้นแคชในเครื่อง และอื่นๆ
Picasso – การจัดการรูปภาพที่คล่องตัวซึ่งดีมากจน Google ใช้แล้ว เป็นการประหยัดเวลาที่สำคัญในโครงการหนักด้านสื่อและโครงการเดิมบางโครงการ
ActiveAndroid – ORM ทำได้ง่ายโดยไม่มีค่าใช้จ่ายด้านประสิทธิภาพ
LibStreaming – การสตรีมวิดีโอแบบเรียลไทม์ ใช้โดยแอพสตรีมมิ่งหลักๆ
นี่เป็นห้องสมุด Android เพียงแห่งเดียวที่คุ้มค่ากับเวลาของคุณหรือไม่? ไม่แน่นอน แต่ฉันสัญญากับคุณว่า: การใช้สิ่งเหล่านี้ในโครงการต่อไปของคุณจะทำให้คุณเป็นนักพัฒนาที่ดีขึ้นมาก หากคุณต้องการเห็นพวกเขาใช้งานจริง ดูที่ GitHub ของฉัน
หากคุณใช้บางส่วนหรือทั้งหมดอยู่แล้ว หรือหากคุณกำลังใช้ห้องสมุดทางเลือก เราขอแนะนำให้คุณแบ่งปันประสบการณ์ของคุณในความคิดเห็นด้านล่าง