未调用的DialogFragment的onCreate()回调(在哪里初始化视图?)

时间:2014-02-18 09:40:53

标签: android android-fragments android-dialogfragment

我想使用DialogFragment显示自定义对话框。但是,在我需要修改它们之前,我无法初始化布局视图。

这是我的DialogFragment课程。

public class RemoteProgressDialog extends DialogFragment {

private TextView lockProgress;
private TextView foldProgress;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Dialog_NoActionBar);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.remote_progress_dialog, null);
    lockProgress = (TextView) view.findViewById(R.id.lock_progress);
    return view;
}

public void lockFinished() {
    lockProgress.setCompoundDrawables(
                                    null,
                                    getResources().getDrawable(R.drawable.icn_mycar_sunroof_open),
                                    null, null);
    // TODO: remove
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    showLockProgress(false);
    dismissDialogIfNeeded();
}

public void showLockProgress(boolean show) {
    lockProgress.setVisibility(show ? View.VISIBLE : View.GONE);
}

private void dismissDialogIfNeeded() {
    if (lockProgress.getVisibility() == View.GONE) {
        // TODO: add conditions
        dismiss();
    }
}

我在Fragment中显示对话框,如下所示:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    progressDialog = new RemoteProgressDialog();
}

@Override
public boolean onLongClick(View v) {
    progressDialog.show(getFragmentManager(), REMOTE_PROGRESS_DIALOG);
    progressDialog.showLockProgress(true);
    return true;
}

起初我尝试使用AlertDialog.Builder构建对话框,但我得到NullPointerException,因为在onCreateDialog()之前未执行showLockProgress()方法,因此lockProgress为空。好吧,我还是不需要AlertDialog,所以我最终使用这种方法,希望它有助于解决问题。

不幸的是它没有帮助。调用方法lockProgress时,showLockProgress()仍为null。我在onCreate()的{​​{1}}和onCreateView()方法以及托管DialogFragment的{​​{1}}中设置了断点。 onAttach()中的那个会被触发,因此应创建Fragment的实例,但似乎不会调用onAttach()DialogFragment。当我长按按钮时,会调用onCreate(),但onCreateView()仍然为空。

为什么在创建对话框实例时或在我调用showLockProgress()方法后立即初始化我的视图?

2 个答案:

答案 0 :(得分:2)

所以我想问题是你的public方法在onCreate等之前调用,因为在show调用DialogFragment之后,初始化对话框需要时间,它是视图和所有变量。因此,在我看来,您可以采用正确的方式处理此方法,只需创建一个boolean变量,然后在显示DialogFragment之前设置该变量。像这样:

public class RemoteProgressDialog extends DialogFragment {

    private boolean mShowText = false; // default value

    private TextView lockProgress;

    public void setShowText(boolean showText){
        this.mShowText = showText;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.remote_progress_dialog, null);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState){
        // initialise your views here
        lockProgress = (TextView) view.findViewById(R.id.lock_progress);
        showLockProgress(mShowText);
    }

    public void showLockProgress(boolean show) {
        lockProgress.setVisibility(show ? View.VISIBLE : View.GONE);
    }

}

您可以在显示Dialog

之前执行此类操作
progressDialog.show(getFragmentManager(), REMOTE_PROGRESS_DIALOG);
progressDialog.setShowText(true);

因此,这样您就无法获得NullPointerException,并且您可以确定,根据您设置的boolean,您TextView中的RemoteProgressDialog将被隐藏或在初始化时可见。

希望这有帮助!

答案 1 :(得分:1)

<强>问题:

我认为问题在于,在创建并显示dialogFragment之前尝试showLockProgress,这会导致在分配之前尝试访问lockProgress

@Override
public boolean onLongClick(View v) {
    progressDialog.show(getFragmentManager(), REMOTE_PROGRESS_DIALOG);
    progressDialog.showLockProgress(true);
    return true;
}

执行该代码时会发生以下情况:

  • DialogFragment的show方法“是一种方便显式创建事务,使用给定标记向其添加片段并提交” - 它创建一个事务来添加一个事务片段并提交它。
  • 但是当主线程准备就绪时,FragmentTransaction的commit方法实际上会在将来的某个时间点调度事务的提交。
  • onLongClick方法在主线程上执行,因此事务的执行提交(以及片段创建)计划在此方法完成后的某个时刻发生。但在其中,您尝试访问stil-not-initialized成员lockProgress(在showLockProgress内)。

<强>解决方案:

使用Android-Developer的idea并实现一个布尔成员,可用于在创建视图后显示(或不显示)进度(例如,在onViewCreated中)。这样你只能从外面告诉DialogFragment它应该显示进度(或不显示进度),但让它在内部处理“when”和“how”。