2012-01-30 46 views
14

Có, tôi đã đọc vô số câu hỏi liên quan đến cùng một vấn đề.Hoạt động đã bị rò rỉ cửa sổ/hộp thoại (điều này một lần nữa!)

Mã của tôi rất đơn giản: Tôi chỉ sử dụng showDialog(int id) trên onCreate và sau đó tôi xoay thiết bị. Mã chỉ là (trường hợp kiểm tra) và điều đó đủ để gây ra sự cố. Đó là sự hiểu biết của tôi rằng phương pháp của showDialog sẽ chăm sóc cho rằng ... hộp thoại sẽ biến mất và sau đó onCreate sẽ được gọi sau này sau khi thay đổi và hiển thị hộp thoại một lần nữa, sạch sẽ. Nhưng không. Có gì sai với lý do này?

Tôi (nghĩ rằng tôi) hiểu the cause, nhưng tôi không biết cách giải quyết điều đó. Ngay cả các ứng dụng iosched có cùng một vấn đề với việc thực hiện của họ của cửa sổ EULA (thay đổi định hướng trên hộp thoại eula và bạn nhận được rò rỉ). Tôi đã đọc về việc loại bỏ các hộp thoại trên onPause, nhưng 1) Tôi có nguy cơ sa thải khi nó không được hiển thị đã có, và 2) theo dõi các hộp thoại có vẻ quá nhiều công việc. Phải có một cách tiếp cận mạnh mẽ hơn.

Vì vậy, ... mã sạch hơn cần thiết để xử lý điều đó là gì?

Cảm ơn bạn.


Log lỗi đầu ra:

01-30 00:27:18.615: E/WindowManager(20316): Activity com.test.PreSetupActivity has leaked window [email protected] that was originally added here 
01-30 00:27:18.615: E/WindowManager(20316): android.view.WindowLeaked: Activity com.test.PreSetupActivity has leaked window [email protected] that was originally added here 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.ViewRootImpl.<init>(ViewRootImpl.java:343) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:245) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:193) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:118) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.Window$LocalWindowManager.addView(Window.java:537) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.Dialog.show(Dialog.java:274) 
01-30 00:27:18.615: E/WindowManager(20316):  at com.test.PreSetupActivity.onCreate(PreSetupActivity.java:88) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.Activity.performCreate(Activity.java:4465) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3347) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.access$700(ActivityThread.java:122) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1150) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.os.Handler.dispatchMessage(Handler.java:99) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.os.Looper.loop(Looper.java:137) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.main(ActivityThread.java:4340) 
01-30 00:27:18.615: E/WindowManager(20316):  at java.lang.reflect.Method.invokeNative(Native Method) 
01-30 00:27:18.615: E/WindowManager(20316):  at java.lang.reflect.Method.invoke(Method.java:511) 
01-30 00:27:18.615: E/WindowManager(20316):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
01-30 00:27:18.615: E/WindowManager(20316):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
01-30 00:27:18.615: E/WindowManager(20316):  at dalvik.system.NativeStart.main(Native Method) 
+0

tôi thấy một số người đang theo dõi các cửa sổ, về cơ bản tạo ra chúng không có phương thức 'showDialog', và kiểm tra xem chúng có được hiển thị hay không (' isShowing() '), và sau đó loại bỏ tương ứng (tại onStop/onPause). Tuy nhiên, tôi tin rằng đó là một dự đoán an toàn để nói rằng cách tự động (showDialog) nên được sạch hơn và dễ dàng hơn, phải không? – davidcesarino

+0

bạn có thể đóng hộp thoại trong onPostexecute(), như dialog.dismiss(); – user3114805

+0

Thay vào đó, tôi sẽ sử dụng DialogFragment. Nó quản lý xoay tự động và do đó là thanh lịch hơn. – WindRider

Trả lời

13

Có một lớp bên trong có tác dụng như stateholder của bạn và có một trường boolean trong đó mà chỉ ra hay không thoại của bạn được hiển thị. Theo dõi này qua định hướng những thay đổi sử dụng onRetainNonConfigurationInstance và chỉ cần tái hiển thị hộp thoại trên onResume

Dưới đây là một số mã + pseudo-code:

public class ProfileActivity extends Activity { 
    private StateHolder mStateHolder; 
    private Dialog dialog; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Object retained = getLastNonConfigurationInstance(); 
    if (retained != null && retained instanceof StateHolder) { 
     mStateHolder = (StateHolder) retained; 
    } else { 
     mStateHolder = new StateHolder(); 
    } 
    } 

    @Override 
    public Object onRetainNonConfigurationInstance() { 
    return mStateHolder; 
    } 

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

    @Override 
    public void onResume() { 
    if(mStateHolder.mIsShowingDialog) { 
     dialog.show(); 
    } 
    } 

    private void showDialog() { 
    mStateHolder.mIsShowingDialog = true; 
    dialog.show(); 
    } 

    private static class StateHolder { 
    boolean mIsShowingDialog; 
    public StateHolder() {} 
    } 

} 
+0

Hmmm, thật không may là tôi thuyết phục bản thân rằng 'showDialog' chỉ là một PITA (xin lỗi). Tôi sẽ thử giải pháp này liên quan đến hộp thoại thủ công và sẽ báo cáo lại. Cảm ơn bạn! – davidcesarino

+1

Cảm ơn bạn một lần nữa. Tôi đang sử dụng khái niệm trên và nó hoạt động hoàn hảo! Tôi thậm chí còn liên tục nhấn Ctrl + F11 rất nhanh trong trình giả lập, thay đổi định hướng khoảng hai lần mỗi giây, nhiều lần ... một thứ mà người dùng trong một chiếc điện thoại bình thường sẽ không bao giờ làm. Và các dòng đăng nhập của tôi sạch sẽ như nó có thể. Cảm ơn bạn rất nhiều vì điều này khiến tôi mất khá nhiều thời gian hôm qua. – davidcesarino

+0

Câu trả lời hay, tôi đã sử dụng phương thức 'onPause()' – rahstame

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