【问题标题】:Android DialogFragment onViewCreated not called未调用 Android DialogFragment onViewCreated
【发布时间】:2020-11-03 18:57:36
【问题描述】:

我正在使用 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
    }
}

onViewCreated 没有被记录。

【问题讨论】:

标签: android android-support-library android-dialogfragment


【解决方案1】:

好吧,onViewCreated 状态的文档“在 onCreateView(LayoutInflater, ViewGroup, Bundle) 返回后立即调用”。

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

【讨论】:

  • 我的问题是这样的 stackoverflow.com/questions/7692713/… 但解决方案不起作用
  • onCreateView 在构建 DialogFragment 时被触发,即使在使用 onCreateDialog 时也是如此。尽管如此,onViewCreated 在构建 DialogFragment 时不会被触发。奇怪的行为。
  • dialogfragment 在 super.onCreateDialog 返回时使用 onCreateView。
  • 我只是好奇为什么覆盖 DialogFragment 的 onViewCreated() 并抛出 RuntimeException 如此困难,因此开发人员知道此方法不是 Dialog 的一部分(扩展了 Fragment)...
  • onViewCreated() 在某些片段中被调用,而对于其他一些片段则不是。奇怪的行为。
【解决方案2】:

这是我确保在 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()
    }
}

【讨论】:

  • 谢谢!这可以完美运行,并且可以很容易地将流收集器添加到onViewCreated!我所做的小改动:由于我使用视图绑定,我不需要额外的 val,我可以在 onCreateView 中返回 binding.root
【解决方案3】:

根据我的测试,如果 onCreateView 返回 null(这是默认行为)则不会调用 onViewCreated,因此如果您不使用 onCreateView 而是在 onCreateDialog 中手动调用 setContentView,则可以手动调用 @987654324 @来自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;
}

在这种情况下,请确保my_dialog.xml 中的根元素具有android:id="@+id/dialog_content"

【讨论】:

  • 这种方法的唯一问题是如果你嵌入了DialogFragment;在这种情况下,onViewCreated 将被调用两次。
【解决方案4】:

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

首先,由于您没有覆盖onCreateView(),因此您的片段视图将为空。这点从source code of Fragment可以看出——默认返回null

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

其次,由于您的视图为空,FragmentManager 不会调用onViewCreated()。来自source code of 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;
}

【讨论】:

    【解决方案5】:

    根据文档 (Selecting Between Dialog or Embedding) 并由我自己测试,您可以覆盖 OnCreateView,使用您的自定义布局对其进行膨胀并返回它。 OnViewCreated 将启动

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
               View view = inflater.inflate(R.layout.custom_layout, null);
               //do whatever        
               return view; 
        }
    

    【讨论】:

      【解决方案6】:

      文档指出 onCreateDialog 将在 onCreateView(DialogFragment 文档)之前调用,onCreateView 将在 onActivityCreated(Fragment 文档)之前调用。 因此,这将是调用流程:

      onCreate
      onCreateDialog
      onCreateView
      onActivityCreated
      

      所以在 onActivityCreated 中做你会在 OnViewCreated 中做的事情,你应该被设置。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多