四、fragment argument 和 页面数据更新
4.1 为什么要使用 fragment argument
当 fragment 和 activity 间的数据进行传递时,如果只是简单的使用 intent 的 extra 来进行传递信息,不仅破坏了 fragment 的封装,停驶也使得 fragment 变为不可复用的结构单元,而使用 fragment argument 的时候,数据信息保存在 fragment bundle 中,这样很好的进行数据的保存和传递,同时相比于使用 onSaveInstanceState 方法,这种方式更加的清晰直白,更容易进行后期的相关维护。
4.2 fragment argument 的使用方法
(1)要附加 argument bundle 给 fragment ,需要调用 Fragment.setArgument 方法,而且应当在 fragment 创建后、添加给 activity 之前完成。所以相对比较好的解决方法是:添加名为 newInstance() 的静态方法给 fragment 类。使用该方法,完成 fragment 实例化及 Bundle 对象的创建,然后将 argument 放入 bundle 中,最后再附加给 fragment。
public static ArticleFragment newInstance(UUID uuid) {
Bundle bundle = new Bundle();
bundle.putSerializable(EXTRA_ARTICLE_ID, uuid);
ArticleFragment fragment = new ArticleFragment();
fragment.setArguments(bundle);
return fragment;
}
(2)当在 fragment 中获取 argument 时,只需调用 Fragment.getArgument 方法,再调用 Bundle 限定类型的 get 方法即可。
UUID id = (UUID) getArguments().getSerializable(EXTRA_ARTICLE_ID);
4.3 使用 onResume 更新页面数据
当我们从列表页面进入到详情页面的时候,会遇到尽管我们已经在详情页修改了信息,但当我们退回列表页时才发现列表中的数据并未更新,那为什么会出现这样的现象呢。当我们进入详情页面时,详情页面被置于栈顶,而原来处于栈顶的列表页面被暂停并停止,当我们从详情页面回退到列表页面的时候,详情页面被销毁,列表页面这时才会被重启并恢复运行,因此它无法做到实时更新信息。
解决这个问题的方法就是在列表页面的 fragment 的 onResume 方法中重新调用更新数据的方法来刷新页面,也就是之前写到的 updateUI 方法,并且每次调用该方法时都判断一下是否已经创建了 Adapter 。
private void updateUI() {
ArticleLab articleLab = ArticleLab.get(getActivity());
List<Article> articles = articleLab.getmArticles();
if (mAdapter == null){
mAdapter = new ArticleAdapter(articles);
mRecyclerView.setAdapter(mAdapter);
}else {
mAdapter.notifyDataSetChanged();
}
}
4.4 notifyDataSetChanged() 和 notifyItemChanged(int)
这两种方法,第一个是通知 RecyclerView 刷新全部可见列表项,而第二种方法是只刷新特定的已改变数据的列表项,所以相比起来,第二种方法更加的高效,并且当页面具有较多的图片时,第一种方式还有可能带来闪图的问题。
但当使用第二种方式来刷新特定的列表项时,需要先定位到该项,我暂时想到的方法是在列表项的点击事件中使用 RecyclerView.getChildAdapterPositon 方法来获取该 ItemView 在Adapter 中的 position, 并使用变量来对其进行保存,然后当用户返回后在 updateUI 也就是 onResume 中进行刷新。
mClickedItem = mCrimeRecyclerView.getChildAdapterPosition(view);