实际项目中要一直用动态方法加载 fragment。
虽然动态加载方法要写的代码会多一点,但是一旦面临需求变更的时候,重构的难度要小不少。
如果使用静态加载方法,fragment 信息必须写入 layout 文件,在设计界面的时候必须知晓相应的 fragment 类 ———— 这样使得 MVC 结构中的 View 和 Controller 黏合得过于紧密,而且也显得似乎是由 View 在“控制” Controller。
静态加载的示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
| <LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:name="com.example.android.tempproject.MyFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
|
而且,这样就意味着实际开发时,必须先确定 Controller 的类型等信息,再对应设计界面;同时,即使只更换 fragment 类但不修改界面,也必须连带着修改 layout 文件。
尤其是当 activity 之间的界面相差很小时,动态加载的方法更加方便。
比如,想要将简单的文章显式界面换成 Viewpager 实现的可翻页模式。实际的文章界面可以一直不变,甚至新的 activity 的代码只是在获取 fragment 的方式上和原有的不同。
原来的 ArticleActivity 类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| public class ArticleActivity extends AppCompatActivity {
...
public ArticleFragment createFragment() {
... // 实际的获取 fragment 类代码
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_article);
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);
if (fragment == null) {
fragment = createFragment();
fragmentManager.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
}
...
}
|
新建的 ArticlePagerActivity 类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| public class ArticlePagerActivity extends AppCompatActivity {
...
private List<Article> articleList;
private void setArticleList() {
... // 获取文章列表的代码
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_article_pager);
mViewPager = (ViewPager) findViewById(R.id.activity_article_pager_view_pager);
setArticleList();
FragmentManager fragmentManager = getSupportFragmentManager();
mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
@Override
public Fragment getItem(int position) {
Article article = articleList.get(position);
return ArticleFragment.createArticleFragment(article.getID());
}
@Override
public int getCount() {
return articleList.size();
}
});
UUID articleId = (UUID) getIntent().getSerializableExtra(EXTRA_ARTICLE_ID);
for (int i = 0; i < mNewsList.size(); i++) {
if (articleList.get(i).getID().equals(articleId)) {
mViewPager.setCurrentItem(i);
break;
}
}
}
...
}
|
然后,只需要在对应 fragment 类中加入新的静态方法,以由文章 id 生成对应的 fragment:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| public class ArticleFragment extends Fragment {
...
private static final String ARG_NEWS_ID = "article_id";
private Article article;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID id = (UUID) getArguments().getSerializable(ARG_NEWS_ID);
article = ... // 由 id 获取 article
}
static ArticleFragment createArticleFragment(UUID articleId) {
Bundle args = new Bundle();
args.putSerializable(ARG_NEWS_ID, articleId);
ArticleFragment fragment = new ArticleFragment();
fragment.setArguments(args);
return fragment;
}
}
|
静态加载 fragment 之间通信要借助其托管的 activity 的 intent 实现:
- 使用
getActivity().getIntent()
- 使用 intent 的 get 方法,获取相应的 extra 信息
但是,这样 fragment 必须直到可以启动相应 activity 的 intent 的详细结构,就把 fragment 和 activity 绑死,破坏了对 activity 的封装,也无法灵活更换 activity。实际的代码中 activity 作为管理 fragment 的一方应该知晓 fragment 知识,而 fragment 则不应该直到管理它的 activity 的信息。
动态加载方法则可以使用 fragment arguments 实现信息传递,保护了 activity 的封装。实际的示例代码也在上一节中展示完毕。