2009-05-21 27 views
22

Tôi đang sử dụng showDialog()dismissDialog() để hiển thị hộp thoại tiến trình trong ứng dụng của mình. Đã chuyển từ việc tạo hộp thoại và gọi show() trên đó để sử dụng tính năng này để lưu trạng thái khi thay đổi hướng.Android - dismissDialog không loại bỏ hộp thoại

Nhưng khi tôi thay đổi hướng từ chân dung-> phong cảnh-> chân dung, dismissDialog() không còn loại bỏ hộp thoại nữa. Hộp thoại luôn ở đó và tôi cần nhấn nút quay lại để nó biến mất.

Bất kỳ lý do nào khiến nó hoạt động theo cách đó?

Sửa

Để khắc phục vấn đề này, tôi đã cố gắng thêm một removeDialog() trong onDestroy() để hộp thoại không được tạo ra/hiển thị hai lần và trước khi thay đổi hướng, hộp thoại được lấy ra. Cố gắng thêm báo cáo đăng nhập và xem những gì sẽ xảy ra

05-21 12:35:14.064: DEBUG/MyClass(193): *************callingShowDialog 
05-21 12:35:14.064: DEBUG/MyClass(193): *************onCreareDialog 

05-21 12:35:15.385: DEBUG/MyClass(193): *************onSaveInstanceState 
05-21 12:35:15.415: DEBUG/MyClass(193): *************onDestroy 

05-21 12:35:15.585: DEBUG/MyClass(193): *************callingShowDialog 
05-21 12:35:15.585: DEBUG/MyClass(193): *************onCreareDialog 
05-21 12:35:15.715: DEBUG/MyClass(193): *************onCreareDialog 
05-21 12:35:17.214: DEBUG/MyClass(193): *************onSaveInstanceState 
05-21 12:35:17.214: DEBUG/MyClass(193): *************onDestroy 

05-21 12:35:17.275: ERROR/WindowManager(193): android.view.WindowLeaked: Activity com.android.MyClass has leaked window com.android.internal.policy.impl.P[email protected] that was originally added here 

05-21 12:35:17.395: DEBUG/MyClass(193): *************callingShowDialog 
05-21 12:35:17.395: DEBUG/MyClass(193): *************onCreareDialog 
05-21 12:35:17.475: DEBUG/MyClass(193): *************onCreareDialog 

Nếu chúng ta thấy ở đây, ban đầu khi hoạt động được hiển thị, onCreateDialog được gọi một lần và về việc thay đổi phương hướng, onSaveInstanceState và onDestroy được gọi.

Nhưng sau đó, onCreateDialog được gọi hai lần (một lần gọi hàm showDialog mà tôi tạo, nhưng tại sao lại là lần thứ 2?) Và điều này xảy ra mỗi lần tôi thay đổi hướng.

Bất kỳ ý tưởng nào tại sao điều đó xảy ra?

Cảm ơn một lần nữa

+0

Ai đó có thể giúp tôi giải quyết vấn đề này? Tôi đã nhìn thấy nhiều bài đăng và blog về vấn đề này nhưng dường như không có giải pháp nào hoạt động. – lostInTransit

Trả lời

0

Xin lưu ý rằng mỗi khi bạn thay đổi hướng, một trường hợp mới của Activity của bạn (và do đó của bạn Dialog qua onCreateDialog) được tạo ra. Bạn có thể xác minh điều này bằng cách thêm một câu lệnh đăng nhập vào một trong hai hàm tạo.

Mặc dù khó nói mà không cần xem qua mã của bạn, tôi đoán bạn đang gọi số dismissDialog trên phiên bản cũ hơn của Activity.

Hãy xem xét những điều sau Activity mà chỉ đơn giản cho thấy một trống Dialog khi một nút được nhấp và bắt đầu một TimerTask để gạt bỏ nó sau 10 giây:

public class Test extends Activity { 

    private Dialog dialog; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.test); 
     Button btn = (Button) findViewById(R.id.testButton); 
     btn.setOnClickListener(new OnClickListener() { 
      public void onClick(View v) { 
       new Timer().schedule(new TimerTask() { 
        @Override public void run() { dialog.dismiss(); } 
       }, 10000); 
       Test.this.showDialog(1); 
      } 
     }); 
    } 

    @Override 
    protected Dialog onCreateDialog(int id) { 
     if(id == 1) { 
      if(dialog == null) { dialog = new Dialog(this); } 
      return dialog; 
     } 
     return super.onCreateDialog(id); 
    } 
} 

Mã này có một vấn đề tương tự như bạn đang mô tả : Nếu - trong 10 giây - hướng được thay đổi, Dialog sẽ không bao giờ bị loại bỏ. Tại sao? Bởi vì tại thời điểm TimerTaskrun, một bộ khác nhau toàn bộ TestDialog trường hợp đã được tạo ra (trong thay đổi hướng) và dialog dụ tham khảo biến các 's TimerTask một trường hợp Test đó là khác nhau từ một trong đó hiện đang hoạt động trên màn hình.

Rõ ràng có một số cách để đối phó với vấn đề này (chủ yếu là tùy thuộc vào ứng dụng của bạn), một cách nhanh chóng (bẩn?) Cách để sửa chữa các mã trên sẽ chỉ đơn giản là làm cho dialog lĩnh vực static:

private static Dialog dialog;
+0

Cảm ơn Josef. Nhưng khi bạn nói rằng sửa chữa thực sự là một hack! Thay vào đó, tôi đang nghĩ đến việc sử dụng Dịch vụ. Cho đến khi dịch vụ đang chạy, tôi sẽ hiển thị hộp thoại. Đó có phải là cách đúng đắn để giải quyết vấn đề này không? – lostInTransit

+0

Nó thực sự phụ thuộc vào ứng dụng. Nhưng bạn nói đúng, (rất) nhiệm vụ chạy dài chắc chắn nên được đưa vào dịch vụ. –

4

Gần đây tôi đã gặp phải vấn đề này.Tôi có một ứng dụng với nhiều hoạt động tất cả cần truy cập các đối tượng toàn cục (kết nối db, danh sách dữ liệu, vv) và vì vậy tôi đã override lớp Application. Để kết thúc, tôi nhận ra tất cả những gì tôi cần là một tham chiếu đến phiên bản mới nhất của hộp thoại tiến trình trong runnable của tôi mà tôi đang sử dụng để loại bỏ hộp thoại. Đây là những gì tôi đã đưa ra và nó một cách duyên dáng sống sót reorientations điện thoại:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    addPreferencesFromResource(R.xml.preferences); 

    mHandler = new Handler(); 
    mApplication = (MyApplication)getApplication(); 

    mFileStorage = (CheckBoxPreference)getPreferenceScreen().findPreference("fileStorage"); 

    mProgressDialog = new ProgressDialog(this); 

    mProgressDialog.setTitle("Location Update"); 
    mProgressDialog.setMessage("Moving databases to new storage location."); 
    mProgressDialog.setIndeterminate(true); 
    mProgressDialog.setCancelable(false); 
    mProgressDialog.setCanceledOnTouchOutside(false); 

    mApplication.setProgressDialog(mProgressDialog); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 

    mPreferences = PreferenceManager.getDefaultSharedPreferences(this); 
    mPreferences.registerOnSharedPreferenceChangeListener(this); 

    if (sUpdateThread != null && sUpdateThread.isAlive()) { 
     mProgressDialog.show(); 
    } 
} 

@Override 
protected void onPause() { 
    super.onPause(); 

    mPreferences.unregisterOnSharedPreferenceChangeListener(this); 

    if (sUpdateThread != null && sUpdateThread.isAlive()) { 
     mProgressDialog.hide(); 
     mApplication.setProgressDialog(null); 
    } 
} 

.... công cụ ngẫu nhiên ở đây ....

private Runnable showProgressRunnable = new Runnable() { 
    public void run() { 
     mProgressDialog.show(); 
    } 
}; 

private Runnable hideProgressRunnable = new Runnable() { 
    public void run() { 
     if (mApplication.getProgressDialog() != null) { 
      mApplication.getProgressDialog().dismiss(); 
     } 
    } 
}; 

thread làm một mHandler.post (showProgressRunnable) khi nhiệm vụ bắt đầu và sau đó thực hiện một mHandler.post (hideProgressRunnable) khi nhiệm vụ kết thúc. Vì tham chiếu đến ProgressDialog mới nhất hiện được lưu trữ trong lớp Ứng dụng, tôi có thể đóng nó một cách đáng tin cậy vì tôi không còn giữ một tham chiếu đối tượng cũ nữa.

liên kết cho hậu thế: http://developer.android.com/reference/android/app/Application.html

0

Sau khi tìm kiếm thông qua tất cả các loại diễn đàn, tôi chỉ làm những điều sau đây:

tôi gọi ShowDialog (MyDialogID) VÀ dismissDialog (MyDialogId) ra khỏi handleMessage (MyMessage) Phương thức từ trình xử lý của tôi.

Trước đó tôi gọi showDialog trong phương thức onCreate() của tôi và cố gắng loại bỏ hộp thoại trong xử lý-Tin nhắn. Tại sao điều này giải quyết vấn đề, tôi không thể nói.

6

Tôi đã chạy vào điều này khi hiển thị hộp thoại trong ghi đè onCreate của Hoạt động. Hãy thử di chuyển mã khiến hộp thoại được hiển thị trong ghi đè onPostCreate thay thế. Điều này dường như làm việc cho tôi.

+0

Tôi đã thấy cùng một vấn đề với showDialog() trong onCreate() - mặc dù điều này dường như chỉ xảy ra khi bắt đầu ứng dụng thông qua trình gỡ lỗi. Di chuyển showDialog() sang onPostCreate() đã thực hiện công việc cho mee - thanks! – sstn

+0

Giải pháp tuyệt vời, chỉ cần sử dụng OnPostCreate để khởi chạy hộp thoại ... @Override void công khai onPostCreate (Bundle savedInstanceState) { super.onCreate (savedInstanceState); launch_app(); } –

+0

Đây là lỗi tài liệu trên Android: http://code.google.com/p/android/issues/detail?id=24646 –

7

Giải pháp tốt nhất cho tôi dường như sử dụng removeDialog (id) thay vì dismissDialog(); Ít sử dụng lại theo cách này, nhưng an toàn hơn (không ném bất kỳ thứ gì) và không có vấn đề gì khi thay đổi định hướng.

3

Sau khi nhấn nút trang chủ và điều hướng đến ứng dụng đúng ngữ pháp (thay đổi ngôn ngữ thiết bị), khi tôi quay lại ứng dụng, hộp thoại mới không thể đóng được qua dismissDialog (Tôi đã mở hộp thoại từ hoạt động trênCreate).

Giải pháp là gọi removeDialog thay vì dissmissDialog(). Điều này đã được đề xuất bởi Harri ở trên, nhiều thx.

Tôi đã tạo ra một báo cáo lỗi Android:

13858


Giải pháp là tạo ra hộp thoại của bạn sử dụng OnPostCreate thay vì OnCreate. Tôi đã thêm thông tin đó vào báo cáo lỗi và được đề xuất cải thiện dialog documentation.

5

Tôi đã lãng phí hơn một ngày trên một vấn đề như thế này với các hộp thoại không bị loại bỏ khi gọi đến dismissDialog. Nó xảy ra sau khi quay màn hình đầu tiên của tôi và không bao giờ làm việc sau đó. Tôi đã sử dụng một AsyncTask bên ngoài đã được thông qua một tham chiếu đến nhà nước một cách rõ ràng.

Cuối cùng giải pháp thực sự đơn giản .... removeDialog(int) thay vì dismissDialog(int).

Tôi đã dành những gì cảm thấy như mãi mãi chứng minh bản thân mình, tôi đã làm việc sa thải vào hoạt động chính xác và kiểm tra số lần mọi thứ được gọi là vv, nhưng nó được gây ra bởi một số jiggerypokery đằng sau hậu trường.

0

Tôi đã thử nghiệm cùng một vấn đề. Tôi đã tạo một số AlertDialog và một số ProgressDialog bên trong số gọi lại onCreateDialog() và hiển thị chúng từ số onCreate(). Tạo các hộp thoại này trực tiếp trong onCreate (mà không cần sử dụng onCreateDialog()) và loại bỏ chúng trong onPause() đã làm việc cho tôi! Dựa trên https://stackoverflow.com/a/5693467/955619

0
private AlertDialog alert11 = null; 
public void gpsDialog(){ 
    if (alert11 == null || !alert11.isShowing()) { 
     AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this); 
     builder1.setMessage("GPS not On"); 
     builder1.setCancelable(true); 

     builder1.setPositiveButton("Enable GPS", 
      new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface dialog, int id) { 

        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); 
        MainActivity.this.startActivity(intent); 
        dialog.dismiss(); 
       } 
      }); 

     builder1.setNegativeButton("Cancel", 
      new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface dialog, int id) { 
        dialog.dismiss(); 
       } 
      }); 

    alert11 = builder1.create(); 

    alert11.show(); 

    } 

} 
Các vấn đề liên quan