2010-11-19 14 views
6

Tôi đã một ứng dụng mà bạn có thể hiển thị và đóng vài Dialogs với:Android RuntimeException onCreateDialog đã không tạo ra một hộp thoại cho id

showDialog(...) 
removeDialog(...) 

tôi chơi một chút với các ứng dụng và khi không có bất kỳ Dialog trên màn hình, tôi nhấn nút menu và tôi đi đến màn hình chính của Android.

Sau một thời gian, tôi nhập lại vào ứng dụng của tôi và đôi khi, tôi nhận được RuntimeException này:

java.lang.IllegalArgumentException: Activity#onCreateDialog did not create a dialog for id 4 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621) 
    at android.app.ActivityThread.access$2200(ActivityThread.java:126) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:123) 
    at android.app.ActivityThread.main(ActivityThread.java:4595) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:521) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
    at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.IllegalArgumentException: Activity#onCreateDialog did not create a dialog for id 4 
    at android.app.Activity.createDialog(Activity.java:878) 
    at android.app.Activity.restoreManagedDialogs(Activity.java:867) 
    at android.app.Activity.performRestoreInstanceState(Activity.java:815) 
    at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1096) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2565) 
    ... 11 more 

Bất kỳ ý tưởng?

Cảm ơn bạn rất nhiều.

UPDATE, biết thêm thông tin:

Việc thực hiện onCreateDialog hiện nay là:

protected Dialog onCreateDialog(int id){ 
Builder b = new AlertDialog.Builder(this); 
if(id == 4){ 
    b.setMessage(...); 
    b.setItems(items, new DialogInterface.OnClickListener(){ 
    public void onClick(DialogInterface dialog, int which){ 
    Intent i = new Intent(Current.this, Another.class); 
    startActivity(i); 
    } 
    }); 
    return b.create(); 
} 
return null; 
} 

Để gọi chức năng này tôi làm:

removeDialog(4); 
showDialog(4); 

Trả lời

2

Sau khi gặp sự cố tương tự này (và tìm kiếm rằng gọi removeDialog từ bên trong không hoạt động đáng tin cậy), tôi đã phát triển cách giải quyết có vẻ hoạt động (mặc dù nó được thừa nhận là hack).

Như đã thấy trong grepcode link posted by antslava, trong phương pháp performRestoreInstanceState, onRestoreInstanceState được gọi ngay trước restoreManagedDialogs và được truyền cùng một ví dụ của Bundle savedInstanceState.

final void performRestoreInstanceState(Bundle savedInstanceState) { 
    onRestoreInstanceState(savedInstanceState); 
    restoreManagedDialogs(savedInstanceState); 
} 

Như vậy, có cơ hội để thay đổi Bundle savedInstanceState được truyền cho restoreManagedDialogs từ bên trong phương pháp onRestoreInstanceState.

Để ngăn chặn bất kỳ và tất cả các hộp thoại quản lý từ được khôi phục, người ta có thể thực hiện onRestoreInstanceState theo cách sau:

// This same variable is defined as private in the Activity class. I need 
// access to it, so I redefine it here. 
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs"; 

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) { 
    super.onRestoreInstanceState(savedInstanceState); 
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG); 
    if (null != b) { 
     savedInstanceState.remove(SAVED_DIALOGS_TAG); 
    } 
} 

Điều này làm cho Bundle tham chiếu bởi chính "android:savedDialogs" phải được loại bỏ từ Bundle savedInstanceState, mà sau đó gây ra các cuộc gọi đến restoreManagedDialogs để quay trở lại ngay lập tức khi phát hiện thấy khóa này không thể tìm thấy:

private void restoreManagedDialogs(Bundle savedInstanceState) { 
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG); 
    if (b == null) { 
     return; 
    } 
    ... 
} 

Điều này sẽ gây ra onCreateDialog không được gọi trong khi khôi phục Hoạt động, có hiệu quả "ẩn" bất kỳ hộp thoại nào, do đó ngăn chặn tình huống mà người dùng phải trả lại null từ onCreateDialog khi xảy ra.

Đây không phải là giải pháp 'một kích thước phù hợp với tất cả', nhưng với các yêu cầu của tôi, dường như nó phù hợp với hóa đơn. Bằng cách xem xét mã trong grepcode đối với một số phiên bản nền tảng (1.6, 2.1, 2.2, 2.2.2 và 4.0.3), có vẻ như giải pháp này sẽ hoạt động nhất quán với những triển khai hiện có này.

0

Bạn đã thực hiện OnCreateDialog như đã trình bày here? Khi bạn gọi showDialog (4) lần đầu tiên, OnCreateDialog (4) sẽ được gọi và bạn cần tạo hộp thoại và trả về từ phương thức này.

+0

Yup, tất cả mã đều hoạt động hoàn toàn tốt. Ứng dụng không sụp đổ ở bất cứ đâu. Tôi hiện đang xem các hộp thoại bật lên và đóng hoàn hảo. Vấn đề bắt đầu ngẫu nhiên khi tôi khởi động lại ứng dụng. – zegnus

0

Bạn có trả lời đúng hộp thoại trong onCreateDialog không? Nếu bạn đã làm dialog.show() trong hộp thoại tạo ra nhưng trả lại một số hộp thoại khác bạn có lẽ có thể nhận được kết quả như thế.

Hoặc bạn đang làm bất kỳ loại thao tác trong của đối tượng thoại trong onPrepareDialog

+0

Yup, hộp thoại được tạo tốt với Builder b = new AlertDialog.Builder (this); ...; return b.create(); Mỗi khi tôi hiển thị hộp thoại tôi gọi removeDialog (4) và sau đó showDialog (4) vì nội dung của hộp thoại thay đổi. Tôi không ghi đè lênPrepareDialog ... – zegnus

11

Trong mức API 8, onCreateDialog(int)deprecated ủng hộ onCreateDialog(int,Bundle). Nếu bạn chỉ thực hiện phương pháp sau và chạy ứng dụng trên thiết bị có cấp API thấp hơn 8, bạn sẽ nhận được thông báo lỗi được mô tả.

Giải pháp là để thực hiện onCreateDialog(int)

+0

Hi mndrix, mục tiêu hiện tại của tôi là 8 nhưng minversion của tôi là 3. Tôi đã cập nhật bài đăng với thực thi onCreateDialog (int) của tôi. Cảm ơn! – zegnus

4

Đối với SDK phiên bản < 8, nếu bạn quay lại null trong onCreateDialog bạn sẽ có được ngoại lệ java.lang.IllegalArgumentException.

+0

Tuyệt vời, có thể là vậy. Trong hộp thoại số 4 của tôi, tôi đã kiểm tra nội bộ và nếu nó không thành công, nó sẽ trả về null. Tôi rằng đây có thể là lỗi. Mặc dù trong tài liệu chính thức, có tùy chọn trả về http://developer.android.com/guide/topics/ui/dialogs.html rỗng nhưng tôi nghĩ rằng vấn đề là trước đây, ứng dụng có thể hiển thị hộp thoại , sau đó người dùng truy cập vào một ứng dụng khác và khi anh ấy quay trở lại, ứng dụng sẽ cố gắng khôi phục hộp thoại nhưng thời gian này trả về giá trị rỗng. Tôi sẽ kiểm tra nó, cảm ơn! – zegnus

+1

Tại đây, bạn có thể xem http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/app/Activity.java#Activity.createDialog%28java .lang.Integer% 2Candroid.os.Bundle% 29. Và để sửa chữa nó, bạn cần sử dụng phương thức removeDialog, bởi vì phương thức này loại bỏ hộp thoại của bạn khỏi mManagedDialogs. – antslava

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