Android 中 Fragment 的默认构造函数

shr*_*day 2 android android-fragments

我有一个片段类,如下所示:

public class MessageFragment extends Fragment {
    Context ctx;
    Button compose;

    public MessageFragment(Context ctx){
        this.ctx = ctx;
    }
...}
Run Code Online (Sandbox Code Playgroud)

构造函数给出了一个错误,指出

这个片段应该提供一个默认的构造函数

同时,我还有 4 个其他片段类,它们的格式与此完全相同,但它们不会给出此错误。我怎样才能解决这个问题?

kco*_*ock 5

当您Activity由于配置更改(例如方向更改)而重新创建时,系统将通过创建您的新实例Fragment,然后在 using 中传递参数来管理重新创建片段的状态setArguments(Bundle args)。它使用默认构造函数来重新创建片段,这就是需要它的原因。您永远不应该依赖片段的非默认构造函数中发生的逻辑,因为配置更改会立即中断。

另外,将 a 传递Context给您Fragment似乎会发生内存泄漏。可能不会,但这不是一个好的做法。等到Fragment生命周期事件之一(例如onCreate()或 )onAttach(),并将对的引用存储为getActivity()您的Context. 然后您可以在 中发布引用onDetach()

编辑:基本上,为了正常运行而需要传递的任何内容都Fragment应该存储在其参数中Bundle,或者保存在onSaveInstanceState(Bundle outState)事件中并在中恢复onCreate(Bundle state),否则您将在配置更改时丢失它。

这就是为什么有用于创建片段的静态工厂方法的通用模式。例如:

public static Fragment newInstance(String arg1, int arg2) {
    Fragment result = new MyFragment();
    Bundle args = new Bundle();
    args.putString("arg1_key", arg1);
    args.putInt("arg2_key", arg2);
    result.setArguments(args); 
    return result;
}
Run Code Online (Sandbox Code Playgroud)

然后使用它代替非默认构造函数。然后,您可以从您的内部Fragment检索数据:

Bundle args = getArguments();
String arg1 = args.getString("arg1_key");
int arg2 = args.getInt("arg2_key");
Run Code Online (Sandbox Code Playgroud)

  • 那么你将构造函数保持为公共还是私有?在 Java 中,您可以将其设置为私有,但在这种情况下,Android Lint 会抱怨“默认构造函数必须是公共的” (2认同)
  • 由于 Fragment 框架的实现,您必须将其公开。 (2认同)