กิจกรรมมีหน้าต่างที่รั่วไหลออกมาซึ่งเพิ่มเข้ามา แต่เดิม


1162

ข้อผิดพลาดนี้คืออะไรและทำไมจึงเกิดขึ้น

05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): android.view.WindowLeaked: Activity ccom.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.ViewRoot.<init>(ViewRoot.java:231)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.Dialog.show(Dialog.java:239)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP$PreparePairingLinkageData.onPreExecute(viewP.java:183)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.AsyncTask.execute(AsyncTask.java:391)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP.onCreate(viewP.java:94)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.access$2200(ActivityThread.java:126)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.Looper.loop(Looper.java:123)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.main(ActivityThread.java:4595)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at java.lang.reflect.Method.invokeNative(Native Method)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at java.lang.reflect.Method.invoke(Method.java:521)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at dalvik.system.NativeStart.main(Native Method)

6
คลาสสิกอื่นคือเมื่อมีการเปลี่ยนแปลงการวางแนว: stackoverflow.com/questions/1111980/…
rds

คำตอบ:


1560

คุณกำลังพยายามแสดงกล่องโต้ตอบหลังจากออกจากกิจกรรมแล้ว

[แก้ไข]

คำถามนี้เป็นหนึ่งในการค้นหายอดนิยมในนักพัฒนาของ Google สำหรับ Android ดังนั้นการเพิ่มจุดสำคัญบางประการจากความคิดเห็นซึ่งอาจเป็นประโยชน์มากขึ้นสำหรับผู้ตรวจสอบในอนาคตโดยไม่ต้องเจาะลึกความคิดเห็น

ตอบ 1 :

คุณกำลังพยายามแสดงกล่องโต้ตอบหลังจากออกจากกิจกรรมแล้ว

คำตอบ 2

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

คำตอบ 3

การยกเลิกการโทร () บนอินสแตนซ์ของกล่องโต้ตอบที่คุณสร้างก่อนออกจากกิจกรรมของคุณเช่นใน onPause () หรือ onDestroy ()


2
@Override โมฆะสาธารณะ onStop () {if (dialog! = null) {dialog.dismiss (); dialog = null; }}
Md.Tarikul ศาสนาอิสลาม

14
แม้หลังจาก 8 ปีนี้ก็ยังมีความเกี่ยวข้อง! ฉันได้รับการยกเว้นเนื่องจากกิจกรรมถูกปิดขณะที่พยายามแสดง AlertDialog ของฉัน (ดังนั้นคำตอบ 2) ในตอนท้ายฉันพบว่าแอปเพิ่มวัตถุ "โมฆะ" ลงในฉาก (ไม่ควรเกิดขึ้น แต่เกิดขึ้น) แต่มันก็ไม่ได้ให้ข้อยกเว้นพิเศษสำหรับมัน ข้อยกเว้นหน้าต่าง "แทน
Neph

เป็นไปได้ไหมที่จะสแกนหากล่องโต้ตอบที่เปิดอยู่ทั้งหมดและปิดทั้งหมดใน onStop ()? ฉันสร้างกล่องโต้ตอบใน ListView เมื่อคลิกที่รายการ ฉันไม่แน่ใจว่าจะดึงข้อมูลอ้างอิงของพวกเขาจาก onStop ได้อย่างไร
Myoch

1
คำตอบ 3 เป็นทางออกที่ดีที่สุด ทำงานอย่างมากสำหรับฉัน ขอขอบคุณเขาอย่างอเล็กซ์ !!
amit bansode

เคล็ดลับเพิ่มเติมถ้าคุณแสดงข้อความโต้ตอบในลูปให้แน่ใจว่าลูปถูกออกหลังจากกิจกรรมเสร็จสิ้น
Thecarisma

406

การแก้ปัญหาคือการเรียกร้องdismiss()ในDialogคุณสร้างในviewP.java:183ก่อนที่จะออกจากเช่นในActivity onPause()ทั้งหมดWindows & Dialogs Activityควรจะปิดก่อนที่จะออกจาก


3
ดังนั้นเมื่อผู้ใช้หมุนโทรศัพท์กล่องโต้ตอบทั้งหมดควรถูกยกเลิก? นั่นไม่ได้เสียงที่ถูกต้อง
LarsH

@ LarsH อย่างที่คุณเห็นคำตอบของฉันถูกเขียนมานานกว่า 7 ปีแล้วและนี่เป็นความจริงในเวลานั้น ฉันไม่ได้ทำงานกับ Android อีกต่อไป แต่จากสิ่งที่ฉันเห็นในเอกสารมันอาจยังคงเป็นเช่นนั้น แต่ Android มาไกลตั้งแต่นั้น (แนะนำ Fragments เพียงเพื่อชื่อหนึ่ง) ดังนั้นตอนนี้อาจเป็นเรื่องง่ายขึ้น
molnarm

108

หากคุณใช้AsyncTaskงานอยู่อาจเป็นเพราะข้อความบันทึกอาจหลอกลวงได้ หากคุณค้นหาในบันทึกของคุณคุณอาจพบข้อผิดพลาดอื่นอาจเป็นหนึ่งในdoInBackground()วิธีการของคุณAsyncTaskที่ทำให้ปัจจุบันของคุณActivityจะระเบิดและดังนั้นเมื่อAsyncTaskกลับมา .. ดีคุณรู้ส่วนที่เหลือ มีผู้ใช้อื่นอธิบายไว้แล้วที่นี่ :-)


22
บางครั้งในกรณีนั้นฉันไม่สามารถเห็นข้อยกเว้นจริงได้ เพื่อหาข้อยกเว้นที่แท้จริงเพียงแสดงความคิดเห็น progressDialog.show () และเรียกใช้แอปอีกครั้ง .. ตอนนี้คุณจะเห็นมัน
ติด

สวัสดีทุกคน! ตามที่กล่าวไว้ข้างต้นโดย @Stuck ฉันไม่สามารถเห็นข้อยกเว้นที่แท้จริงได้เช่นกันฉันทำอะไร ผมติดตามโดยใช้จุดทำลายและผมค้นพบว่าผมใช้อ้างอิงของการเรียนการประยุกต์ใช้วิธีการภายในdoInBackgroundของAsyncTaskชั้น แต่ไม่มีการประกาศไว้ในAndroidManifestไฟล์โดยใช้สถานที่เช่นนี้android:name android:name="my.package.MyApplicationClass"การปฏิบัติที่ดีเมื่อใช้AsyncTaskมันอยู่เสมออย่าลืมที่จะยกตัวอย่างการแจ้งเตือนของคุณภายในวิธีการและไล่มันในonPreExecute onPostExecute
GFPF

66

ฉันเรียกข้อผิดพลาดนี้โดยเข้าใจผิดเรียกhide()แทนบน dismiss()AlertDialog


4
เกิดอะไรขึ้นกับฉัน นอกจากนี้การเรียก hide () จากนั้นการตั้งค่าไดอะล็อกให้เป็นโมฆะก็ไม่ใช่ทางเลือกอื่น
Lucas Tulio

ฉันจะรู้ปัญหาที่อยู่เบื้องหลังนี้จริงๆ แต่การโทรเลิก () ช่วยฉันได้!
Karoly

59

คุณสามารถรับข้อยกเว้นนี้ได้เพียงข้อผิดพลาดง่ายๆ / เป็นใบ้โดย (ตัวอย่าง) การโทรโดยไม่ตั้งใจfinish()หลังจากที่แสดงAlertDialogขึ้นหากคุณพลาดคำสั่งการโทรหยุดในคำสั่งสลับ ...

   @Override
   public void onClick(View v) {
    switch (v.getId()) {
        case R.id.new_button:
            openMyAlertDialog();
            break; <-- If you forget this the finish() method below 
                       will be called while the dialog is showing!
        case R.id.exit_button:
            finish();
            break;
        }
    }

finish()วิธีการจะปิดActivityแต่AlertDialogยังคงแสดง!

ดังนั้นเมื่อคุณจ้องมองโค้ดอย่างจริงจังมองหาปัญหาเกลียวที่ไม่ดีหรือการเขียนโค้ดที่ซับซ้อนและอย่ามองไปที่ป่าเพื่อมองหาต้นไม้ บางครั้งมันอาจเป็นเพียงสิ่งที่เรียบง่ายและโง่เง่าเหมือนคำสั่ง break ที่ขาดหายไป :)


มากหรือน้อยตรงประเด็นของฉัน เรียกว่าเสร็จสิ้นใน onError หลังจากสร้างกล่องโต้ตอบไม่ใช่ใน onClick สำหรับปุ่มยกเลิก
jbass

46

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

คุณรู้แล้วว่าจากการอ่านคำตอบอื่น ๆ ว่ามีX has leaked window DecorView@d9e6131[]ข้อผิดพลาดหมายความว่ากล่องโต้ตอบเปิดขึ้นเมื่อแอปของคุณปิด แต่ทำไม

อาจเป็นไปได้ว่าแอปของคุณชนด้วยเหตุผลอื่นขณะที่กล่องโต้ตอบเปิด

สิ่งนี้นำไปสู่การปิดแอปของคุณเนื่องจากมีข้อบกพร่องบางอย่างในรหัสของคุณซึ่งนำไปสู่กล่องโต้ตอบที่ยังคงเปิดอยู่ในเวลาเดียวกับที่แอปของคุณปิดเนื่องจากข้อผิดพลาดอื่น ๆ

ดังนั้นมองผ่านตรรกะของคุณ แก้ไขข้อผิดพลาดแรกจากนั้นข้อผิดพลาดที่สองจะแก้ไขตัวเองป้อนคำอธิบายรูปภาพที่นี่

ข้อผิดพลาดหนึ่งทำให้เกิดข้อผิดพลาดอื่นซึ่งทำให้เกิดข้อผิดพลาดอื่นเช่น DOMINOS!


2
ไม่อยากจะเชื่อเลยว่ามี upvote เพียงตัวเดียว .. หรือเราแค่เขียนโปรแกรมไม่ดีจริงๆฮ่าฮ่าฮ่าฉันยังชอบ domino analogy ของคุณด้วย
user2161301

แก้ไขข้อผิดพลาดครั้งแรกและข้อผิดพลาดที่สองจะไม่เกิดขึ้น อุปมานี้ช่วยฉันได้
itabdullah

สิ่งนี้ไม่ถูกต้องตัวอย่างเช่นการหมุนโทรศัพท์อาจทำให้เกิดการหมุน "กิจกรรม" ได้
Sreekanth Karumanaghat

36

ปัญหานี้เกิดขึ้นเมื่อพยายามแสดงกล่องโต้ตอบหลังจากคุณออกจากกิจกรรมแล้ว

ฉันเพิ่งแก้ไขปัญหานี้เพียงแค่เขียนรหัสต่อไปนี้:

@Override
public void onDestroy(){
    super.onDestroy();
    if ( progressDialog!=null && progressDialog.isShowing() ){
        progressDialog.cancel();
    }
}

โดยพื้นฐานจากคลาสใดที่คุณเริ่ม progressDialog, แทนที่ overDestroy method และทำเช่นนี้ มันแก้ไขปัญหา "หน้าต่างรั่วไหลของกิจกรรม"


ไม่รับประกันว่าจะเรียก onDestroy ดีกว่าที่จะวางรหัสนั้นใน onPause หรือ onStop
Amruta-Pani

19

ฉันเพิ่งเผชิญกับปัญหาเดียวกัน

เหตุผลที่อยู่เบื้องหลังปัญหานี้คือกิจกรรมที่ถูกปิดก่อนที่จะปิดกล่องโต้ตอบ มีสาเหตุหลายประการที่กล่าวมาข้างต้น รายการที่กล่าวถึงในโพสต์ด้านบนถูกต้องเช่นกัน

ฉันเข้าสู่สถานการณ์เพราะในเธรดฉันกำลังเรียกใช้ฟังก์ชันที่กำลังทำการยกเว้น เนื่องจากหน้าต่างถูกยกเลิกและข้อยกเว้น


16

ปิดกล่องโต้ตอบเมื่อกิจกรรมทำลาย

@Override
protected void onDestroy()
{
    super.onDestroy();
    if (pDialog!=null && pDialog.isShowing()){
        pDialog.dismiss();
    }
}

ถ้า pDialog เป็นโมฆะจะทำให้เกิดข้อผิดพลาดในขณะที่คุณทำการสอบถามสถานะของกล่องโต้ตอบว่าง
Jonathan Dunn

1
ไม่มีมันจะไม่ @JonDunn เพราะ Java จะไม่ประมวลผลแบบบูลที่สองถ้าคนแรกที่เป็นเท็จ
matdev

13

สิ่งนี้จะช่วยได้

if (! isFinishing()) {

    dialog.show();

    }

2
ในบรรดาคำตอบที่คล้ายกันหลายร้อยคำตอบไม่มีใครแสดงวิธีตรวจสอบว่ามีหน้าต่างอยู่หรือไม่ ดังนั้นคุณประหยัดเวลาในการหาวิธีที่จะทำ ขอบคุณ
kolyaseg

11

ฉันมีข้อความแสดงข้อผิดพลาดที่คลุมเครือเหมือนกันและไม่รู้ว่าทำไม ปมที่ได้รับจากคำตอบก่อนหน้าฉันเปลี่ยนการโทรที่ไม่ใช่ GUI ไปยัง mDialog.finish () เป็น mDialog.dismiss () และข้อผิดพลาดหายไป สิ่งนี้ไม่ได้ส่งผลกระทบต่อพฤติกรรมของวิดเจ็ตของฉัน แต่มันทำให้เกิดความสับสนและอาจทำให้สถานะหน่วยความจำรั่วไหลได้


สังเกตเห็นว่าฉันกำลังทำ mDialog.hide () ก่อนการโทรเสร็จสิ้น () การเปลี่ยนเป็น mDialog.dismiss () ทำเคล็ดลับ
mays

11

ฉันได้รับบันทึกเหล่านี้ในแอปพลิเคชันเครื่องเล่นวิดีโอ ข้อความเหล่านี้ถูกส่งออกไปขณะที่เครื่องเล่นวิดีโอถูกปิด น่าสนใจฉันเคยได้รับบันทึกเหล่านี้เพียงครั้งเดียวในการวิ่งแบบสุ่ม progressdialogนอกจากนี้ใบสมัครของฉันไม่ได้เกี่ยวข้องใด ๆ ในที่สุดฉันได้รับปัญหานี้ด้วยการใช้งานด้านล่าง

@Override
protected void onPause()
{
    Log.v("MediaVideo", "onPause");
    super.onPause();
    this.mVideoView.pause();
    this.mVideoView.setVisibility(View.GONE);
}

@Override
protected void onDestroy()
{
    Log.v("MediaVideo", "onDestroy");
    super.onDestroy();
}

@Override
protected void onResume()
{
    Log.v("MediaVideo", "onResume");
    super.onResume();
    this.mVideoView.resume();
}

แทนที่OnPauseด้วยการเรียกร้องให้mVideoView.pause()และชุดที่จะvisibility GONEวิธีนี้ฉันสามารถแก้ไขปัญหาActivity has leaked windowบันทึกข้อผิดพลาด" "


ฉันยังประสบปัญหาเดียวกัน ฉันเพิ่มรหัสบรรทัดเหล่านี้ในรหัสของฉัน แต่มันไม่ทำงานและให้ข้อผิดพลาดเดียวกัน "android.view.WindowLeaked ที่ถูกเพิ่มเดิม" และยังไม่เล่นวิดีโอและให้ "ไม่สามารถเล่นวิดีโอ"
User42590

10

ฉันมีปัญหาเดียวกันและพบหน้านี้และในขณะที่สถานการณ์ของฉันแตกต่างกันฉันเรียกfinishจากifบล็อกก่อนที่จะกำหนดกล่องแจ้งเตือน

ดังนั้นการโทรเพียงอย่างเดียวdismissจะไม่ทำงาน (อย่างที่มันยังไม่ได้ทำ) แต่หลังจากอ่านคำตอบของ Alex Volovoyและรู้ตัวว่าเป็นกล่องเตือนทำให้เกิด ฉันพยายามเพิ่มคำสั่งส่งคืนหลังจากเสร็จสิ้นภายในifบล็อกนั้นและแก้ไขปัญหา

ฉันคิดว่าเมื่อคุณโทรเสร็จมันก็หยุดทุกอย่างและทำเสร็จตรงนั้น แต่ก็ไม่ได้ ดูเหมือนว่าจะไปที่จุดสิ้นสุดของบล็อกของรหัสในนั้นเสร็จสิ้น

ดังนั้นหากคุณต้องการใช้สถานการณ์ที่บางครั้งมันจะเสร็จสิ้นก่อนที่จะทำรหัสบางอย่างที่คุณต้องใส่คำสั่งกลับมาหลังจากเสร็จสิ้นหรือมันจะยังคงดำเนินต่อไปและทำหน้าที่เหมือนเสร็จถูกเรียกในตอนท้ายของ บล็อกของรหัสไม่ใช่ที่ที่คุณเรียกว่า นั่นคือเหตุผลที่ฉันได้รับข้อผิดพลาดแปลก ๆ เหล่านั้นทั้งหมด

private picked(File aDirectory){
     if(aDirectory.length()==0){
        setResult(RESULT_CANCELED, new Intent()); 
        finish(); 
        return;
    }
     AlertDialog.Builder alert= new AlertDialog.Builder(this); // Start dialog builder
     alert
        .setTitle("Question")
        .setMessage("Do you want to open that file?"+aDirectory.getName());
    alert
        .setPositiveButton("OK", okButtonListener)
        .setNegativeButton("Cancel", cancelButtonListener);
    alert.show();
}

หากคุณไม่ใส่ผลตอบแทนทันทีหลังจากที่ฉันเรียกว่าเสร็จสิ้นในนั้นมันจะทำหน้าที่ราวกับว่าคุณได้เรียกมันมาหลังจากนั้นalert.show();และด้วยเหตุนี้มันจะบอกว่าหน้าต่างรั่วไหลออกมาโดยการทำเสร็จหลังจากที่คุณทำกล่องโต้ตอบปรากฏขึ้น ไม่ใช่ในกรณีที่มันยังคงคิดว่ามันเป็น

ฉันคิดว่าฉันจะเพิ่มสิ่งนี้เพราะที่นี่แสดงให้เห็นว่าคำสั่ง finish ทำแตกต่างจากนั้นฉันคิดว่ามันทำและฉันเดาว่ามีคนอื่นที่คิดเหมือนฉันก่อนที่ฉันจะค้นพบสิ่งนี้


7

นี่ไม่ใช่คำตอบสำหรับคำถาม แต่เกี่ยวข้องกับหัวข้อ

หากกิจกรรมได้กำหนดแอตทริบิวต์ไว้ในรายการ

 android:noHistory="true"

จากนั้นหลังจากดำเนินการ onPause () บริบทของกิจกรรมจะหายไป ดังนั้นมุมมองทั้งหมดที่ใช้บริบทนี้อาจทำให้เกิดข้อผิดพลาดนี้


คุณสามารถเกี่ยวข้องกับสิ่งที่คล้ายกันสำหรับprogessdialog.show().. และprogressdialog.hide()ใน asynctaskกิจกรรมเดียวกันแทนที่จะonPause()มาจากactivity?? ดูที่ปัญหาของฉัน ... stackoverflow.com/questions/39332880/…
Bhuro

1
มันทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน: android: noHistory = "true"
Shohel Rana

6

ไม่เพียง แต่พยายามที่จะแสดงการแจ้งเตือน แต่ยังสามารถเรียกใช้เมื่อคุณเสร็จสิ้นกิจกรรมเฉพาะและพยายามเริ่มกิจกรรม / บริการใหม่หรือพยายามหยุดมัน

ตัวอย่าง:

OldActivity instance;

    oncreate() {
       instance=this;
    }
    instance.finish();
    instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));

6

โดยทั่วไปปัญหานี้เกิดขึ้นเนื่องจากกล่องโต้ตอบความคืบหน้า: คุณสามารถแก้ปัญหานี้โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้ในกิจกรรมของคุณ:

 // 1):
          @Override
                protected void onPause() {
                    super.onPause();
                    if ( yourProgressDialog!=null && yourProgressDialog.isShowing() )
                  {
                        yourProgressDialog.cancel();
                    }
                }

       // 2) :
         @Override
            protected void onDestroy() {
                super.onDestroy();
                if ( yourProgressDialog!=null && yourProgressDialog.isShowing()
               {
                    yourProgressDialog.cancel();
                }
            }

5

พบปัญหาที่ฉันทำกิจกรรมเมื่อ ProgressDialog ยังคงปรากฏ

ดังนั้นก่อนซ่อนกล่องโต้ตอบและทำกิจกรรมให้เสร็จสิ้น


5

ลองรหัสนี้:

public class Sample extends Activity(){
@Override
 public void onCreate(Bundle instance){

}
 @Override
    public void onStop() {
        super.onStop();
      progressdialog.dismiss(); // try this
    }

}

progressdialog.dismiss();สิ่งนี้สามารถสร้าง NullPointerException
tpk

5

นี่อาจเป็นได้ถ้าคุณมีข้อผิดพลาดที่doInBackground()ฟังก์ชันและมีรหัสนี้

ลองเพิ่มกล่องโต้ตอบในที่สุด ตอนแรกตรวจสอบและแก้ไขdoInBackground()ฟังก์ชั่น

protected void onPreExecute() {
     super.onPreExecute();
     pDialog = new ProgressDialog(CreateAccount.this);
     pDialog.setMessage("Creating Product..");
     pDialog.setIndeterminate(false);
     pDialog.setCancelable(true);
     pDialog.show();

 }

 protected String doInBackground(String...args) {
     ERROR CAN BE IS HERE
 }

 protected void onPostExecute(String file_url) {
     // dismiss the dialog once done
     pDialog.dismiss();

5

เรื่องนี้เกิดขึ้นกับฉันเมื่อฉันใช้ในProgressDialog AsyncTaskที่จริงฉันใช้วิธีการในhide() onPostExecuteจากคำตอบของ @Alex Volovoy ฉันจำเป็นต้องใช้dismiss()ด้วยProgressDialogเพื่อลบออกใน onPostExecute และเสร็จแล้ว

progressDialog.hide(); // Don't use it, it gives error

progressDialog.dismiss(); // Use it

นี่ไม่ใช่คำตอบทั้งหมด มีสองวิธีในการรั่วกล่องโต้ตอบ 1) หากคุณมีAsyncTaskและคุณแสดงDialogสิ่งที่เกิดขึ้นซึ่งทำให้การActivityโทรonPause()(อาจตรรกะบางอย่างใน AsyncTask ของคุณเองเช่นผู้ฟังก็จะรั่วไหล 2) ดังกล่าวข้างต้นDialogซึ่งถูกสร้างขึ้นด้วยที่Activity Contextไม่เคย ออกและActivityย้ายไป
เคล็ดลับ

5

"ความActivity has leaked window that was originally added...ผิดพลาด" เกิดขึ้นเมื่อคุณพยายามแสดงการแจ้งเตือนหลังจากที่มีประสิทธิภาพActivityfinished

คุณมีสองตัวเลือก AFAIK:

  1. คิดใหม่เข้าสู่ระบบของการแจ้งเตือนของคุณ: โทรdismiss()บนdialogก่อนที่จริงออกจากกิจกรรมของคุณ
  2. ใส่dialogในหัวข้อที่แตกต่างและเรียกใช้ในนั้นthread(เป็นอิสระจากปัจจุบันactivity)

5

นี่เป็นวิธีการแก้ปัญหาเมื่อคุณต้องการยกเลิก AlertDialog แต่ไม่ต้องการให้มีการอ้างอิงกับกิจกรรมภายใน

โซลูชันต้องการให้คุณมีandroidx.lifecycle การพึ่งพาในโครงการของคุณ (ฉันเชื่อว่าในขณะที่ความคิดเห็นมันเป็นข้อกำหนดทั่วไป)

สิ่งนี้ช่วยให้คุณสามารถมอบหมายการโต้ตอบของกล่องโต้ตอบไปยังวัตถุภายนอก (ผู้สังเกตการณ์) และคุณไม่จำเป็นต้องสนใจมันอีกต่อไปเพราะมันจะยกเลิกการเป็นสมาชิกโดยอัตโนมัติเมื่อกิจกรรมตาย (นี่คือข้อพิสูจน์: https://github.com/googlecodelabs/android-lifecycles/issues/5 )

ดังนั้นผู้สังเกตจะเก็บการอ้างอิงไปยังกล่องโต้ตอบและกิจกรรมเก็บการอ้างอิงถึงผู้สังเกตการณ์ เมื่อ "onPause" เกิดขึ้น - ผู้สังเกตการณ์จะยกเลิกการโต้ตอบและเมื่อ "onDestroy" เกิดขึ้น - กิจกรรมจะลบผู้สังเกตการณ์ดังนั้นจะไม่มีการรั่วไหลเกิดขึ้น (อย่างน้อยที่สุดฉันไม่เห็นข้อผิดพลาดใน logcat อีกต่อไป)

// observer
class DialogDismissLifecycleObserver( private var dialog: AlertDialog? ) : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun onPause() {
        dialog?.dismiss()
        dialog = null
    }
}
// activity code
private fun showDialog() {
        if( isDestroyed || isFinishing ) return
        val dialog = AlertDialog
            .Builder(this, R.style.DialogTheme)
            // dialog setup skipped
            .create()
        lifecycle.addObserver( DialogDismissLifecycleObserver( dialog ) )
        dialog.show()
}

4

ข้อยกเว้นหน้าต่างที่รั่วมีสองสาเหตุ:

1) แสดงไดอะล็อกเมื่อไม่มีบริบทของกิจกรรมเพื่อแก้ไขปัญหานี้คุณควรแสดงไดอะล็อกเฉพาะคุณเท่านั้นที่แน่ใจว่ามีกิจกรรมอยู่:

if(getActivity()!= null && !getActivity().isFinishing()){
        Dialog.show();
}

2) ไม่ยกเลิกการโต้ตอบอย่างเหมาะสมเพื่อแก้ปัญหาใช้รหัสนี้:

@Override
public void onDestroy(){
    super.onDestroy();
    if ( Dialog!=null && Dialog.isShowing() ){
        Dialog.dismiss();
}
}

4

คุณต้องทำให้ProgressdialogวัตถุในonPreExecuteวิธีการAsyncTaskและคุณควรdismissในonPostExecuteวิธี


4

ทางออกที่ดีที่สุดคือเพียงเพิ่มการโต้ตอบในการลองจับและยกเลิกการโต้ตอบเมื่อเกิดข้อยกเว้น

เพียงใช้รหัสด้านล่าง

 try {
        dialog.show();
    } catch (Exception e) {
        dialog.dismiss();
    }

3
ไม่ไดอะล็อกจะเป็นโมฆะหลังจากที่เรียกเสร็จแล้ว? ฉันคิดว่าdialog.dismiss()จะสร้างข้อผิดพลาดด้วย
Ashu Kumar

3

ในกรณีของฉันสาเหตุที่ฉันลืมรวมสิทธิ์ในไฟล์รายการ Android

ฉันจะทราบได้อย่างไร เช่นเดียวกับ @Bobby ที่กล่าวไว้ในความคิดเห็นภายใต้คำตอบที่ยอมรับเพียงเลื่อนขึ้นไปยังบันทึกของคุณและคุณจะเห็นเหตุผลหรือเหตุการณ์แรกที่ทำให้เกิดข้อยกเว้นจริงๆ เห็นได้ชัดว่าข้อความ "กิจกรรมรั่วหน้าต่างที่ถูกเพิ่มเข้ามาในตอนแรก" เป็นเพียงข้อยกเว้นที่เป็นผลมาจากสิ่งที่ข้อยกเว้นแรกคือ


3

ลองรหัสด้านล่างมันจะทำงานเมื่อใดก็ตามที่คุณจะยกเลิกการเจรจาความคืบหน้าและมันจะดูว่าอินสแตนซ์ที่มีอยู่หรือไม่

try {
        if (null != progressDialog && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

2

ทางออกที่ดีที่สุดคือสิ่งนี้ก่อนที่จะแสดงprogressbarหรือprogressDialog

if (getApplicationContext().getWindow().getDecorView().isShown()) {

  //Show Your Progress Dialog

}

มันไม่ได้ผลสำหรับฉัน ฉันมี Dialog.show () หลังจากการตอบสนองจากการโทร HTTP และเมื่อในขณะเดียวกันฉันหมุนหน้าจอกิจกรรมถูกถอดออก แต่ดูเหมือนว่าจะมี isShown == จริงก่อน Dialog.show () แล้ว Dialog ขัดข้องทั้งๆที่การตรวจสอบนี้
Michał Ziobro

1

เพียงตรวจสอบให้แน่ใจว่ากิจกรรมของคุณไม่ปิดโดยไม่คาดคิดเนื่องจากมีข้อยกเว้นบางอย่างเกิดขึ้นในรหัสของคุณ โดยทั่วไปจะเกิดขึ้นในงาน async เมื่อกิจกรรมเผชิญกับการปิดกำลังในวิธี doinBackground แล้ว asynctask กลับไปที่ onPostexecute วิธี


1

ฉันมีวิธีแก้ไขปัญหานี้อีกและต้องการทราบว่าดูเหมือนว่าใช้ได้สำหรับคุณ: แทนที่จะเลิกใช้งาน onDestroy ซึ่งดูเหมือนจะเป็นโซลูชันชั้นนำฉันจะขยาย ProgressDialog ...

public class MyProgressDialog extends ProgressDialog {

  private boolean isDismissed;

  public MyProgressDialog(Context context) {
    super(context);
  }

  @Override
  public void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    dismiss();
  }

  @Override
  public void dismiss() {
    if (isDismissed) {
      return;
    }
    try {
      super.dismiss();
    } catch (IllegalArgumentException e) {
      // ignore
    }
    isDismissed = true;
  }

นี่เป็นสิ่งที่ดีกว่า AFAIC เพราะคุณไม่จำเป็นต้องกดปุ่มโต้ตอบความคืบหน้าในฐานะสมาชิกเพียงแค่ยิง (แสดง) และลืม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.