Android: onCreateOptionsMenu ถูกเรียกเมื่อใดในช่วงวงจรชีวิตของกิจกรรม


149

ฉันใส่จุดพักสองสามจุดonCreate(หนึ่งจุดเริ่มต้นและอีกจุดท้ายของวิธีการ) และฉันก็ใส่จุดเริ่มต้นonCreateOptionsMenuไว้ onCreateวิธีการที่เรียกว่าครั้งแรกและก่อนที่จะเสร็จสิ้นการonCreateOptionsMenuที่เรียกว่า

ฉันกำลังพยายามแยกFragmentรหัสการนำทางในแอพของฉันดังนั้นฉันจึงมีวัตถุสองอย่างที่ฉันมอบหมายonCreateOptionsMenuให้ขึ้นอยู่กับว่าแอปทำงานบนโทรศัพท์ / แท็บเล็ตหรือไม่ (ฉันใช้ขนาดหน้าจอเพื่อกำหนดสิ่งนี้ หน้าจอขนาดใหญ่มีมุมมองที่ฉันตรวจสอบหลังจากโครงร่างพองเกินไป) ปัญหาฉันมีคือผมสร้างวัตถุเหล่านี้ใน onCreate onCreateOptionsMenuและฉันได้รับข้อยกเว้นชี้โมฆะเมื่อฉันอ้างอิงวัตถุใน

คำตอบ:


112

กระบวนการ onCreate เรียกว่าเป็นครั้งแรกและก่อนที่มันจะเสร็จสิ้น onCreateOptionsMenu เรียกว่า

ซึ่งจะเป็นจริงในอุปกรณ์และแอพด้วยแถบแอ็คชั่นสไตล์ Honeycomb อย่างเป็นทางการ หากไม่มีแถบการดำเนินการonCreateOptionsMenu()ไม่ควรถูกเรียกจนกระทั่งผู้ใช้เรียกเมนูโดยทั่วไปแล้วกดปุ่มเมนู

(ฉันใช้ขนาดหน้าจอเพื่อกำหนดสิ่งนี้ไฟล์เลย์เอาต์ของฉันสำหรับหน้าจอขนาดใหญ่มีมุมมองที่ฉันตรวจสอบหลังจากเลย์เอาต์เกินจริง)

การทดสอบนั้นจะหยุดลงในไม่ช้าเมื่อไอศครีมแซนวิชส่งไป จากสิ่งที่ฉันสามารถบอกได้โทรศัพท์ ICS จะมีแถบแอ็คชั่น (แม้ว่าอาจไม่ใช่แถบระบบ)


ฉันลืมที่จะพูดถึงว่าฉันใช้ห้องสมุด ActionbarSherlock คำตอบของคุณทำให้ฉันนึกถึง นั่นอาจเป็นสาเหตุของพฤติกรรมนี้เนื่องจากเป็น wrapper ในไลบรารีความเข้ากันได้ซึ่งทำให้รายการเมนูใน "ActionBar"
Christopher Perry

@commonsware - นั่นหมายถึงอุปกรณ์และแอพที่ไม่มีแถบการกระทำ เมนูจะปรากฏขึ้นแม้ว่า onCreateOptionsMenu จะไม่เห็นรายการหรือไม่
NinjaCoder

12
ในกรณีของฉันบนสร้างเมนูโทรหลังจากวันที่
Kostya Khuta

1
ใช่ฉันมีปัญหาเดียวกัน ... แต่รหัสของฉันเกี่ยวข้องกับ Fragment
Yoann Hercouet

ผมเริ่มมีNPEเมื่อตรวจสอบถ้าเปิดในnav drawer fragment onCreateOptionsMenuฉันต้องทำการตรวจสอบโมฆะทั้งใน onCreateOptionsMenu ของกิจกรรมรวมทั้งการเรียกกลับที่แฟรกเมนต์ใช้ใน onCreateOptionsMenu แปลกจริง ๆ เพราะมันเกิดขึ้นบนหน้าจอเพียงไม่กี่หน้าจอ
theblang

54

ในกรณีของฉันใน Android 2.3 และด้วยFragmentActivityจากห้องสมุดสนับสนุน v4 ลำดับของวิธีวงจรชีวิตที่เรียกใช้มีดังต่อไปนี้:

07-18 18:29:21.629  20183-20183/? I/onCreate:
07-18 18:29:21.719  20183-20183/? I/onStart: 
07-18 18:29:21.719  20183-20183/? I/onResume: 
07-18 18:29:21.739  20183-20183/? I/onCreateOptionsMenu:

27

ฉันพบว่าใน onResume () ฉันโทรหา

invalidateOptionsMenu();

onCreateOptionsMenu (เมนูเมนู) เรียกหลังจากนั้น - ตามวงจรชีวิตของกิจกรรม (ฉันคิดว่านั่นเป็นคำที่ถูกต้องที่นี่)ตามที่ระบุโดย @ tir38

@Override
public void onResume() {
    super.onResume();
    invalidateOptionsMenu();
}

4
หากคุณใช้ actionbarsherlock ให้โทรวิธีนี้supportInvalidateOptionsMenu();
Shan Xeeshi

3
ระวังเมื่อคุณพูดว่า "ทันที" มันจะไม่เกิดขึ้นทันทีอย่างแท้จริง เมื่อคุณinvalidateOptionsMenuงานที่จะสร้างเมนูตัวเลือกจะถูกเพิ่มไปยังคิวข้อความของ UI สิ่งใดก็ตามที่อยู่ในคิวจะเริ่มทำงานก่อน
tir38

21

นอกเหนือจากคำตอบข้างต้นในกรณีของ ICS และ Honeycomb onCreateOptionsMenu จะถูกเรียกใช้หลังจาก onCreate และ onPostCreate ในขณะที่ Gingerbread และเวอร์ชันก่อนหน้านั้นจะถูกเรียกใช้หลังจาก onCreate แต่ก่อนบน postCreate ความแตกต่างเพียงอย่างเดียวที่ฉันพบ


3

ในประสบการณ์ของฉันActionBarActivityจากการสนับสนุน v7 onCreateOptionsMenu()เรียกว่าsetContentView()วิธีการในช่วงกลางของonCreate()มันจะปรากฏบน 4.1.1

แต่ใน 4.4 อีกเรื่องหนึ่งเรียกว่าหลังจากonCreateOptionMenu() onCreate()ฉันก็ไม่รู้เหมือนกันว่ามันอาจจะเกิดขึ้นทันทีหลังจากนั้น แต่เป็นความจริงหลังจาก ฉันไม่ได้ทดสอบรุ่นอื่น แต่ 4.1.1 เป็นครั้งแรกที่ฉันมีปัญหากับคำสั่งซื้อ init


บางทีคุณอาจจะต้องใช้supportInvalidateOptionsMenu()?
David d C e Freitas

2

ฉันขอแนะนำให้สร้างฟังก์ชั่นการโทรกลับในส่วนของคุณเพื่อหลีกเลี่ยงปัญหาเกี่ยวกับเวลากับ onResume () และ onCreateOptionsMenu ()

ทำผลงานต่อไปนี้ไร้ที่ติสำหรับฉัน:

  1. สร้างและเพิ่มส่วนของคุณในกิจกรรมของคุณ
  2. ทิ้งการอ้างอิงของส่วนนี้ไว้ในกิจกรรมของคุณ
  3. สร้างวิธีการสาธารณะ doSomethingWithTheMenu () ในส่วนของคุณ
  4. เรียกวิธีการนี้จากภายในกิจกรรมของคุณเมื่อมีการเรียก onCreateOptionsMenu (เมนูเมนู)

ตัวอย่าง:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    if (this.myFragment != null) {
        this.myFragment.doSomethingWithTheMenu(menu);
    }
    return true;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.