Android 中的片段与自定义视图
Fragment vs. Custom View in Android
Fragment 和Custom View 可以实现类似的功能,我知道fragment 比custom view 的复用性更好,还有其他benefits/enhancements 可以使用Fragment 吗?片段应该取代自定义视图,还是只是针对某些特定目的的增强?
例如下面的代码是fragment:
public class TestFragment extends Fragment {
private TextView tv_name;
private Button btn_play;
private Button btn_delete;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.testfragment, container, false);
}
@Override
public void onStart() {
super.onStart();
tv_name = (TextView)getView().findViewById(R.id.tv_name);
btn_play = (Button)getView().findViewById(R.id.btn_play);
btn_delete = (Button)getView().findViewById(R.id.btn_delete);
}
}
自定义视图的代码:
public class TestCustomView extends LinearLayout {
private TextView tv_name;
private Button btn_play;
private Button btn_delete;
public TestCustomView(Context context, AttributeSet attrs){
super(context, attrs);
setOrientation(LinearLayout.HORIZONTAL);
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
tv_name = new TextView(context);
addView(tv_name);
btn_play = new Button(context);
addView(btn_play);
btn_delete = new Button(context);
addView(btn_delete);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.testfragment, container, false);
}
}
TestFragment
和TestCustomView
都可以创建由TextView
和Buttons
组成的视图,并使用Framelayout/fragment
和com.packagename.TestCustomView
的标签在 activity 的 xml 布局文件中声明,但是使用 Fragment 有什么好处?
片段有自己的生命周期,这可能是障碍也可能是奖励,具体取决于您的需要。
片段获取生命周期方法,如 onResume 或 onSavedInstanceState,可以帮助您处理应用程序中的状态转换。如果您使用自定义视图,则需要自行处理此类事情。
有人反对使用片段,建议阅读https://developer.squareup.com/blog/advocating-against-android-fragments/
片段可以在不同的场景中使用,但最常用的是:
- 包装视图
- headless fragment - 即无视图 => 一般而言不是很有用,但可以使用
- 可保留片段 - 可以是以上任何一种。通过使用 Fragment.setRetainInstance(true) you can bypass Fragment.onDestroy(),即可以在配置更改时保留片段数据,但片段视图结构仍然是 destroyed/recreated
- 可以添加到 activity 返回堆栈,即轻松返回按钮以前的状态恢复
有些情况下颈部完全疼痛,然后有些情况可以更快地达到效果。
对于一些自定义和更灵活的情况,片段可能会变得混乱并且管理它们会很困难。因此,在某些情况下,直接处理视图可能非常方便并且更有帮助。不过一切以需求为准。
注意 View
也有自己的生命周期,可以store/recreate保存实例状态。多做一点工作,但它也有选择。
自定义视图的优点是简单,其主要目的是在屏幕上显示一段数据。他们必须依赖其他组件才能做更多事情。
将片段视为一个功能单元,一种使用一个或多个视图显示具有特定用途的 UI 的一部分的方法。片段连接到 Activity 生命周期,它们可以包含和控制加载器以用数据填充视图。它们还可以包括子片段。最后,它们也可以添加到合成后栈中。他们可以做很多事情,但学习起来有些复杂。
如您所见,Fragments 与 Activity 的共同点比它们与自定义视图的共同点多得多。
附带说明一下,片段也可以是无头的(没有 UI)。无头片段提供了一种封装非可视化功能的方法,它依赖于单独组件中的 Activity 生命周期。
使用 Fragments
而不是 Custom Views
最有用的功能是它们有自己的生命周期回调,即我们可以注册自己的 FragmentLifecycleCallbacks
来执行一些操作 before/after Fragment
creation/destruction.
我们可以创建自己的 FragmentLifecycleCallbacks
并将其注册到 Activity
以在 Fragment
到 Dagger
中注入依赖项。
在 Custom Views
中注入依赖项也有一些变通方法,但是通过 FragmentLifecycleCallbacks
注入依赖项更加简洁和容易。
Fragment 和Custom View 可以实现类似的功能,我知道fragment 比custom view 的复用性更好,还有其他benefits/enhancements 可以使用Fragment 吗?片段应该取代自定义视图,还是只是针对某些特定目的的增强?
例如下面的代码是fragment:
public class TestFragment extends Fragment {
private TextView tv_name;
private Button btn_play;
private Button btn_delete;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.testfragment, container, false);
}
@Override
public void onStart() {
super.onStart();
tv_name = (TextView)getView().findViewById(R.id.tv_name);
btn_play = (Button)getView().findViewById(R.id.btn_play);
btn_delete = (Button)getView().findViewById(R.id.btn_delete);
}
}
自定义视图的代码:
public class TestCustomView extends LinearLayout {
private TextView tv_name;
private Button btn_play;
private Button btn_delete;
public TestCustomView(Context context, AttributeSet attrs){
super(context, attrs);
setOrientation(LinearLayout.HORIZONTAL);
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
tv_name = new TextView(context);
addView(tv_name);
btn_play = new Button(context);
addView(btn_play);
btn_delete = new Button(context);
addView(btn_delete);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.testfragment, container, false);
}
}
TestFragment
和TestCustomView
都可以创建由TextView
和Buttons
组成的视图,并使用Framelayout/fragment
和com.packagename.TestCustomView
的标签在 activity 的 xml 布局文件中声明,但是使用 Fragment 有什么好处?
片段有自己的生命周期,这可能是障碍也可能是奖励,具体取决于您的需要。
片段获取生命周期方法,如 onResume 或 onSavedInstanceState,可以帮助您处理应用程序中的状态转换。如果您使用自定义视图,则需要自行处理此类事情。
有人反对使用片段,建议阅读https://developer.squareup.com/blog/advocating-against-android-fragments/
片段可以在不同的场景中使用,但最常用的是:
- 包装视图
- headless fragment - 即无视图 => 一般而言不是很有用,但可以使用
- 可保留片段 - 可以是以上任何一种。通过使用 Fragment.setRetainInstance(true) you can bypass Fragment.onDestroy(),即可以在配置更改时保留片段数据,但片段视图结构仍然是 destroyed/recreated
- 可以添加到 activity 返回堆栈,即轻松返回按钮以前的状态恢复
有些情况下颈部完全疼痛,然后有些情况可以更快地达到效果。
对于一些自定义和更灵活的情况,片段可能会变得混乱并且管理它们会很困难。因此,在某些情况下,直接处理视图可能非常方便并且更有帮助。不过一切以需求为准。
注意 View
也有自己的生命周期,可以store/recreate保存实例状态。多做一点工作,但它也有选择。
自定义视图的优点是简单,其主要目的是在屏幕上显示一段数据。他们必须依赖其他组件才能做更多事情。
将片段视为一个功能单元,一种使用一个或多个视图显示具有特定用途的 UI 的一部分的方法。片段连接到 Activity 生命周期,它们可以包含和控制加载器以用数据填充视图。它们还可以包括子片段。最后,它们也可以添加到合成后栈中。他们可以做很多事情,但学习起来有些复杂。
如您所见,Fragments 与 Activity 的共同点比它们与自定义视图的共同点多得多。
附带说明一下,片段也可以是无头的(没有 UI)。无头片段提供了一种封装非可视化功能的方法,它依赖于单独组件中的 Activity 生命周期。
使用 Fragments
而不是 Custom Views
最有用的功能是它们有自己的生命周期回调,即我们可以注册自己的 FragmentLifecycleCallbacks
来执行一些操作 before/after Fragment
creation/destruction.
我们可以创建自己的 FragmentLifecycleCallbacks
并将其注册到 Activity
以在 Fragment
到 Dagger
中注入依赖项。
在 Custom Views
中注入依赖项也有一些变通方法,但是通过 FragmentLifecycleCallbacks
注入依赖项更加简洁和容易。