未调用Android DialogFragment onViewCreated

Gau*_*sth 29 android android-dialogfragment android-support-library

我正在使用android兼容库(v4修订版8).在自定义DialogFragment中,没有调用onViewCreated的覆盖方法.例如.

public class MyDialogFragment extends DialogFragment{
    private String mMessage;
    public MyDialogFragment(String message) {
        mMessage = message;
    }

    @Override
    public Dialog onCreateDialog( Bundle savedInstanceState){
        super.onCreateDialog(savedInstanceState);
        Log.d("TAG", "onCreateDialog");
        setRetainInstance(true); 
        //....do something
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        Log.d("TAG", "onViewCreated");
        //...do something
    }
}
Run Code Online (Sandbox Code Playgroud)

onViewCreated未被记录.

Bar*_*rak 17

好吧,onViewCreated状态的文档"在onCreateView(LayoutInflater,ViewGroup,Bundle)之后立即调用"已经返回".

DialogFragment使用onCreateDialog而不是onCreateView,因此不会触发onViewCreated.(将是我的工作理论,我没有潜入android源来确认).

  • 构建DialogFragment时会触发`onCreateView`,即使也使用`onCreateDialog`.仍然,构建DialogFragment时不会触发`onViewCreated`.奇怪的行为. (7认同)
  • 我只是好奇为什么很难为DialogFragment覆盖onViewCreated()并抛出RuntimeException,因此开发人员知道这个方法不是Dialog的一部分(谁扩展了Fragment)...... (4认同)

Car*_*mer 12

这就是我确保在 kotlin 中调用 onViewCreated 的方式:

class MyDialog: DialogFragment() {

    private lateinit var dialogView: View

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        dialogView = LayoutInflater.from(context).inflate(R.layout.dialog, null)
        val dialog = MaterialAlertDialogBuilder(context!!)
                .setView(dialogView)
                .create()

        return dialog
    }

    // Need to return the view here or onViewCreated won't be called by DialogFragment, sigh
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return dialogView
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // Yay it's now called!
    }

    override fun onDestroyView() {
        dialogView = null
        super.onDestroyView()
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你!这可以完美地工作,并且可以非常轻松地将流收集器添加到“onViewCreated”!我做了一个小改动:因为我使用视图绑定,所以不需要额外的 val,我可以在 `onCreateView` 中返回 `binding.root` (2认同)

vin*_*3m1 8

从我的测试,onViewCreated不叫,如果onCreateView返回null,这是默认行为,所以如果你不使用onCreateView但手动调用setContentViewonCreateDialog,你可以手动调用onViewCreated来自onCreateDialog:

@Override public Dialog onCreateDialog(Bundle savedInstanceState) {
    final Dialog d = super.onCreateDialog(savedInstanceState);
    d.setContentView(R.layout.my_dialog);
    // ... do stuff....
    onViewCreated(d.findViewById(R.id.dialog_content), savedInstanceState);
    return d;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,请确保in元素中my_dialog.xmlandroid:id="@+id/dialog_content"

  • 这种方法的唯一问题是您是否嵌入了“DialogFragment”;在这种情况下,`onViewCreated` 将被调用两次。 (2认同)

bco*_*rso 6

您可以从源代码中看到发生了什么:

首先,由于您不覆盖onCreateView()您的片段,因此视图将为null.这可以从源代码中Fragment看出- 默认返回null:

// android.support.v4.app.Fragment.java
@Nullable
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
        @Nullable Bundle savedInstanceState) {
    return null;
}
Run Code Online (Sandbox Code Playgroud)

其次,因为你的视图是null,所以FragmentManager不会调用onViewCreated().从源代码FragmentManager:

// android.support.v4.app.FragmentManager.java
if (f.mView != null) {
    f.mInnerView = f.mView;
    // ... 

    // only called if the fragments view is not null!
    f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
    f.mInnerView = null;
}
Run Code Online (Sandbox Code Playgroud)