今天主要學(xué)習(xí)下通過 arguments倔叼,實(shí)現(xiàn)activity 給fragment傳遞數(shù)據(jù)。
以下為目錄:
- 從 fragment 中啟動(dòng) activity
- argument 的優(yōu)點(diǎn)
- argument 的用法
從 fragment 中啟動(dòng) activity
從 fragment 中啟動(dòng) activity 苛骨,和從 activity 中啟動(dòng) activity 是一樣的鸽扁,如圖污呼。
需要注意的小點(diǎn)是避咆,newIntent 方法是寫在 CrimeActivity 中的舟肉。在CrimeFragment 中調(diào)用 getActivity().getIntent().getSerializableExtra(...) 得到值。
CrimeActivity.java
public static Intent newIntent(Context packageContext, UUID crimeId){
Intent intent = new Intent(packageContext,CrimeActivity.class);
intent.putExtra(EXTRA_CRIME_ID,crimeId);
return intent;
}
argument 的優(yōu)點(diǎn)
那么為什么又要用 argument 呢查库?因?yàn)檫@破環(huán)了 CrimeFragment 的封裝路媚,CrimeActivity 無法用于其他的 Activity 了。比較好的做法是把 crime ID 存放到 CrimeFragment 的某個(gè)地方樊销,而不是保存到 CrimeActivity 的私有空間中整慎。這樣就無需依賴 CrimeActivity 的私有空間了。這樣就不需要依賴 CrimeActivity 的 intent 內(nèi)的 extra围苫,CrimeFragment 就能獲取自己所需要的數(shù)據(jù)裤园。屬于fragment 的“某個(gè)地方”就是 argument bundle。
要附加 argument bundle 給 fragment够吩。需要調(diào)用 Fragment.setArguments(Bundle) 方法比然。而且必須在 fragment 創(chuàng)建后,添加給 activity 前呀伙。為了滿足以上的要求零抬,添加 newInstance() 方法隙弛,完成 fragment 實(shí)例和 Bundle 的創(chuàng)建满力。
argument 的用法
那么如何使用呢碳胳?我們從頭來講废境。
首先還是當(dāng)然還是需要啟動(dòng) CrimeActivity榛泛。在 CrimeListFragment 的 CrimeHolder 中啟動(dòng)嚎研。
CrimeListFragment.java
@Override
public void onClick(View view) {
Intent intent = CrimeActivity.newIntent(getActivity(),mCrime.getId());
startActivity(intent);
}
在 CrimeActivity 中得到 id 并傳給 CrimeFragment蓖墅。
CrimeActivity.java
@Override
protected Fragment createFragment() {
UUID crimeId = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID);
return CrimeFragment.newInstance(crimeId);
}
CrimeFragment 存放 id 到 argument并創(chuàng)建 fragment。
CrimeFragmen.java
private static final String ARG_CRIME_ID = "crime_id";
public static CrimeFragment newInstance (UUID crimeId){
Bundle args = new Bundle();
args.putSerializable(ARG_CRIME_ID,crimeId);
CrimeFragment fragment = new CrimeFragment();
fragment.setArguments(args);
return fragment;
}
在 onCreat(Bundle savedInstanceState) 中得到
CrimeFragment.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID crimeId = (UUID) getArguments().getSerializable(ARG_CRIME_ID);
mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);
}
現(xiàn)在數(shù)據(jù)可以正常顯示了临扮,那么我想點(diǎn)擊某個(gè)列表項(xiàng)论矾,然后修改它的值,返回列表項(xiàng)后杆勇,可以直接看到修改后的值贪壳,該怎么操作呢?
其實(shí)我們修改后蚜退,數(shù)據(jù)已經(jīng)保存到模型層了闰靴,我們只需要刷新 RecycleView 就可以了。調(diào)用 notifyDataSetChanged() 就行了钻注。這里需要注意的是蚂且,要在 onResume() 方法中寫。
CrimeListFragment.java
@Override
public void onResume() {
super.onResume();
updateUI();
}
private void updateUI() {
CrimeLab crimeLab = CrimeLab.get(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
if (mAdapter==null){
mAdapter = new CrimeAdapter(crimes);
mCrimeRecyclerView.setAdapter(mAdapter);
}else {
mAdapter.notifyDataSetChanged();
}
}
現(xiàn)在又有一個(gè)新的問題幅恋,notifyDataSetChanged() 是更新所有的列表項(xiàng)杏死,但是我們每次只修改一個(gè),怎么優(yōu)化這一步操作呢捆交?可以調(diào)用 RecycleView.Adapter 的 notifyItemChanged(int) 方法识埋。
增加一個(gè)變量:
CrimeListFragment.java
//保存位置變量
private int mPosition;
...
//得到位置
@Override
public void onClick(View view) {
Intent intent = CrimeActivity.newIntent(getActivity(),mCrime.getId());
mPosition = this.getAdapterPosition();
startActivity(intent);
}
...
//更新某個(gè)位置的數(shù)據(jù)
private void updateUI() {
CrimeLab crimeLab = CrimeLab.get(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
if (mAdapter==null){
mAdapter = new CrimeAdapter(crimes);
mCrimeRecyclerView.setAdapter(mAdapter);
}else {
// mAdapter.notifyDataSetChanged();
mAdapter.notifyItemChanged(mPosition);
}
}