Hoạt động đã bị rò rỉ cửa sổ ban đầu được thêm vào


1163

Lỗi này là gì và tại sao nó lại xảy ra?

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
Một cổ điển khác là khi định hướng thay đổi: stackoverflow.com/questions/1111980/ từ
rds

Câu trả lời:


1560

Bạn đang cố gắng hiển thị Hộp thoại sau khi bạn thoát khỏi Hoạt động.

[BIÊN TẬP]

Câu hỏi này là một trong những tìm kiếm hàng đầu trên google cho nhà phát triển Android, do đó, thêm một vài điểm quan trọng từ các bình luận, có thể hữu ích hơn cho nhà điều tra trong tương lai mà không đi sâu vào cuộc trò chuyện bình luận.

Trả lời 1 :

Bạn đang cố gắng hiển thị Hộp thoại sau khi bạn thoát khỏi Hoạt động.

Trả lời 2

Lỗi này có thể gây hiểu nhầm đôi chút trong một số trường hợp (mặc dù câu trả lời vẫn hoàn toàn chính xác) - tức là trong trường hợp của tôi, một Ngoại lệ chưa được xử lý đã bị ném vào AsyncTask, khiến Activity bị tắt, sau đó một tiến trình mở gây ra Ngoại lệ này .. vì vậy ngoại lệ 'thực' đã sớm hơn một chút trong nhật ký

Trả lời 3

Hủy bỏ cuộc gọi () trên phiên bản Hộp thoại bạn đã tạo trước khi thoát Hoạt động của mình, ví dụ như trong onPause () hoặc onDestroy ()


2
@Override void công khai onStop () {if (hộp thoại! = Null) {hộp thoại.dismiss (); hộp thoại = null; }}
Md.Tarikul Hồi giáo

14
Ngay cả sau 8 năm, điều này vẫn có liên quan! Tôi đã có ngoại lệ vì hoạt động đã bị đóng trong khi nó đang cố hiển thị AlertDialog của tôi (vì vậy Câu trả lời 2). Cuối cùng, tôi phát hiện ra rằng ứng dụng đã thêm một đối tượng "null" vào cảnh (không nên xảy ra nhưng nó đã xảy ra) nhưng nó không đưa ra một ngoại lệ nào nữa cho nó và toàn bộ sự việc bị che dấu bởi "rò rỉ" cửa sổ "ngoại lệ thay thế.
Neph

Có thể quét tất cả các hộp thoại đang mở và đóng tất cả chúng trong onStop () không? Tôi tạo các hộp thoại trong ListView khi nhấp vào các mục. Tôi không chắc chắn làm thế nào để lấy tham chiếu của họ từ onStop.
Myoch

1
Câu trả lời 3 là giải pháp tốt nhất. làm việc rất nhiều cho tôi Cảm ơn Kaze, Alex !!
amit bansode

mẹo bổ sung nếu bạn đang hiển thị hộp thoại trong một vòng lặp, đảm bảo vòng lặp được thoát sau khi kết thúc hoạt động
Thecarisma

406

Giải pháp là gọi dismiss()cho Dialogbạn đã tạo viewP.java:183trước khi thoát Activity, ví dụ như trong onPause(). Tất cả các Windows & Dialogs nên được đóng lại trước khi rời khỏi một Activity.


3
Vì vậy, khi người dùng xoay điện thoại, tất cả các hộp thoại sẽ bị loại bỏ ?? Điều đó không đúng.
LarsH

@LarsH như bạn có thể thấy, câu trả lời của tôi đã được viết cách đây hơn 7 năm và điều này hoàn toàn đúng vào thời điểm đó. Tôi không còn làm việc với Android nữa, nhưng dựa trên những gì tôi thấy trong tài liệu , nó vẫn có thể là trường hợp, nhưng Android đã đi một chặng đường dài kể từ khi (giới thiệu Fragment chỉ để đặt tên cho một cái), vì vậy bây giờ có lẽ dễ dàng hơn.
molnarm

108

Nếu bạn đang sử dụng AsyncTask, có lẽ thông điệp tường trình đó có thể là lừa đảo. Nếu bạn tra cứu trong nhật ký của mình, bạn có thể tìm thấy một lỗi khác, có thể là một lỗi trong doInBackground()phương pháp của bạn AsyncTask, đó là làm cho hiện tại của bạn Activitybị nổ tung, và do đó một khi AsyncTasktrở lại .. tốt, bạn biết phần còn lại. Một số người dùng khác đã giải thích rằng ở đây :-)


22
Đôi khi trong trường hợp đó tôi không thể nhìn thấy ngoại lệ thực sự. Để tìm ngoại lệ thực sự, chỉ cần nhận xét tiến trìnhDialog.show () và chạy lại ứng dụng .. bây giờ bạn thấy nó.
Bị kẹt

Chào các bạn! Như đã đề cập ở trên bởi @Stuck Tôi cũng không thể thấy ngoại lệ thực sự, Tôi đã làm gì? Tôi đã theo dõi nó bằng cách sử dụng các điểm ngắt và tôi phát hiện ra rằng tôi đang sử dụng một tham chiếu của một lớp Ứng dụng bên trong phương thức doInBackgroundcủa AsyncTasklớp nhưng không khai báo nó trong AndroidManifesttệp bằng cách sử dụng thuộc tính android:namenhư thế này : android:name="my.package.MyApplicationClass". Một thực hành tốt khi sử dụng AsyncTasknó là luôn nhớ khởi tạo cảnh báo của bạn bên trong phương thức onPreExecutevà loại bỏ nó onPostExecute.
GFPF

66

Tôi đã kích hoạt lỗi này bằng cách gọi nhầm hide()thay vì dismiss()trên một AlertDialog.


4
Chính xác những gì đã xảy ra với tôi. Ngoài ra, gọi ẩn () và sau đó đặt hộp thoại thành null cũng không phải là một lựa chọn hợp lệ.
Lucas Tulio

Tôi thực sự sẽ biết vấn đề đằng sau này. Nhưng gọi sa thải () đã giúp tôi!
Karoly

59

Bạn có thể nhận được ngoại lệ này chỉ bằng một lỗi đơn giản / ngớ ngẩn, bằng cách (chẳng hạn) vô tình gọi finish()sau khi đã hiển thị AlertDialog, nếu bạn bỏ lỡ một câu lệnh ngắt trong câu lệnh chuyển đổi ...

   @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;
        }
    }

Các finish()phương pháp sẽ đóng Activity, nhưng AlertDialogvẫn hiển thị!

Vì vậy, khi bạn đang nhìn chăm chú vào mã, tìm kiếm các vấn đề luồng xấu hoặc mã hóa phức tạp và như vậy, đừng để mất rừng cho cây. Đôi khi nó có thể chỉ là một cái gì đó đơn giản và ngu ngốc như một tuyên bố phá vỡ mất tích. :)


Nhiều hay ít chính xác vấn đề của tôi. Đã gọi kết thúc trong onError sau khi hộp thoại được tạo, không phải trong onClick cho nút loại bỏ.
jbass

46

Các câu trả lời cho câu hỏi này đều đúng, nhưng hơi khó hiểu để tôi thực sự hiểu tại sao. Sau khi chơi khoảng 2 giờ, lý do cho lỗi này (trong trường hợp của tôi) đánh tôi:

Bạn đã biết, từ việc đọc các câu trả lời khác, rằng có X has leaked window DecorView@d9e6131[]lỗi có nghĩa là một hộp thoại đã mở khi ứng dụng của bạn đóng. Nhưng tại sao?

Có thể là do ứng dụng của bạn bị sập vì một số lý do khác trong khi hộp thoại của bạn đang mở

Điều này dẫn đến việc đóng ứng dụng của bạn do một số lỗi trong mã của bạn, dẫn đến hộp thoại vẫn mở cùng lúc với ứng dụng của bạn bị đóng do lỗi khác.

Vì vậy, nhìn qua logic của bạn. Giải quyết lỗi đầu tiên và sau đó lỗi thứ hai sẽ tự khắc phụcnhập mô tả hình ảnh ở đây

Một lỗi gây ra lỗi khác, gây ra lỗi khác, như DOMINOS!


2
Không thể tin rằng điều này chỉ có một upvote .. hoặc chúng tôi thực sự rất tệ trong việc lập trình hahaha Tôi cũng thích sự tương tự domino của bạn
user2161301 15/07/17

Giải quyết lỗi đầu tiên và lỗi thứ hai sẽ không xảy ra . Sự tương tự này đã giúp tôi.
itabdullah

Điều này không hoàn toàn đúng, các trường hợp như xoay điện thoại cũng có thể khiến xoay vòng "hoạt động" xảy ra.
Saletanth Karumanaghat

36

Vấn đề này phát sinh khi cố gắng hiển thị Hộp thoại sau khi bạn thoát khỏi Hoạt động.

Tôi chỉ giải quyết vấn đề này chỉ bằng cách viết mã sau đây:

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

Về cơ bản, từ lớp nào bạn đã bắt đầu tiến trìnhDialog, ghi đè phương thức onDestroy và thực hiện theo cách này. Nó đã giải quyết vấn đề "Hoạt động có cửa sổ bị rò rỉ".


onDestroy không được bảo đảm để được gọi. Tốt hơn là đặt mã đó vào OnPause hoặc onStop
Amruta-Pani

19

Gần đây tôi đã phải đối mặt với vấn đề tương tự.

Lý do đằng sau vấn đề này là hoạt động bị đóng trước khi hộp thoại bị loại bỏ. Có nhiều lý do cho những điều trên xảy ra. Những người được đề cập trong các bài viết trên cũng đúng.

Tôi đã rơi vào một tình huống, bởi vì trong luồng, tôi đang gọi một hàm đang ném ngoại lệ. Do đó, cửa sổ đã bị loại bỏ và do đó là ngoại lệ.


16

Loại bỏ hộp thoại khi hủy hoạt động

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

nếu pDialog là null thì điều này sẽ gây ra lỗi khi bạn truy vấn trạng thái của hộp thoại null
Jonathan Dunn

1
không, nó sẽ không @JonDunn, bởi vì Java sẽ không xử lý boolean thứ hai nếu cái đầu tiên là sai
matdev

13

Điều này có thể giúp đỡ.

if (! isFinishing()) {

    dialog.show();

    }

2
Trong số hàng trăm câu trả lời tương tự, không có ai chỉ ra cách kiểm tra nếu cửa sổ tồn tại. Vì vậy, bạn tiết kiệm cho tôi một chút thời gian để tìm cách để làm điều đó. Cảm ơn.
kolyaseg

11

Tôi đã có thông báo lỗi tối nghĩa tương tự và không biết tại sao. Đưa ra manh mối từ các câu trả lời trước, tôi đã thay đổi các cuộc gọi không phải GUI của mình thành mDialog.finish () thành mDialog.dismiss () và các lỗi đã biến mất. Điều này không ảnh hưởng đến hành vi của widget của tôi nhưng nó gây bối rối và có thể đã đánh dấu một rò rỉ bộ nhớ quan trọng.


Nhận thấy rằng tôi đã thực hiện một mDialog. Leather () trước khi kết thúc cuộc gọi (). Thay đổi nó thành mDialog.dismiss () đã thực hiện thủ thuật.
mays

11

Tôi đã nhận được các bản ghi này trong ứng dụng trình phát video của tôi. Những tin nhắn này đã bị ném trong khi trình phát video đã bị đóng. Thật thú vị, tôi đã từng nhận được các bản ghi này một lần trong một vài lần chạy một cách ngẫu nhiên. Ngoài ra ứng dụng của tôi không liên quan đến bất kỳ progressdialog. Cuối cùng, tôi đã giải quyết vấn đề này với việc thực hiện dưới đây.

@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();
}

Ghi đè OnPausecuộc gọi với mVideoView.pause()và đặt visibilitythành GONE. Bằng cách này tôi có thể giải quyết Activity has leaked windowvấn đề lỗi " ".


tôi cũng đối mặt với vấn đề tương tự tôi đã thêm các dòng mã này vào mã của mình nhưng nó không hoạt động và gây ra lỗi tương tự "android.view.WindowLeaked đã được thêm vào ban đầu" và cũng không phát video và đưa ra "Video không thể phát"
User42590

10

Tôi đã có cùng một vấn đề và tìm thấy trang này, và trong khi tình huống của tôi khác, tôi đã gọi finishtừ một ifkhối trước khi nó xác định hộp cảnh báo.

Vì vậy, chỉ đơn giản là gọi dismisssẽ không hoạt động (vì nó chưa được thực hiện) nhưng sau khi đọc câu trả lời của Alex Volovoy và nhận ra đó là hộp cảnh báo gây ra nó. Tôi đã cố gắng thêm một tuyên bố trở lại ngay sau khi kết thúc bên trong ifkhối đó và điều đó đã khắc phục vấn đề.

Tôi nghĩ rằng một khi bạn gọi xong thì nó dừng mọi thứ lại và kết thúc ngay tại đó, nhưng không được. Nó dường như đi đến cuối khối mã sau đó kết thúc.

Vì vậy, nếu bạn muốn thực hiện một tình huống đôi khi nó sẽ kết thúc trước khi thực hiện một số mã, bạn phải đặt một tuyên bố trả lại ngay sau khi kết thúc hoặc nó sẽ tiếp tục và hành động như kết thúc được gọi vào cuối khối mã không phải nơi bạn gọi nó. Đó là lý do tại sao tôi nhận được tất cả những lỗi kỳ lạ.

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();
}

Nếu bạn không đặt trả lại ngay sau khi tôi gọi kết thúc ở đó, nó sẽ hoạt động như thể bạn đã gọi nó sau alert.show();và do đó nó sẽ nói rằng cửa sổ bị rò rỉ bằng cách hoàn thành ngay sau khi bạn làm hộp thoại xuất hiện, mặc dù đó là không phải là trường hợp, nó vẫn nghĩ rằng nó là.

Tôi nghĩ tôi sẽ thêm cái này vào đây vì nó cho thấy lệnh kết thúc hoạt động khác đi và tôi nghĩ nó đã làm và tôi đoán có những người khác cũng nghĩ giống như tôi trước khi tôi phát hiện ra điều này.


7

Đây không phải là câu trả lời cho câu hỏi nhưng nó có liên quan đến chủ đề.

Nếu hoạt động đã xác định một thuộc tính trong Bản kê khai

 android:noHistory="true"

sau đó sau khi thực hiện onPause (), bối cảnh hoạt động bị mất. Vì vậy, tất cả các chế độ xem sử dụng bối cảnh này có thể gây ra lỗi này.


Bạn có thể liên hệ bất cứ điều gì tương tự cho progessdialog.show().. và progressdialog.hide()trong asynctaskcùng một hoạt động thay vì onPause()từ activity?? hãy xem vấn đề của tôi ... stackoverflow.com/questions/39332880/
Kẻ

1
nó hoạt động hoàn hảo với tôi: android: noHistory = "true"
Shohel Rana

6

Không chỉ cố gắng hiển thị cảnh báo mà còn có thể được gọi khi bạn hoàn thành một trường hợp cụ thể của hoạt động và cố gắng bắt đầu hoạt động / dịch vụ mới hoặc cố gắng ngăn chặn nó.

Thí dụ:

OldActivity instance;

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

6

Nói chung, sự cố này xảy ra do hộp thoại tiến trình: bạn có thể giải quyết vấn đề này bằng cách sử dụng bất kỳ một trong các phương pháp sau trong hoạt động của mình:

 // 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

Có vấn đề khi tôi hoàn thành một Hoạt động khi ProgressDialog vẫn được hiển thị.

Vì vậy, đầu tiên ẩn Hộp thoại và sau đó kết thúc hoạt động.


5

Hãy thử mã này:

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

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

}

progressdialog.dismiss();điều này có thể tạo NullPulumException.
tpk

5

Điều này có thể là nếu bạn có một lỗi tại doInBackground()chức năng và có mã này.

Cố gắng thêm hộp thoại cuối cùng. Đầu tiên doInBackground()chức năng kiểm tra và sửa chữa

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

Điều này xảy ra với tôi khi tôi đang sử dụng ProgressDialogtrong AsyncTask. Trên thực tế tôi đang sử dụng hide()phương pháp trong onPostExecute. Dựa trên câu trả lời của @ Alex Volovoy tôi cần phải sử dụng dismiss()với ProgressDialogđể xoá bỏ nó trong onPostExecute và thực hiện nó.

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

progressDialog.dismiss(); // Use it

Đây không thực sự là câu trả lời đầy đủ. Có hai cách để rò rỉ một hộp thoại. 1) Nếu bạn có một AsyncTaskvà bạn hiển thị Dialog, sau đó một cái gì đó xảy ra mà làm cho Activitycuộc gọi onPause()(có thể một số logic trong AsyncTask bạn thân, giống như một người biết lắng nghe, sau đó nó sẽ bị rò rỉ. 2) Như đã đề cập ở trên, Dialogđược tạo ra với điều đó Activity Contextlà không bao giờ gạt bỏ và Activitydi chuyển trên.
lừa đảo

5

Các " Activity has leaked window that was originally added..." lỗi xảy ra khi bạn cố gắng hiển thị một cảnh báo sau khi Activitylà một cách hiệu quả finished.

Bạn có hai tùy chọn AFAIK:

  1. Xem xét lại thông tin đăng nhập của thông báo của bạn: gọi dismiss()vào dialogtrước khi thực sự thoát khỏi hoạt động của bạn.
  2. Đặt dialogmột chủ đề khác và chạy nó trên đó thread(độc lập với hiện tại activity).

5

Đây là một giải pháp khi bạn muốn loại bỏ AlertDialog nhưng không muốn giữ một tham chiếu đến nó trong hoạt động.

giải pháp yêu cầu bạn phải có sự phụ thuộc androidx.lifecycle trong dự án của bạn (tôi tin rằng tại thời điểm nhận xét đó là một yêu cầu chung)

điều này cho phép bạn ủy quyền loại bỏ hộp thoại cho đối tượng bên ngoài (người quan sát) và bạn không cần phải quan tâm đến nó nữa, vì nó tự động hủy đăng ký khi hoạt động chết. (đây là bằng chứng: https://github.com/googlecodelabs/android-lifec đua /issues / 5 ).

vì vậy, người quan sát giữ tham chiếu đến hộp thoại và hoạt động giữ tham chiếu đến người quan sát. khi "onPause" xảy ra - người quan sát bỏ qua hộp thoại và khi "onDestroy" xảy ra - hoạt động sẽ loại bỏ người quan sát, vì vậy không có rò rỉ nào xảy ra (tốt, ít nhất tôi không thấy lỗi trong logcat nữa)

// 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

Ngoại lệ cửa sổ bị rò rỉ có hai lý do:

1) hiển thị hộp thoại khi Bối cảnh hoạt động không tồn tại, để giải quyết vấn đề này, bạn chỉ hiển thị hộp thoại mà bạn chắc chắn Hoạt động tồn tại:

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

2) không loại bỏ hộp thoại một cách thích hợp, để giải quyết sử dụng mã này:

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

4

Bạn phải tạo Progressdialogđối tượng trong onPreExecutephương thức AsyncTaskvà bạn nên làm dismissnó trên onPostExecutephương thức.


4

Giải pháp tốt nhất là chỉ cần thêm hộp thoại vào hộp thoại thử và loại bỏ khi xảy ra ngoại lệ

Chỉ cần sử dụng mã dưới đây

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

3
không phải hộp thoại sẽ bị vô hiệu hóa sau khi gọi xong?, tôi nghĩ dialog.dismiss()cũng sẽ tạo ra lỗi
Ashu Kumar

3

Trong trường hợp của tôi, lý do là tôi đã quên bao gồm quyền trong tệp kê khai Android.

Làm thế nào tôi tìm ra? Chà, giống như @Bulk nói trong một bình luận bên dưới câu trả lời được chấp nhận, chỉ cần cuộn thêm lên nhật ký của bạn và bạn sẽ thấy lý do hoặc sự kiện đầu tiên thực sự đã ném Ngoại lệ. Rõ ràng, thông báo "Hoạt động đã bị rò rỉ cửa sổ ban đầu được thêm vào" chỉ là một Ngoại lệ xuất phát từ bất kỳ Ngoại lệ đầu tiên là gì.


3

Hãy thử mã bên dưới, nó sẽ hoạt động bất cứ lúc nào bạn sẽ bỏ qua cuộc đối thoại tiến trình và nó sẽ xem liệu phiên bản của nó có khả dụng hay không.

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

2

Giải pháp tốt nhất là đặt cái này trước khi hiển thị progressbarhoặcprogressDialog

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

  //Show Your Progress Dialog

}

Điều này không làm việc cho tôi. Tôi có Dialog.show () sau khi phản hồi từ cuộc gọi HTTP và trong khi đó, tôi xoay màn hình Hoạt động bị tách ra nhưng dường như có isShown == true trước Dialog.show () và sau đó Dialog gặp sự cố mặc dù kiểm tra này
Michał Ziobro

1

Chỉ cần đảm bảo rằng hoạt động của bạn không đóng cửa bất ngờ do một số ngoại lệ được nêu ở đâu đó trong mã của bạn. Nói chung, nó xảy ra trong tác vụ không đồng bộ khi hoạt động phải đối mặt với việc đóng cửa trong phương thức doinBackground và sau đó asynctask trở lại phương thức onPostexecute.


1

Tôi có một giải pháp khác cho vấn đề này và muốn biết liệu nó có hợp lệ với bạn không: thay vì loại bỏ trong onDestroy, dường như là giải pháp hàng đầu, tôi đang mở rộng 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;
  }

Điều này tốt hơn, AFAIC, vì bạn không phải giữ hộp thoại tiến trình với tư cách là thành viên, chỉ cần bắn (hiển thị) và quên

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.