本章要实现从fragment 中启动CrimeActivity
从 fragment 中启动 activity
类似于从 activity 中启动 activity。照着敲一遍代码,此小结无非就是启动下activity,在fragment中直接getActivity()得到activity,然后调用activity中的方法来拿到activity中的数据,但是这样做就破坏了fragment的封装,它不再是可复用的构建单元,于是就出现了下一小结的内容。
fragment argument
还是照着敲代码呗~ 关键代码(CrimeFragment .java):
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;
}
调用以上方法,这样子去在CrimeActivity中创建fragment实例,就传参了。activity和fragment不需要也无法同时相互保持独立,CrimeActivity必须了解CrimeFragment的内部细节,但fragment不一定需要知道其托管activity的细节问题。
刷新显示列表项
这里是利用fragment中的onResume()方法来进行刷新操作的,一旦重新打开了此页面,就刷新。
图解:
通过 fragment 获取返回结果
在fragment中,也有的startActivityForResult()方法,也可以利用此方法获取返回结果,覆盖Fragment.onActivityResult(...)方法,但是,fragment没有setResult()方法,因此,应该让托管的activity去处理返回结果值。
public class CrimeFragment extends Fragment {
...
public void returnResult() {
getActivity().setResult(Activity.RESULT_OK, null);
}
}
深入学习:为何要用 fragment argument
防止内存不够,操作系统强制杀掉应用,数据丢书的情况。
清楚直白方便。
挑战练习:实现高效的 RecyclerView 刷新
开始看到这个问题,想到一个方法,就是在CrimeListFragment中记录点击的crime,然后咋onResume()里面专门更新刚刚点击这一条数据,虽然心里不知道怎么的,总感觉不是太好,大概是因为,onResume()方法更新次数太多?哈哈哈~ 但是,这好像很简单就解决了这个问题。
public class CrimeListFragment extends Fragment{
...
private int currentPosition = -1;
...
private void updateUI() {
CrimeLab crimeLab = CrimeLab.get(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
if (mAdapter == null) {
mAdapter = new CrimeAdapter(crimes);
mCrimeRecyclerView.setAdapter(mAdapter);
} else {
if (currentPosition != -1) {
mAdapter.notifyItemChanged(currentPosition);
} else {
mAdapter.notifyDataSetChanged();
}
}
}
private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
...
@Override
public void onClick(View v) {
Intent intent = CrimeActivity.newIntent(getActivity(), mCrime.getId());
currentPosition = this.getAdapterPosition();
startActivity(intent);
}
}
当然还是方案就是借助上上小结的传递数据的方式来更新一条数据吧,同样是记录当前的更新位置,把position返回回来,在onActivityResult()中作更新,不在onResume()里面每次调用更新了。
挑战练习:优化 CrimeLab 的表现
这里可使用LinkedHashMap ,然后用UUID作为key来存储数据。
public class CrimeLab {
private static CrimeLab sCrimeLab;
private Map<UUID, Crime> mCrimes;
public static CrimeLab get(Context context) {
if (sCrimeLab == null) {
sCrimeLab = new CrimeLab(context);
}
return sCrimeLab;
}
private CrimeLab(Context context) {
mCrimes = new LinkedHashMap<>();
for (int i = 0; i < 100; i++) {
Crime crime = new Crime();
crime.setTitle("Crime #" + i);
crime.setSolved(i % 2 == 0);
mCrimes.put(crime.getId(), crime);
}
Crime crime = new Crime();
crime.setTitle("Crime # 101");
crime.setSolved(false);
crime.setRequiresPolice(true);
mCrimes.put(crime.getId(), crime);
}
public List<Crime> getCrimes() {
return new ArrayList<>(mCrimes.values());
}
public Crime getCrime(UUID id) {
return mCrimes.get(id);
}
}