อุปกรณ์ Android มีแกนจำนวนมากดังนั้นการเขียนแอปที่ราบรื่นจึงเป็นเรื่องง่ายสำหรับทุกคนใช่ไหม ไม่ถูกต้อง. เนื่องจากทุกอย่างบน Android สามารถทำได้หลายวิธีการเลือกตัวเลือกที่ดีที่สุดอาจเป็นเรื่องยาก หากคุณต้องการเลือกวิธีที่มีประสิทธิภาพสูงสุดคุณต้องรู้ว่าเกิดอะไรขึ้นภายใต้ประทุน โชคดีที่คุณไม่จำเป็นต้องพึ่งพาความรู้สึกหรือการรับรู้กลิ่นเนื่องจากมีเครื่องมือมากมายที่ช่วยให้คุณพบปัญหาคอขวดโดยการวัดและอธิบายสิ่งที่เกิดขึ้น แอพที่ได้รับการปรับแต่งอย่างเหมาะสมและราบรื่นช่วยปรับปรุงประสบการณ์ของผู้ใช้อย่างมากและยังใช้พลังงานแบตเตอรี่น้อยลงอีกด้วย
มาดูตัวเลขก่อนเพื่อพิจารณาว่าการเพิ่มประสิทธิภาพมีความสำคัญเพียงใด ตามก โพสต์ Nimbledroid ผู้ใช้ 86% (รวมถึงฉัน) ได้ถอนการติดตั้งแอปหลังจากใช้เพียงครั้งเดียวเนื่องจากประสิทธิภาพไม่ดี หากคุณกำลังโหลดเนื้อหาบางส่วนคุณมีเวลาน้อยกว่า 11 วินาทีในการแสดงให้ผู้ใช้เห็น ผู้ใช้ทุกคนที่สามเท่านั้นที่จะให้เวลาคุณมากขึ้น นอกจากนี้คุณอาจได้รับบทวิจารณ์ที่ไม่ดีมากมายบน Google Play ด้วยเหตุนี้
สิ่งแรกที่ผู้ใช้ทุกคนสังเกตเห็นซ้ำแล้วซ้ำอีกคือเวลาเริ่มต้นของแอป ตาม อีกโพสต์ Nimbledroid , จาก 100 แอพอันดับต้น ๆ , 40 แอพเริ่มต้นภายใน 2 วินาทีและ 70 แอพเริ่มต้นภายใน 3 วินาที ดังนั้นหากเป็นไปได้โดยทั่วไปคุณควรแสดงเนื้อหาบางส่วนโดยเร็วที่สุดและชะลอการตรวจสอบพื้นหลังและอัปเดตเล็กน้อย
จำไว้เสมอว่าการเพิ่มประสิทธิภาพก่อนเวลาอันควรเป็นรากเหง้าของความชั่วร้ายทั้งหมด คุณไม่ควรเสียเวลามากเกินไปกับการเพิ่มประสิทธิภาพไมโคร คุณจะเห็นประโยชน์สูงสุดของการเพิ่มประสิทธิภาพโค้ดที่ทำงานบ่อยครั้ง ตัวอย่างเช่นซึ่งรวมถึง onDraw()
ฟังก์ชันซึ่งทำงานทุกเฟรมตามอุดมคติ 60 ครั้งต่อวินาที การวาดภาพเป็นการดำเนินการที่ช้าที่สุดดังนั้นลองวาดใหม่เฉพาะสิ่งที่คุณต้องทำ ข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้จะมาในภายหลัง
ทฤษฎีเพียงพอนี่คือรายการบางสิ่งที่คุณควรพิจารณาหากประสิทธิภาพมีความสำคัญกับคุณ
สมมติว่าคุณมี String และด้วยเหตุผลบางอย่างคุณต้องการต่อท้าย Strings มากกว่า 10,000 ครั้ง โค้ดอาจมีลักษณะดังนี้
String string = 'hello'; for (int i = 0; i <10000; i++) { string += ' world'; }
คุณสามารถดูได้ใน Android Studio Monitors ว่าการต่อสายอักขระบางตัวไม่มีประสิทธิภาพเพียงใด มี Garbage Collections (GC) มากมายเกิดขึ้น
การดำเนินการนี้ใช้เวลาประมาณ 8 วินาทีบนอุปกรณ์ที่ค่อนข้างดีของฉันซึ่งมี Android 5.1.1 วิธีที่มีประสิทธิภาพมากขึ้นในการบรรลุเป้าหมายเดียวกันคือการใช้ StringBuilder เช่นนี้
StringBuilder sb = new StringBuilder('hello'); for (int i = 0; i <10000; i++) { sb.append(' world'); } String string = sb.toString();
บนอุปกรณ์เดียวกันสิ่งนี้เกิดขึ้นเกือบจะในทันทีโดยใช้เวลาน้อยกว่า 5 มิลลิวินาที การแสดงภาพของ CPU และหน่วยความจำแทบจะแบนราบทั้งหมดดังนั้นคุณสามารถจินตนาการได้ว่าการปรับปรุงนี้ใหญ่แค่ไหน โปรดสังเกตว่าเพื่อให้บรรลุความแตกต่างนี้เราต้องต่อท้าย 10,000 สตริงซึ่งคุณอาจไม่ได้ทำบ่อยๆ ดังนั้นในกรณีที่คุณเพิ่มสตริงเพียงสองสามครั้งคุณจะไม่เห็นการปรับปรุงใด ๆ อย่างไรก็ตามหากคุณทำ:
String string = 'hello' + ' world';
ได้รับการแปลงภายในเป็น StringBuilder ดังนั้นจึงทำงานได้ดี
คุณอาจสงสัยว่าเหตุใดการเชื่อมสตริงเข้าด้วยกันจึงช้ามาก? มันเกิดจากข้อเท็จจริงที่ว่าสตริงไม่เปลี่ยนรูปดังนั้นเมื่อสร้างแล้วจะไม่สามารถเปลี่ยนแปลงได้ แม้ว่าคุณจะคิดว่าคุณกำลังเปลี่ยนค่าของ String แต่คุณกำลังสร้าง String ใหม่ด้วยค่าใหม่ ในตัวอย่างเช่น:
String myString = 'hello'; myString += ' world';
สิ่งที่คุณจะได้รับในหน่วยความจำไม่ใช่ 1 String“ hello world” แต่จริงๆแล้ว 2 Strings String myString จะมีคำว่า“ hello world” ตามที่คุณคาดหวัง อย่างไรก็ตามสตริงดั้งเดิมที่มีค่า“ สวัสดี” ยังมีชีวิตอยู่โดยไม่มีการอ้างอิงใด ๆ เพื่อรอการเก็บรวบรวมขยะ นี่คือเหตุผลที่คุณควรจัดเก็บรหัสผ่านไว้ในอาร์เรย์ถ่านแทนสตริง หากคุณจัดเก็บรหัสผ่านเป็น String รหัสผ่านจะยังคงอยู่ในหน่วยความจำในรูปแบบที่มนุษย์อ่านได้จนถึง GC ถัดไปสำหรับระยะเวลาที่คาดเดาไม่ได้ กลับไปที่ความไม่เปลี่ยนรูปที่อธิบายไว้ข้างต้น String จะยังคงอยู่ในหน่วยความจำแม้ว่าคุณจะกำหนดค่าอื่นหลังจากใช้งานแล้วก็ตาม อย่างไรก็ตามหากคุณล้างอาร์เรย์ถ่านหลังจากใช้รหัสผ่านรหัสผ่านจะหายไปจากทุกที่
ก่อนที่คุณจะเริ่มเขียนโค้ดคุณควรตัดสินใจว่าคุณจะใช้ข้อมูลประเภทใดสำหรับคอลเลกชันของคุณ ตัวอย่างเช่นคุณควรใช้ Vector
หรือ ArrayList
? ขึ้นอยู่กับลักษณะการใช้งานของคุณ หากคุณต้องการคอลเลกชันที่ปลอดภัยต่อเธรดซึ่งจะอนุญาตให้ใช้เธรดเดียวพร้อมกันได้คุณควรเลือก Vector
เนื่องจากมีการซิงโครไนซ์แล้ว ในกรณีอื่น ๆ คุณควรยึดตาม ArrayList
เว้นแต่คุณจะมีเหตุผลเฉพาะเจาะจงในการใช้เวกเตอร์
แล้วกรณีที่คุณต้องการคอลเลกชันที่มีวัตถุที่ไม่เหมือนใครล่ะ? คุณควรเลือก Set
ไม่สามารถมีรายการที่ซ้ำกันตามการออกแบบดังนั้นคุณจะไม่ต้องดูแลมันด้วยตัวเอง มีชุดหลายประเภทดังนั้นให้เลือกชุดที่เหมาะกับกรณีการใช้งานของคุณ สำหรับกลุ่มไอเท็มที่ไม่ซ้ำใครง่ายๆคุณสามารถใช้ HashSet
หากคุณต้องการรักษาลำดับของรายการที่แทรกไว้ให้เลือก LinkedHashSet
ก TreeSet
จัดเรียงรายการโดยอัตโนมัติดังนั้นคุณจะไม่ต้องเรียกใช้วิธีการเรียงลำดับใด ๆ นอกจากนี้ยังควรจัดเรียงรายการอย่างมีประสิทธิภาพโดยที่คุณไม่ต้องคิด อัลกอริทึมการเรียงลำดับ .
การเรียงลำดับจำนวนเต็มหรือสตริงค่อนข้างตรงไปตรงมา อย่างไรก็ตามหากคุณต้องการจัดเรียงชั้นเรียนตามคุณสมบัติบางอย่าง? สมมติว่าคุณกำลังเขียนรายการอาหารที่คุณกินและเก็บชื่อและการประทับเวลาไว้ คุณจะเรียงลำดับมื้ออาหารตามการประทับเวลาจากต่ำสุดไปสูงสุดอย่างไร โชคดีที่มันค่อนข้างเรียบง่าย การติดตั้ง Comparable
ก็เพียงพอแล้ว อินเทอร์เฟซใน Meal
คลาสและแทนที่ compareTo()
ฟังก์ชัน ในการเรียงลำดับมื้ออาหารตามการประทับเวลาต่ำสุดไปสูงสุดเราสามารถเขียนอะไรแบบนี้ได้
@Override public int compareTo(Object object) { Meal meal = (Meal) object; if (this.timestamp meal.getTimestamp()) { return 1; } return 0; }
มีแอปมากมายที่รวบรวมตำแหน่งของผู้ใช้ คุณควรใช้ Google Location Services API เพื่อจุดประสงค์นั้นซึ่งมีฟังก์ชันที่มีประโยชน์มากมาย มี บทความแยกต่างหาก เกี่ยวกับการใช้งานดังนั้นฉันจะไม่พูดซ้ำ
ฉันแค่อยากเน้นประเด็นสำคัญบางอย่างจากมุมมองด้านประสิทธิภาพ
ก่อนอื่นให้ใช้เฉพาะตำแหน่งที่แม่นยำที่สุดเท่าที่คุณต้องการ ตัวอย่างเช่นหากคุณกำลังทำการพยากรณ์อากาศคุณไม่จำเป็นต้องมีตำแหน่งที่แม่นยำที่สุด การรับพื้นที่คร่าวๆตามเครือข่ายนั้นเร็วกว่าและประหยัดแบตเตอรี่มากขึ้น คุณสามารถบรรลุได้โดยตั้งค่าลำดับความสำคัญเป็น LocationRequest.PRIORITY_LOW_POWER
คุณยังสามารถใช้ฟังก์ชันของ LocationRequest
เรียกว่า setSmallestDisplacement()
. การตั้งค่านี้เป็นเมตรจะทำให้แอปของคุณไม่ได้รับแจ้งเกี่ยวกับการเปลี่ยนแปลงตำแหน่งหากมีขนาดเล็กกว่าค่าที่กำหนด ตัวอย่างเช่นหากคุณมีแผนที่ที่มีร้านอาหารใกล้เคียงอยู่รอบ ๆ ตัวคุณและคุณตั้งค่าการกระจัดที่เล็กที่สุดเป็น 20 เมตรแอปจะไม่ร้องขอให้ตรวจสอบร้านอาหารหากผู้ใช้กำลังเดินไปมาในห้อง คำขอจะไร้ผลเนื่องจากจะไม่มีร้านอาหารใหม่ในบริเวณใกล้เคียง
กฎข้อที่สองขอให้อัปเดตตำแหน่งบ่อยเท่าที่คุณต้องการเท่านั้น นี่ค่อนข้างอธิบายตัวเองได้ หากคุณกำลังสร้างแอปพยากรณ์อากาศนั้นจริงๆคุณไม่จำเป็นต้องขอตำแหน่งทุกๆสองสามวินาทีเนื่องจากคุณอาจไม่มีการคาดการณ์ที่แม่นยำเช่นนี้ (โปรดติดต่อฉันหากคุณต้องการ) คุณสามารถใช้ setInterval()
ฟังก์ชันสำหรับตั้งค่าช่วงเวลาที่ต้องการซึ่งอุปกรณ์จะอัปเดตแอปของคุณเกี่ยวกับตำแหน่ง หากหลายแอปยังคงขอตำแหน่งของผู้ใช้ทุกแอปจะได้รับการแจ้งเตือนเมื่ออัปเดตตำแหน่งใหม่ทุกครั้งแม้ว่าคุณจะมี setInterval()
ที่สูงกว่าก็ตาม ชุด. เพื่อป้องกันไม่ให้แอปของคุณได้รับการแจ้งเตือนบ่อยเกินไปตรวจสอบให้แน่ใจว่าได้กำหนดช่วงเวลาการอัปเดตที่เร็วที่สุดด้วย setFastestInterval()
และสุดท้ายกฎข้อที่สามคือการขอการอัปเดตตำแหน่งเฉพาะเมื่อคุณต้องการ หากคุณแสดงวัตถุใกล้เคียงบนแผนที่ทุก ๆ x วินาทีและแอปทำงานเป็นพื้นหลังคุณไม่จำเป็นต้องทราบตำแหน่งใหม่ ไม่มีเหตุผลที่จะอัปเดตแผนที่หากผู้ใช้ไม่สามารถมองเห็นได้ อย่าลืมหยุดฟังการอัปเดตตำแหน่งตามความเหมาะสมโดยเฉพาะใน onPause()
จากนั้นคุณสามารถดำเนินการอัปเดตต่อได้ใน onResume()
มีโอกาสสูงที่แอปของคุณกำลังใช้อินเทอร์เน็ตเพื่อดาวน์โหลดหรืออัปโหลดข้อมูล หากเป็นเช่นนั้นคุณมีเหตุผลหลายประการที่ต้องใส่ใจ การจัดการคำขอเครือข่าย . หนึ่งในนั้นคือข้อมูลมือถือซึ่ง จำกัด ไว้สำหรับผู้คนจำนวนมากและคุณไม่ควรเสียไป
อันที่สองคือแบตเตอรี่ ทั้ง WiFi และเครือข่ายมือถือสามารถใช้งานได้ค่อนข้างมากหากใช้มากเกินไป สมมติว่าคุณต้องการดาวน์โหลด 1 kb หากต้องการขอเครือข่ายคุณต้องปลุกวิทยุเซลลูลาร์หรือ WiFi จากนั้นจึงดาวน์โหลดข้อมูลได้ อย่างไรก็ตามวิทยุจะไม่หลับทันทีหลังการใช้งาน มันจะอยู่ในสถานะใช้งานได้อีกประมาณ 20-40 วินาทีขึ้นอยู่กับอุปกรณ์และผู้ให้บริการของคุณ
แล้วคุณจะทำอะไรได้บ้าง? แบทช์ เพื่อหลีกเลี่ยงการปลุกวิทยุทุกๆสองสามวินาทีให้ดึงสิ่งที่ผู้ใช้อาจต้องการไว้ล่วงหน้าในนาทีที่กำลังจะมาถึง วิธีการจัดกลุ่มที่เหมาะสมนั้นมีไดนามิกสูงขึ้นอยู่กับแอปของคุณ แต่ถ้าเป็นไปได้คุณควรดาวน์โหลดข้อมูลที่ผู้ใช้อาจต้องการในอีก 3-4 นาทีถัดไป นอกจากนี้ยังสามารถแก้ไขพารามิเตอร์แบทช์ตามประเภทอินเทอร์เน็ตของผู้ใช้หรือสถานะการชาร์จ ตัวอย่างเช่นหากผู้ใช้ใช้ WiFi ขณะชาร์จคุณสามารถดึงข้อมูลล่วงหน้าได้มากกว่าหากผู้ใช้ใช้อินเทอร์เน็ตบนมือถือโดยใช้แบตเตอรี่ต่ำ การพิจารณาตัวแปรเหล่านี้ทั้งหมดอาจเป็นเรื่องยากซึ่งมีเพียงไม่กี่คนที่จะทำได้ โชคดีที่มี GCM Network Manager คอยช่วยเหลือ!
GCM Network Manager เป็นคลาสที่มีประโยชน์มากพร้อมคุณสมบัติที่ปรับแต่งได้มากมาย คุณสามารถกำหนดเวลาได้ทั้งงานที่ทำซ้ำและงานครั้งเดียว ในงานที่ทำซ้ำคุณสามารถตั้งค่าต่ำสุดและช่วงเวลาการทำซ้ำสูงสุดได้ สิ่งนี้จะช่วยให้สามารถจัดกลุ่มได้ไม่เพียง แต่คำขอของคุณเท่านั้น แต่ยังรวมถึงคำขอจากแอปอื่น ๆ ด้วย วิทยุจะต้องปลุกเพียงครั้งเดียวต่อบางช่วงเวลาและในขณะเปิดเครื่องแอปทั้งหมดในคิวจะดาวน์โหลดและอัปโหลดสิ่งที่ควรจะทำ ผู้จัดการรายนี้ยังทราบถึงประเภทเครือข่ายและสถานะการชาร์จของอุปกรณ์ดังนั้นคุณจึงสามารถปรับเปลี่ยนได้ คุณสามารถดูรายละเอียดและตัวอย่างเพิ่มเติมได้ใน บทความนี้ ฉันขอให้คุณตรวจสอบ งานตัวอย่างมีลักษณะดังนี้:
Task task = new OneoffTask.Builder() .setService(CustomService.class) .setExecutionWindow(0, 30) .setTag(LogService.TAG_TASK_ONEOFF_LOG) .setUpdateCurrent(false) .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED) .setRequiresCharging(false) .build();
อย่างไรก็ตามตั้งแต่ Android 3.0 หากคุณส่งคำขอเครือข่ายในเธรดหลักคุณจะได้รับ NetworkOnMainThreadException
แน่นอนว่าจะเตือนคุณว่าอย่าทำแบบนั้นอีก
การสะท้อนกลับคือความสามารถของคลาสและอ็อบเจ็กต์ในการตรวจสอบตัวสร้างฟิลด์วิธีการและอื่น ๆ ของตนเอง โดยปกติจะใช้สำหรับความเข้ากันได้แบบย้อนหลังเพื่อตรวจสอบว่ามีวิธีการที่กำหนดสำหรับ OS เวอร์ชันใดรุ่นหนึ่งหรือไม่ หากคุณต้องใช้การสะท้อนเพื่อจุดประสงค์นั้นตรวจสอบให้แน่ใจว่าได้แคชการตอบสนองเนื่องจากการใช้การสะท้อนค่อนข้างช้า ไลบรารีที่ใช้กันอย่างแพร่หลายบางแห่งใช้ Reflection เช่นกันเช่น Roboguice สำหรับการฉีดแบบพึ่งพา นั่นคือเหตุผลที่คุณควรชอบ Dagger 2 สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการสะท้อนคุณสามารถตรวจสอบ โพสต์แยกต่างหาก .
วิธีจัดการบอทที่ไม่ลงรอยกัน
การทำกล่องอัตโนมัติและการแกะกล่องเป็นกระบวนการในการแปลงประเภทดั้งเดิมเป็นประเภทวัตถุหรือในทางกลับกัน ในทางปฏิบัติหมายถึงการแปลง int เป็นจำนวนเต็ม เพื่อให้บรรลุนั้นคอมไพเลอร์ใช้ Integer.valueOf()
ทำงานภายใน การแปลงไม่เพียง แต่ช้า แต่ Objects ยังใช้หน่วยความจำมากกว่าเดิมอีกด้วย มาดูโค้ดกัน
Integer total = 0; for (int i = 0; i <1000000; i++) { total += i; }
แม้ว่าจะใช้เวลาโดยเฉลี่ย 500 มิลลิวินาที แต่การเขียนใหม่เพื่อหลีกเลี่ยงการบ็อกซ์อัตโนมัติจะทำให้เร็วขึ้นอย่างมาก
int total = 0; for (int i = 0; i <1000000; i++) { total += i; }
โซลูชันนี้ทำงานด้วยความเร็วประมาณ 2ms ซึ่งเร็วกว่า 25 เท่า ถ้าคุณไม่เชื่อฉันลองทดสอบดูสิ ตัวเลขจะแตกต่างกันอย่างเห็นได้ชัดในแต่ละอุปกรณ์ แต่ก็น่าจะเร็วกว่ามาก และยังเป็นขั้นตอนง่ายๆในการเพิ่มประสิทธิภาพอีกด้วย
โอเคคุณคงไม่ได้สร้างตัวแปรประเภท Integer บ่อยนัก แต่แล้วกรณีที่หลีกเลี่ยงได้ยากกว่าล่ะ? เช่นเดียวกับในแผนที่ที่คุณต้องใช้ Objects เช่น Map
? ดูวิธีแก้ปัญหาที่หลายคนใช้
Map myMap = new HashMap(); for (int i = 0; i <100000; i++) { myMap.put(i, random.nextInt()); }
การแทรก ints แบบสุ่ม 100k ในแผนที่จะใช้เวลาประมาณ 250ms ในการรัน ตอนนี้ดูวิธีแก้ปัญหาด้วย SparseIntArray
SparseIntArray myArray = new SparseIntArray(); for (int i = 0; i <100000; i++) { myArray.put(i, random.nextInt()); }
ใช้เวลาน้อยกว่ามากประมาณ 50ms นอกจากนี้ยังเป็นหนึ่งในวิธีการที่ง่ายกว่าในการปรับปรุงประสิทธิภาพโดยไม่ต้องทำอะไรซับซ้อนและยังอ่านโค้ดได้อีกด้วย ในขณะที่เรียกใช้แอปที่ชัดเจนด้วยโซลูชันแรกใช้หน่วยความจำของฉัน 13MB การใช้ ints ดั้งเดิมทำให้บางอย่างต่ำกว่า 7MB ดังนั้นแค่ครึ่งเดียว
SparseIntArray เป็นเพียงหนึ่งในคอลเลกชั่นเด็ด ๆ ที่สามารถช่วยคุณหลีกเลี่ยงการล็อกอัตโนมัติ แผนที่เช่น Map
อาจถูกแทนที่ด้วย SparseLongArray
เนื่องจากค่าของแผนที่เป็นประเภท Long
หากคุณดูที่ไฟล์ รหัสแหล่งที่มา จาก SparseLongArray
คุณจะเห็นบางสิ่งที่น่าสนใจ ภายใต้ฝากระโปรงนั้นเป็นเพียงอาร์เรย์คู่หนึ่ง คุณยังสามารถใช้ SparseBooleanArray
ในทำนองเดียวกัน
หากคุณอ่านซอร์สโค้ดคุณอาจสังเกตเห็นข้อความที่ระบุว่า SparseIntArray
อาจช้ากว่า HashMap
. ฉันทดลองมามาก แต่สำหรับฉัน SparseIntArray
ดีกว่าเสมอทั้งความจำและประสิทธิภาพที่ชาญฉลาด ฉันเดาว่ายังคงขึ้นอยู่กับคุณว่าคุณจะเลือกแบบใดทดลองกับกรณีการใช้งานของคุณและดูว่าแบบใดที่เหมาะกับคุณมากที่สุด มี SparseArrays
ในหัวของคุณเมื่อใช้แผนที่
ดังที่ฉันได้กล่าวไว้ข้างต้นเมื่อคุณเพิ่มประสิทธิภาพคุณอาจเห็นประโยชน์สูงสุดในการเพิ่มประสิทธิภาพโค้ดซึ่งทำงานบ่อย หนึ่งในฟังก์ชันที่ทำงานบ่อยมากคือ onDraw()
อาจไม่แปลกใจที่คุณมีหน้าที่วาดมุมมองบนหน้าจอ เนื่องจากอุปกรณ์มักจะทำงานที่ 60 fps ฟังก์ชันจะทำงาน 60 ครั้งต่อวินาที ทุกเฟรมมีเวลา 16 ms ที่ต้องจัดการอย่างเต็มที่รวมถึงการจัดเตรียมและการวาดภาพดังนั้นคุณควรหลีกเลี่ยงฟังก์ชันที่ช้า เฉพาะเธรดหลักเท่านั้นที่สามารถวาดบนหน้าจอได้ดังนั้นคุณควรหลีกเลี่ยงการดำเนินการที่มีราคาแพงกับมัน หากคุณตรึงเธรดหลักเป็นเวลาหลายวินาทีคุณอาจได้รับกล่องโต้ตอบ Application Not Responding (ANR) ที่น่าอับอาย สำหรับการปรับขนาดรูปภาพงานฐานข้อมูล ฯลฯ ให้ใช้เธรดพื้นหลัง
ฉันเคยเห็นบางคนพยายามย่อโค้ดโดยคิดว่าวิธีนั้นจะมีประสิทธิภาพมากกว่า นั่นไม่ใช่วิธีที่จะไปได้อย่างแน่นอนเนื่องจากโค้ดที่สั้นกว่าไม่ได้หมายถึงโค้ดที่เร็วกว่า คุณไม่ควรวัดคุณภาพของโค้ดด้วยจำนวนบรรทัดไม่ว่าในกรณีใด
สิ่งหนึ่งที่คุณควรหลีกเลี่ยงใน onDraw()
กำลังจัดสรรวัตถุเช่น Paint เตรียมทุกอย่างในตัวสร้างเพื่อให้พร้อมเมื่อวาดภาพ แม้ว่าคุณจะมี onDraw()
ปรับให้เหมาะสมคุณควรเรียกใช้บ่อยเท่าที่คุณต้องการ จะมีอะไรดีไปกว่าการเรียกใช้ฟังก์ชันที่ปรับให้เหมาะสม ดีไม่เรียกใช้ฟังก์ชันใด ๆ เลย ในกรณีที่คุณต้องการวาดข้อความมีฟังก์ชั่นตัวช่วยที่ค่อนข้างเรียบร้อยชื่อว่า drawText()
ซึ่งคุณสามารถระบุสิ่งต่างๆเช่นข้อความพิกัดและสีของข้อความ
คุณคงรู้เรื่องนี้ แต่ฉันไม่สามารถข้ามไปได้ รูปแบบการออกแบบ Viewholder เป็นวิธีที่ทำให้การเลื่อนรายการราบรื่นขึ้น เป็นการแคชมุมมองชนิดหนึ่งซึ่งสามารถลดการเรียกไปที่ findViewById()
ได้อย่างจริงจัง และเพิ่มมุมมองด้วยการจัดเก็บ มันจะมีลักษณะเช่นนี้
static class ViewHolder { TextView title; TextView text; public ViewHolder(View view) { title = (TextView) view.findViewById(R.id.title); text = (TextView) view.findViewById(R.id.text); } }
จากนั้นภายใน getView()
ฟังก์ชั่นของอะแดปเตอร์ของคุณคุณสามารถตรวจสอบว่าคุณมีมุมมองที่ใช้งานได้หรือไม่ ถ้าไม่คุณสร้างขึ้นมา
ViewHolder viewHolder; if (convertView == null) { convertView = inflater.inflate(R.layout.list_item, viewGroup, false); viewHolder = new ViewHolder(convertView); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.title.setText('Hello World');
คุณสามารถค้นหาข้อมูลที่เป็นประโยชน์มากมายเกี่ยวกับรูปแบบนี้ได้จากอินเทอร์เน็ต นอกจากนี้ยังสามารถใช้ในกรณีที่มุมมองรายการของคุณมีองค์ประกอบหลายประเภทอยู่ในนั้นเช่นส่วนหัวบางส่วน
มีโอกาสที่แอปของคุณจะมีรูปภาพบางส่วน ในกรณีที่คุณดาวน์โหลด JPG บางส่วนจากเว็บอาจมีความละเอียดสูงมาก อย่างไรก็ตามอุปกรณ์ที่จะแสดงจะมีขนาดเล็กลงมาก แม้ว่าคุณจะถ่ายภาพด้วยกล้องของอุปกรณ์ของคุณ แต่ก็ต้องลดขนาดลงก่อนที่จะแสดงเนื่องจากความละเอียดของภาพถ่ายนั้นใหญ่กว่าความละเอียดของจอแสดงผลมาก การปรับขนาดภาพก่อนที่จะแสดงเป็นสิ่งสำคัญ หากคุณลองแสดงผลแบบเต็มความละเอียดหน่วยความจำก็จะหมดลงอย่างรวดเร็ว ที่นั่น เป็นจำนวนมากที่เขียนเกี่ยวกับการแสดงบิตแมปอย่างมีประสิทธิภาพในเอกสาร Android ฉันจะพยายามสรุปให้ได้
คุณจึงมีบิตแมป แต่คุณไม่รู้อะไรเลย มีการตั้งค่าสถานะที่เป็นประโยชน์ของ Bitmaps ที่เรียกว่า inJustDecodeBounds ที่บริการของคุณซึ่งช่วยให้คุณค้นหาความละเอียดของบิตแมปได้ สมมติว่าบิตแมปของคุณคือ 1024x768 และ ImageView ที่ใช้แสดงมีขนาดเพียง 400x300 คุณควรหารความละเอียดของบิตแมปด้วย 2 ไปเรื่อย ๆ จนกว่าจะยังใหญ่กว่า ImageView ที่กำหนด ถ้าคุณทำมันจะลดขนาดบิตแมปลงด้วยปัจจัย 2 ทำให้คุณมีบิตแมป 512x384 บิตแมปแบบลดขนาดใช้หน่วยความจำน้อยลง 4 เท่าซึ่งจะช่วยคุณได้มากในการหลีกเลี่ยงข้อผิดพลาด OutOfMemory ที่มีชื่อเสียง
ตอนนี้คุณรู้วิธีทำแล้วคุณไม่ควรทำ …อย่างน้อยก็ไม่ใช่ว่าแอปของคุณต้องใช้รูปภาพเป็นหลักและไม่ใช่แค่ 1-2 ภาพ หลีกเลี่ยงสิ่งต่างๆเช่นการปรับขนาดและการรีไซเคิลภาพด้วยตนเองอย่างแน่นอนใช้ไลบรารีของบุคคลที่สามเพื่อสิ่งนั้น คนที่นิยมมากที่สุดคือ ปิกัสโซ โดย Square Universal Image Loader , เย็น โดย Facebook หรือรายการโปรดของฉัน ร่อน . มีชุมชนนักพัฒนาที่กระตือรือร้นอยู่รอบ ๆ ดังนั้นคุณสามารถค้นหาผู้คนมากมายที่เป็นประโยชน์ได้ที่หัวข้อปัญหาใน GitHub เช่นกัน
Strict Mode เป็นเครื่องมือที่มีประโยชน์สำหรับนักพัฒนาซอฟต์แวร์ที่หลายคนไม่รู้จัก โดยปกติจะใช้สำหรับตรวจจับคำขอเครือข่ายหรือการเข้าถึงดิสก์จากเธรดหลัก คุณสามารถตั้งค่าอะไร ประเด็น โหมดเข้มงวดควรมองหาและสิ่งที่ควรทำให้เกิดโทษ ตัวอย่างของ Google มีลักษณะดังนี้:
public void onCreate() { if (DEVELOPER_MODE) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .detectNetwork() .penaltyLog() .build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects() .detectLeakedClosableObjects() .penaltyLog() .penaltyDeath() .build()); } super.onCreate(); }
หากคุณต้องการตรวจหาทุกปัญหาในโหมดเข้มงวดคุณสามารถใช้ detectAll()
เช่นเดียวกับเคล็ดลับประสิทธิภาพมากมายคุณไม่ควรพยายามแก้ไขรายงานทุกอย่างในโหมดเข้มงวดโดยสุ่มสี่สุ่มห้า เพียงตรวจสอบและหากแน่ใจว่าไม่ใช่ปัญหาก็ปล่อยไว้เฉยๆ ตรวจสอบให้แน่ใจว่าใช้โหมดเข้มงวดสำหรับการดีบักเท่านั้นและปิดใช้งานในรุ่นที่ใช้งานจริงเสมอ
ตอนนี้เรามาดูเครื่องมือบางอย่างที่สามารถช่วยคุณค้นหาปัญหาคอขวดหรืออย่างน้อยก็แสดงว่ามีบางอย่างผิดปกติ
นี่คือเครื่องมือที่มีอยู่ใน Android Studio ตามค่าเริ่มต้นคุณจะพบ Android Monitor ที่มุมล่างซ้ายและสลับไปมาระหว่าง 2 แท็บได้ที่นั่น Logcat และจอภาพ ส่วนจอภาพประกอบด้วยกราฟ 4 แบบ เครือข่าย CPU GPU และหน่วยความจำ พวกเขาค่อนข้างอธิบายตัวเองได้ดีดังนั้นฉันจะรีบผ่านมันไป นี่คือภาพหน้าจอของกราฟที่ถ่ายขณะแยกวิเคราะห์ JSON บางส่วนเมื่อดาวน์โหลด
ส่วนเครือข่ายจะแสดงการรับส่งข้อมูลขาเข้าและขาออกในหน่วย KB / s ส่วนของ CPU จะแสดงการใช้งาน CPU เป็นเปอร์เซ็นต์ จอภาพ GPU จะแสดงระยะเวลาที่ใช้ในการแสดงผลเฟรมของหน้าต่าง UI นี่คือจอภาพที่มีรายละเอียดมากที่สุดจาก 4 ตัวนี้ดังนั้นหากคุณต้องการรายละเอียดเพิ่มเติม อ่านนี่ .
สุดท้ายนี้เรามีไฟล์ จอภาพหน่วยความจำ ซึ่งคุณอาจใช้มากที่สุด ตามค่าเริ่มต้นจะแสดงจำนวนหน่วยความจำที่ว่างและจัดสรรในปัจจุบัน คุณสามารถบังคับใช้ Garbage Collection ได้เช่นกันเพื่อทดสอบว่าจำนวนหน่วยความจำที่ใช้ลดลงหรือไม่ มีคุณสมบัติที่มีประโยชน์ที่เรียกว่า Dump Java Heap ซึ่งจะสร้างไฟล์ HPROF ซึ่งสามารถเปิดได้ด้วยไฟล์ HPROF Viewer และ Analyzer . ซึ่งจะช่วยให้คุณเห็นจำนวนวัตถุที่คุณจัดสรรหน่วยความจำถูกยึดไปเท่าใดและวัตถุใดที่ทำให้หน่วยความจำรั่วไหล การเรียนรู้วิธีใช้เครื่องวิเคราะห์นี้ไม่ใช่งานที่ง่ายที่สุด แต่ก็คุ้มค่า สิ่งต่อไปที่คุณสามารถทำได้กับ Memory Monitor คือทำการติดตามการจัดสรรตามกำหนดเวลาซึ่งคุณสามารถเริ่มและหยุดได้ตามที่คุณต้องการ อาจมีประโยชน์ในหลาย ๆ กรณีตัวอย่างเช่นเมื่อเลื่อนหรือหมุนอุปกรณ์
นี่เป็นเครื่องมือตัวช่วยง่ายๆซึ่งคุณสามารถเปิดใช้งานได้ในตัวเลือกสำหรับนักพัฒนาเมื่อคุณเปิดใช้งานโหมดนักพัฒนาแล้ว เลือก Debug GPU overdraw,“ Show overdraw areas” และหน้าจอของคุณจะมีสีแปลก ๆ โอเคนั่นคือสิ่งที่ควรจะเกิดขึ้น สีหมายถึงจำนวนครั้งที่พื้นที่หนึ่ง ๆ ถูกวาดทับ สีที่แท้จริงหมายความว่าไม่มีการวาดทับนี่คือสิ่งที่คุณควรตั้งเป้าหมาย สีน้ำเงินหมายถึงการวางทับหนึ่งครั้งสีเขียวหมายถึงสองสีชมพูสามสีแดงสี่
ในขณะที่การมองเห็นสีที่แท้จริงเป็นสิ่งที่ดีที่สุด แต่คุณมักจะเห็นภาพวาดบางส่วนโดยเฉพาะบริเวณข้อความลิ้นชักการนำทางกล่องโต้ตอบและอื่น ๆ ดังนั้นอย่าพยายามกำจัดอย่างเต็มที่ หากแอปของคุณเป็นสีน้ำเงินหรือเขียวก็คงใช้ได้ อย่างไรก็ตามหากคุณเห็นสีแดงมากเกินไปบนหน้าจอที่เรียบง่ายคุณควรตรวจสอบสิ่งที่เกิดขึ้น อาจมีชิ้นส่วนซ้อนทับกันมากเกินไปหากคุณยังคงเพิ่มไว้แทนที่จะแทนที่ ดังที่ฉันได้กล่าวไปแล้วข้างต้นการวาดภาพเป็นส่วนที่ช้าที่สุดของแอปดังนั้นจึงไม่มีเหตุผลที่จะวาดอะไรบางอย่างหากจะมีเลเยอร์มากกว่า 3 เลเยอร์ที่วาดลงไป อย่าลังเลที่จะตรวจสอบแอพโปรดของคุณด้วยแอพนี้ คุณจะเห็นว่าแม้แต่แอปที่มีการดาวน์โหลดมากกว่าพันล้านครั้งก็มีพื้นที่สีแดงดังนั้นให้ใช้งานง่ายเมื่อคุณพยายามเพิ่มประสิทธิภาพ
นี่เป็นอีกเครื่องมือหนึ่งจากตัวเลือกสำหรับนักพัฒนาที่เรียกว่า การเรนเดอร์ GPU โปรไฟล์ . เมื่อเลือกแล้วให้เลือก“ บนหน้าจอเป็นแถบ” คุณจะสังเกตเห็นแถบสีปรากฏบนหน้าจอของคุณ เนื่องจากทุกแอปพลิเคชันมีแถบแยกกันแถบสถานะจึงมีแถบสถานะของตัวเองและในกรณีที่คุณมีปุ่มนำทางซอฟต์แวร์ก็จะมีแถบของตัวเองด้วย อย่างไรก็ตามแถบจะได้รับการอัปเดตเมื่อคุณโต้ตอบกับหน้าจอ
แถบประกอบด้วยสี 3-4 สีและตามเอกสารของ Android ขนาดของมันมีความสำคัญอย่างยิ่ง ยิ่งเล็กยิ่งดี ที่ด้านล่างคุณจะมีสีน้ำเงินซึ่งแสดงถึงเวลาที่ใช้ในการสร้างและอัปเดตรายการที่แสดงของ View หากส่วนนี้สูงเกินไปแสดงว่ามีมุมมองแบบกำหนดเองจำนวนมากหรือมีงานจำนวนมากที่ทำใน onDraw()
ฟังก์ชั่น. หากคุณมี Android 4.0+ คุณจะเห็นแถบสีม่วงเหนือแถบสีน้ำเงิน นี่แสดงถึงเวลาที่ใช้ในการถ่ายโอนทรัพยากรไปยังเธรดการแสดงผล จากนั้นก็มาถึงส่วนสีแดงซึ่งแสดงถึงเวลาที่ใช้ในการแสดงผล 2D ของ Android ที่ออกคำสั่งไปยัง OpenGL เพื่อวาดและวาดใหม่รายการที่แสดง ที่ด้านบนคือแถบสีส้มซึ่งแสดงถึงเวลาที่ CPU กำลังรอให้ GPU ทำงานให้เสร็จสิ้น หากสูงเกินไปแสดงว่าแอปทำงานกับ GPU มากเกินไป
ถ้าคุณเก่งพอมีอีกหนึ่งสีด้านบนสีส้ม เป็นเส้นสีเขียวแสดงถึงเกณฑ์ 16 มิลลิวินาที เนื่องจากเป้าหมายของคุณควรใช้งานแอปที่ 60 fps คุณมีเวลา 16 ms ในการวาดทุกเฟรม หากคุณไม่ทำบางเฟรมอาจถูกข้ามไปแอปอาจกระตุกและผู้ใช้จะสังเกตเห็นได้อย่างแน่นอน ให้ความสนใจเป็นพิเศษกับภาพเคลื่อนไหวและการเลื่อนซึ่งเป็นจุดที่ความราบรื่นมีความสำคัญมากที่สุด แม้ว่าคุณจะสามารถตรวจจับเฟรมที่ข้ามได้ด้วยเครื่องมือนี้ แต่ก็ไม่ได้ช่วยให้คุณทราบได้อย่างแท้จริงว่าปัญหาอยู่ที่ใด
นี่เป็นหนึ่งในเครื่องมือโปรดของฉันเนื่องจากมีประสิทธิภาพมาก คุณสามารถเริ่มได้จาก Android Studio ผ่าน Tools -> Android -> Android Device Monitor หรือจะอยู่ในโฟลเดอร์ sdk / tools ของคุณเป็น 'จอภาพ' ก็ได้ นอกจากนี้คุณยังสามารถค้นหา hierarachyviewer แบบสแตนด์อโลนที่ปฏิบัติการได้ที่นั่น แต่เมื่อเลิกใช้แล้วคุณควรเปิดจอภาพ อย่างไรก็ตามคุณเปิดการตรวจสอบอุปกรณ์ Android ให้เปลี่ยนไปใช้มุมมองของผู้ดูลำดับชั้น หากคุณไม่เห็นแอปที่ทำงานอยู่ที่กำหนดให้กับอุปกรณ์ของคุณ นั่นเอง มีสองสิ่งที่คุณสามารถทำได้เพื่อแก้ไข ลองตรวจสอบดู นี้ เธรดปัญหามีผู้ที่มีปัญหาทุกประเภทและวิธีแก้ปัญหาทุกประเภท บางอย่างก็น่าจะเหมาะกับคุณเช่นกัน
ด้วย Hierarchy Viewer คุณสามารถดูภาพรวมของลำดับชั้นมุมมองของคุณได้อย่างเป็นระเบียบ (ชัดเจน) หากคุณเห็นทุกรูปแบบใน XML แยกกันคุณอาจมองเห็นมุมมองที่ไร้ประโยชน์ได้อย่างง่ายดาย อย่างไรก็ตามหากคุณยังคงรวมเค้าโครงเข้าด้วยกันอาจทำให้เกิดความสับสนได้ง่าย เครื่องมือเช่นนี้ช่วยให้มองเห็นได้ง่ายเช่น RelativeLayout บางตัวซึ่งมีลูกเพียง 1 ลูกอีกตัวคือ RelativeLayout นั่นทำให้หนึ่งในนั้นถอดออกได้
หลีกเลี่ยงการเรียก requestLayout()
เนื่องจากจะทำให้เกิดการข้ามลำดับชั้นการดูทั้งหมดเพื่อดูว่าแต่ละมุมมองควรมีขนาดใหญ่เพียงใด หากมีข้อขัดแย้งกับการวัดลำดับชั้นอาจมีการข้ามหลายครั้งซึ่งหากเกิดขึ้นในระหว่างการเคลื่อนไหวบางอย่างจะทำให้บางเฟรมถูกข้ามไปอย่างแน่นอน หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีที่ Android ดึงมุมมองคุณสามารถทำได้ อ่านนี่ . มาดูมุมมองเดียวที่เห็นใน Hierarchy Viewer
มุมขวาบนมีปุ่มสำหรับขยายการแสดงตัวอย่างของมุมมองนั้น ๆ ในหน้าต่างแบบสแตนด์อโลน คุณยังสามารถดูตัวอย่างจริงของมุมมองในแอปได้อีกด้วย รายการถัดไปคือตัวเลขซึ่งแสดงจำนวนเด็กที่มีมุมมองที่กำหนดรวมถึงมุมมองด้วย หากคุณเลือกโหนด (ควรเป็นรูทหนึ่ง) และกด“ รับเวลาเลย์เอาต์” (วงกลม 3 สี) คุณจะมีค่าอีก 3 ค่าพร้อมกับวงกลมสีที่มีป้ายกำกับการวัดการจัดวางและการวาด อาจไม่น่าตกใจที่ระยะการวัดแสดงถึงเวลาที่ใช้ในการวัดมุมมองที่กำหนด ขั้นตอนการจัดวางเป็นเรื่องเกี่ยวกับเวลาในการแสดงผลในขณะที่การวาดภาพเป็นการดำเนินการวาดจริง ค่าและสีเหล่านี้สัมพันธ์กัน สีเขียวหมายถึงมุมมองที่แสดงเป็น 50% แรกของมุมมองทั้งหมดในแผนภูมิ สีเหลืองหมายถึงการแสดงผลช้าลง 50% ของมุมมองทั้งหมดในแผนภูมิสีแดงหมายความว่ามุมมองที่กำหนดเป็นหนึ่งในมุมมองที่ช้าที่สุด เนื่องจากค่าเหล่านี้เป็นค่าสัมพัทธ์จึงมีค่าสีแดงเสมอ คุณไม่สามารถหลีกเลี่ยงได้
ภายใต้ค่าที่คุณมีชื่อคลาสเช่น 'TextView', ID มุมมองภายในของออบเจ็กต์และ android: id ของมุมมองซึ่งคุณตั้งไว้ในไฟล์ XML ฉันขอแนะนำให้คุณสร้างนิสัยในการเพิ่ม ID ให้กับทุกมุมมองแม้ว่าคุณจะไม่ได้อ้างอิงในโค้ดก็ตาม จะทำให้การระบุมุมมองใน Hierarchy Viewer เป็นเรื่องง่ายมากและในกรณีที่คุณมีการทดสอบอัตโนมัติในโครงการของคุณก็จะทำให้การกำหนดเป้าหมายองค์ประกอบเร็วขึ้นมาก ซึ่งจะช่วยประหยัดเวลาสำหรับคุณและเพื่อนร่วมงานของคุณในการเขียน การเพิ่ม ID ให้กับองค์ประกอบที่เพิ่มในไฟล์ XML นั้นค่อนข้างตรงไปตรงมา แต่องค์ประกอบที่เพิ่มแบบไดนามิกล่ะ? มันก็ดูเรียบง่ายเหมือนกัน เพียงสร้างไฟล์ ids.xml ภายในโฟลเดอร์ค่าของคุณและพิมพ์ในฟิลด์ที่จำเป็น จะมีลักษณะดังนี้:
setId(R.id.item_title)
จากนั้นในโค้ดคุณสามารถใช้ LinearLayouts
มันไม่ง่ายไปกว่านี้แล้ว
มีอีกสองสิ่งที่ควรใส่ใจเมื่อเพิ่มประสิทธิภาพ UI โดยทั่วไปคุณควรหลีกเลี่ยงลำดับชั้นแบบลึกในขณะที่เลือกลำดับชั้นที่ตื้นหรือกว้าง อย่าใช้เค้าโครงที่คุณไม่ต้องการ ตัวอย่างเช่นคุณอาจแทนที่กลุ่มที่ซ้อนกัน RelativeLayout
ด้วย a TableLayout
หรือ a LinearLayout
อย่าลังเลที่จะทดลองใช้เลย์เอาต์ต่างๆอย่าใช้แค่ RelativeLayout
เสมอไป และ
|_+_|. ลองสร้างมุมมองที่กำหนดเองบางส่วนเมื่อจำเป็นซึ่งสามารถปรับปรุงประสิทธิภาพได้อย่างมากหากทำได้ดี ตัวอย่างเช่นคุณทราบหรือไม่ว่า Instagram ไม่ได้ใช้ TextView สำหรับ การแสดงความคิดเห็น เหรอ?
คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับ Hierarchy Viewer ได้ที่ ไซต์ Android Developers พร้อมคำอธิบายของบานหน้าต่างที่แตกต่างกันโดยใช้เครื่องมือ Pixel Perfect เป็นต้นอีกสิ่งหนึ่งที่ฉันอยากจะชี้ให้เห็นคือการจับภาพมุมมองในไฟล์. psd ซึ่งทำได้โดยปุ่ม“ จับภาพเลเยอร์หน้าต่าง” ทุกมุมมองจะอยู่ในเลเยอร์ที่แยกจากกันดังนั้นจึงง่ายมากที่จะซ่อนหรือเปลี่ยนแปลงใน Photoshop หรือ GIMP นั่นเป็นอีกเหตุผลหนึ่งในการเพิ่ม ID ในทุกมุมมองที่คุณทำได้ มันจะทำให้เลเยอร์มีชื่อที่สมเหตุสมผล
คุณจะพบเครื่องมือดีบั๊กมากมายในตัวเลือกสำหรับนักพัฒนาดังนั้นฉันแนะนำให้คุณเปิดใช้งานและดูว่าพวกเขากำลังทำอะไรอยู่ สิ่งที่อาจจะผิดไป?
ไซต์นักพัฒนา Android ประกอบด้วยชุดไฟล์ แนวทางปฏิบัติที่ดีที่สุดสำหรับประสิทธิภาพ . ครอบคลุมพื้นที่ต่างๆมากมายรวมถึงการจัดการหน่วยความจำซึ่งฉันไม่ได้พูดถึงจริงๆ ฉันเพิกเฉยต่อเรื่องนี้อย่างเงียบ ๆ เพราะการจัดการหน่วยความจำและการติดตามการรั่วไหลของหน่วยความจำเป็นเรื่องราวที่แยกจากกัน การใช้ไลบรารีของบุคคลที่สามเพื่อแสดงภาพอย่างมีประสิทธิภาพจะช่วยได้มาก แต่หากคุณยังคงมีปัญหาเกี่ยวกับหน่วยความจำให้ตรวจสอบ นกขมิ้นรั่ว ทำโดย Square หรืออ่าน นี้ .
นี่เป็นข่าวดี สิ่งใหม่ที่ไม่ดีคือการเพิ่มประสิทธิภาพ Android แอพมีความซับซ้อนกว่ามาก มีหลายวิธีในการทำทุกอย่างดังนั้นคุณควรทำความคุ้นเคยกับข้อดีข้อเสียของพวกเขา โดยปกติจะไม่มีโซลูชัน Silver bullet ที่มีประโยชน์เพียงอย่างเดียว คุณจะสามารถเลือกวิธีแก้ปัญหาที่ดีที่สุดสำหรับคุณได้โดยการทำความเข้าใจสิ่งที่เกิดขึ้นเบื้องหลังเท่านั้น เพียงเพราะนักพัฒนาซอฟต์แวร์คนโปรดของคุณบอกว่าสิ่งที่ดีไม่จำเป็นต้องหมายความว่านั่นคือทางออกที่ดีที่สุดสำหรับคุณ มีพื้นที่มากมายให้พูดคุยและมีเครื่องมือในการทำโปรไฟล์ที่ล้ำหน้ากว่านี้ดังนั้นเราอาจจะพูดคุยกันในครั้งต่อไป
อย่าลืมเรียนรู้จากนักพัฒนาชั้นนำและ บริษัท ชั้นนำ คุณสามารถค้นหาบล็อกวิศวกรรมสองร้อยบล็อกได้ที่ ลิงค์นี้ . เห็นได้ชัดว่าไม่ใช่แค่เนื้อหาที่เกี่ยวข้องกับ Android ดังนั้นหากคุณสนใจเฉพาะ Android คุณต้องกรองบล็อกนั้น ๆ ฉันขอแนะนำบล็อกของ เฟสบุ๊ค และ อินสตาแกรม . แม้ว่า UI ของ Instagram บน Android จะเป็นที่น่าสงสัย แต่บล็อกด้านวิศวกรรมของพวกเขาก็มีบทความที่น่าสนใจจริงๆ สำหรับฉันมันยอดเยี่ยมมากที่ได้เห็นวิธีการทำสิ่งต่างๆใน บริษัท ที่จัดการกับผู้ใช้หลายร้อยล้านคนในแต่ละวันได้อย่างง่ายดายดังนั้นการไม่อ่านบล็อกของพวกเขาจึงดูเหมือนบ้า โลกเปลี่ยนแปลงเร็วมากดังนั้นหากคุณไม่พยายามปรับปรุงเรียนรู้จากผู้อื่นและใช้เครื่องมือใหม่ ๆ อยู่ตลอดเวลาคุณจะถูกทิ้งไว้เบื้องหลัง ดังที่ Mark Twain กล่าวไว้ว่าคนที่อ่านหนังสือไม่ออกก็ไม่มีประโยชน์มากกว่าคนที่อ่านหนังสือไม่ออก