本章主要介紹了如何使用 fragment 的 arguments 來(lái)傳遞信息
GitHub 地址:
完成第十章
1. 從 fragment 中啟動(dòng) activity
1.1 直接啟動(dòng)
從 fragment 中直接啟動(dòng) acitivity 的方法一般如下:
Intent intent = new Intent(getActivity(), TargetActivity.class);
startActivity(intent);
Fragment 中也帶有 startActivity()方法崭捍,其中 Intent 構(gòu)造方法需要的 Context 對(duì)象可以通過(guò) getActivity() 方法獲得拄衰。
1.2 附加 extra 信息
一般來(lái)說(shuō),為了保證類(lèi)之間的獨(dú)立,啟動(dòng)一個(gè) activity 的 intent 及其需要的參數(shù)應(yīng)該寫(xiě)在目標(biāo) activity 中缴淋,對(duì)于 fragment 同樣如此戚长。
對(duì)需要啟動(dòng)的目標(biāo) activity 可以如下:
//先定義一個(gè) key 以便識(shí)別
private static final String EXTRA_KEY = "com.kniost.appname.activity_name";
//然后定義一個(gè)獲取專(zhuān)用的 Intent 的靜態(tài)公有方法
public static Intent newIntent(Context context, Object data) {
Intent intent = new Intent(context, TargetActivity.class);
intent.putExtra(EXTRA_KEY, data);
return intent;
}
在需要的時(shí)候調(diào)用這個(gè)方法得到 Intent 并啟動(dòng)即可敦腔。
1.3 獲取 extra 信息
activity 可以通過(guò) getIntent().getExtra() 方法直接獲取信息缆八,然而真正需要信息的是 fragment。fragment 可不能用 intent 啟動(dòng)蛔琅。
在 fragment 中有兩種方法可以獲取信息:
- 一是從 activity 的 extra 中獲取信息胎许。這種方法比較簡(jiǎn)單,但是不推薦罗售,因?yàn)樗乒至?fragment 的封裝性辜窑,不利于解耦(在一個(gè)類(lèi)中用到另一個(gè)類(lèi)的變量),不便于復(fù)用寨躁。
Object data = (Object) getActivity().getIntent().getSerializable(EXTRA_KEY);
-
第二個(gè)就是比較好的做法穆碎,那就是將數(shù)據(jù)存放在 fragment 的 argument bundle 中,這樣無(wú)需托管的 activity 的 intent 內(nèi)指定 extra 的存在职恳,fragment 本身就能獲取自己所需的 extra 數(shù)據(jù)所禀。
和給一個(gè) activity 傳遞 extra 信息類(lèi)似,一般也會(huì)在目標(biāo)fragment 中添加一個(gè)公有的靜態(tài)方法 newInstance()放钦,參數(shù)則是需要的 extra 信息
```java
//首先也要定義一個(gè) key 用于獲取數(shù)據(jù)
private static final String ARG_EXTRA_KEY = "data_I_need";
……
public static TargetFragment newInstance(Object data) {
Bundle args = new Bundle();
args.putSerializable(ARG_EXTRA_KEY, data);
TargetFragment fragment = new TargetFragment();
fragment.setArguments(args);
return fragment;
}
```
這樣色徘,在托管的 activity 中新建 TargetFragment 類(lèi)的時(shí)候只要調(diào)用 TargetFragment.newInstance(Object data) 來(lái)獲取實(shí)例即可。
在 fragment 里獲取 argument 的方法比較簡(jiǎn)單操禀,直接調(diào)用 getArguments().getX() 方法即可褂策,其中 X 表示可以從 Bundle 中獲取的類(lèi)型,Serializable 是比較常用的傳遞復(fù)雜參數(shù)的方法。
2. 刷新顯示列表項(xiàng)
由于書(shū)上的例子中使用的是單例斤寂,也就是說(shuō)對(duì)于 Adapter 和 Fragment 來(lái)說(shuō)使用的數(shù)據(jù)都是指向同一地址的耿焊,只要在某處修改了,所有使用該數(shù)據(jù)的地方實(shí)際都改變了遍搞。這樣的話罗侯,修改數(shù)據(jù)之后只需要使用 RecyclerView.Adatper 的方法 notifyDataSetChanged() 即可刷新 RecyclerView 了。
3. 挑戰(zhàn)練習(xí):實(shí)現(xiàn)高效的 RecyclerView 刷新
使用 notifyItemChanged(int position) 方法可以高效地刷新單個(gè)被修改的 ViewHolder尾抑。
對(duì)于本書(shū)的這個(gè)問(wèn)題歇父,有特殊的做法。因?yàn)檫@個(gè) RecyclerView 和 fragment 是寫(xiě)在一個(gè)類(lèi)中的再愈,而且一次只會(huì)有一個(gè) ViewHolder 被改變,所以可以通過(guò)讀寫(xiě)同一個(gè)成員變量來(lái)判斷修改的 item 的位置护戳。
以下是具體解決方法:
//CrimeListFragment.java
private int positionClicked;
然后在 ViewHolder 的構(gòu)造函數(shù)建立 Listener 的時(shí)候用 getAdapterPosition() 方法記錄下被點(diǎn)擊的 ViewHolder 的位置
@Override
public void onClick(View view) {
Intent intent = CrimeActivity.newInent(getActivity(), mCrime.getId());
positionClicked = getAdapterPosition();
startActivity(intent);
}
最后在 updateUI() 函數(shù)中直接調(diào)用 mAdapter.notifyItemChanged(positionClicked);
if (mAdapter == null) {
mAdapter = new CrimeAdapter(crimes);
mCrimeRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.notifyItemChanged(positionClicked);
}
GitHub Page: kniost.github.io
簡(jiǎn)書(shū):http://www.reibang.com/u/723da691aa42