我想保持我的应用程序很薄。
问题:我想重用我的Fragment
类代码,在ViewPager
中创建3个不同的实例,这些实例将有3个页面。每个Fragment
都有不同的ImageView
或背景Drawable
。关于此的最佳做法是什么?我注意到使用像here这样的工厂方法似乎很好,还有其他选择吗?
我有一个Fragment
,其中包含以下方法:
Fragment.java
public static Fragment newInstance(Context context) {
FragmentTutorial f = new FragmentTutorial();
Bundle args = new Bundle();
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment, null);
return root;
}
我有一个ViewPagerAdapter类,它有以下几种方法:
ViewPagerAdapter.java
public ViewPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
@Override
public Fragment getItem(int position) {
return new FragmentTutorial().newInstance(mContext);
}
@Override
public int getCount() {
return totalPage;
}
答案 0 :(得分:7)
我发现“最好”的方式(我认为当然)是做以下事情:
onCreateView()
甚至运行之前设置数据,或者在其他时候可以在onCreateView()之后运行。我个人使用布尔值来检查数据是否已设置。在onCreateView()
[或onActivityCreated()
]内,我检查数据是否已经设置。如果有,则加载数据。或者,在设置数据时,我会检查是否已经创建/缓存了视图。这是通过简单地使用变量来缓存数据来完成的,比如private ImageView mBackgroundView
。如果视图不为null,那么我可以安全地在视图上设置数据。getCount()
只使用列表的大小getItem()
只获取该位置列表中的项目
基本上,片段就像一个简单的仆人 - 它只是最不必要的工作。如果它不必处理选择数据,那就更好了。因此它会更加灵活。只需给出在片段上适当设置数据/视图的方法。现在,ArrayAdapter可以完成所有肮脏的工作,管理数据并将其提供给适当的片段。利用这一点。
现在,请注意,这假设您要使用单个布局,但希望更改该布局的不同方面(文本,背景等)。如果你想制作一个可以使用任何类型的定义布局的主片段类,你可以注意到它会降低运行时灵活性(你如何将文本或背景更改为你从互联网上获得的东西?你根本不能如果你只能定义并从预先设定的布局中选择。)
无论哪种方式,ArrayAdapter都应该处理所有不同的数据,而片段只是按照设计的方式进行,最好是以更灵活的方式。
修改强> 这是我最近实现这种模式的项目。请注意,它有更多,所以我会在早上/下午用一些不那么伪的伪代码替换它。
<强> EDIT2:强> 这是上述模式的更多(如果过度)简化示例。
免责声明:以下代码绝对没有生命周期管理实施,并且是自14年8月左右以来未被触及的旧代码
现在,以下是代码的确切相关部分:
// Note: Found out later can extend normal Fragments but must use v13 adapter
public class BaseFragment extends android.support.v4.app.Fragment {
FrameLayout mMainLayout; // The parent layout
int mNewColor = 0; // The new bg color, set from activity
String mNewText = ""; // The new text, set from activity
TextView mMainText; // The only textview in this fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the fragment's layout
View view = inflater.inflate(R.layout.fragment_base,container,false);
// Save the textview for further editing
mMainText = (TextView) view.findViewById(R.id.textView);
// Save the framelayout to change background color later
mMainLayout = (FrameLayout) view.findViewById(R.id.mainLayout);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// If there is new text or color assigned, set em
if(mNewText != ""){
mMainText.setText(mNewText);
}
if(mNewColor != 0){
mMainLayout.setBackgroundColor(mNewColor);
}
}
@Override
public void onStart(){
super.onStart();
}
// Simply indicate to change the text of the fragment
public void changeText(String newText){
mNewText=newText;
}
// Simply indicate to change the background color of the fragment
public void changeBG(int color) {
// If no color was passed, then set background to white
if(color == 0)
{
mNewColor=getResources().getColor(R.color.white);
}
// else set the color to what was passed in
else{
mNewColor=color;
}
}
}
class MyAdapter extends FragmentPagerAdapter{
// Three simple fragments
BaseFragment fragA;
BaseFragment fragB;
BaseFragment fragC;
public MyAdapter(FragmentManager fm) {
super(fm);
}
public void setFragments(Context c){
// Set up the simple base fragments
fragA = new BaseFragment();
fragB = new BaseFragment();
fragC = new BaseFragment();
Resources res = c.getResources();
fragA.changeText("This is Fragment A!");
fragB.changeText("This is Fragment B!");
fragC.changeText("This is Fragment C!");
fragA.changeBG(res.getColor(R.color.dev_blue));
fragB.changeBG(res.getColor(R.color.dev_green));
fragC.changeBG(res.getColor(R.color.dev_orange));
}
@Override
public Fragment getItem(int position) {
// TODO: Make this more efficient, use a list or such, also comment more
Fragment frag = null;
if(position == 0){
frag = fragA;
}
else if(position == 1){
frag = fragB;
}
else if(position == 2){
frag = fragC;
}
return frag;
}
@Override
public int getCount() {
return 3;
}
}
答案 1 :(得分:3)
创建实例时,您需要传递某种id和newInstance()
。根据该ID,您可以使用if..else
来选择布局文件。
请参阅下面的参考码:
int id;
public static Fragment newInstance(Context context, int id) {
FragmentTutorial f = new FragmentTutorial();
Bundle args = new Bundle();
this.id = id;
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(id == 1)
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment1, null);
else
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment2, null);
return root;
}
答案 2 :(得分:0)
您是否只是将字段引入Fragment类以解释背景中的差异等,并将它们添加到其构造函数中?然后在getItem
中根据position
的值实例化具有不同值的Fragment类。