天天看點

Android中DialogFragment優于Dialog

首先DialogFragment是跟随Fragment一起被Google推出的,DialogFragment是基于Fragment的,生命周期和Fragment是一樣的。

在Android中,實作對話框的方式多種:

  1. Dialog/Alter
  2. DialogFragment
  3. Activity的Style設定成Dialog

通常,我們在開發中實作通過繼承Dialog來實作對話框的效果,但是,基于Dialog的對話框生命周期是不會随着Activity的,我們可以寫一段簡單的代碼來看看:

public class MyDialogActivity extends AppCompatActivity {
    private static final String TAG = "MyDialogActivity";
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG,"onCreate");
        setContentView(R.layout.activity_dialog);

        Button button = findViewById(R.id.button4);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyDialog myDialog = new MyDialog(MyDialogActivity.this);
                myDialog.show();

            }
        });
        //延時2秒主動關閉Activity
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                finish();
            }
        },2000);
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e(TAG,"onResume");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.e(TAG,"onStart");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.e(TAG,"onRestart");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG,"onPause");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e(TAG,"onDestroy");
    }
    @Override
    protected void onStop() {
        super.onStop();
        Log.e(TAG,"onStop");
    }

    static class MyDialog extends Dialog {
        private String TAG = "Dialog";
        public MyDialog(@NonNull Context context) {
            super(context);
            setContentView(R.layout.dialog_demo);
        }

        @Override
        protected void onStop() {
            super.onStop();
            Log.e(TAG,"onStop");
        }

        @Override
        protected void onStart() {
            super.onStart();
            Log.e(TAG,"onStart");
        }

        @Override
        public void cancel() {
            super.cancel();
            Log.e(TAG,"cancel");
        }

        @Override
        public void dismiss() {
            super.dismiss();
            Log.e(TAG,"dismiss");
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.e(TAG,"onCreate");
        }


    }

}           

運作起來後,打開一個Dialog,然後延時兩秒關閉Dialog,發現Log中竟然報錯了:

大緻的意思,Dialog沒被關閉,造成了記憶體洩漏

解決辦法也很簡單,在Activity中的onDestory方法中主動關閉:

@Override
    protected void onDestroy() {
        super.onDestroy();
        if (myDialog != null){
            myDialog.cancel();
        }
        Log.e(TAG,"onDestroy");
    }           

如果每次都要這樣做,感覺比較繁瑣,為什麼不能讓系統自己來回收呢?這裡就可以使用DialogFragment:

public class MyDialogFragment extends DialogFragment {
    private static final String TAG = "MyDialogFragment";

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG,"onCreate");
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d(TAG,"onCreateView");
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d(TAG,"onDetach");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"onDestroy");
    }
}           

從日志來看,當Activity生命周期發生變化的時候,DialogFragment的生命周期也在發生變化,這和Fragment是一樣的,是以可以保證當對話框的生命周期和Activity的生命周期保持一緻,避免記憶體洩漏

順便提一下,在通過點選彈出對話框的時候,不要直接new一個對話框,如果可以複用,就盡量複用,減少對象的建立

繼續閱讀