Android程式設計權威指南 - 第10章 使用fragment argument
目標
本章的目標效果是,在列表中點選一項,彈出明細fragment介面。
此介面可以修改後,並儲存返回列表fragment介面。
類的呼叫關係如下:
啟動明細介面CrimeFragment
CrimeListFragment類中啟動呼叫
- 啟動是在點選列表的某一項之後,所以在onListItemClick函式中啟動
- 和Activity啟動另外一個Activity函式一樣,通過顯示的宣告一個Intent物件,物件指定了呼叫類和被呼叫類。需要說明的是,仍舊呼叫的是包含目標fragment的Activity,而不是直接呼叫fragment。
- 仍舊通過intent的putExtra來傳遞資訊。由於明細是要顯示對應的物件內容的,所以我們傳遞了具體的Crime物件給被呼叫者。並且設定了其對應的key為CrimeFragment.EXTRA_CRIME_ID常量。
- 通過startActivity()來啟動
具體程式碼如下
@Override
public void onListItemClick(ListView a, View v, int position, long id) {
Crime c = ((CrimeAdapter)getListAdapter()).getItem(position);
Log.d(TAG, c.getTitle() + " was clicked.");
// Start CrimeActivity
Intent i = new Intent(getActivity(), CrimeActivity.class);
i.putExtra(CrimeFragment.EXTRA_CRIME_ID, c.getId());
startActivity(i);
}
CrimeFragment類的設計
獲取Intent內容
和Activity一樣,通過activity的getSerializableExtra來獲得Intent傳遞的物件
UUID crimeId = (UUID)this.getIntent().getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
獲取Intent並處理的設計
在哪獲取Intent傳遞的訊息資訊?
我們可以直接在CrimeFragment類中使用上面的程式碼獲取Intent的內容,並生成具體的Crime物件,然後重新整理明細介面。
但是這樣做的問題在於,犧牲了CrimeFragment的封裝性,使得其無法再被其他的activity進行呼叫。
所以,我們應該在Activity就處理掉Intent資訊,並將獲取的資訊作為引數傳遞給Fragment。傳遞此引數的物件就是Bundle。
用於傳遞引數的Bundle物件
- 每一個Fragment都有一個對應的Bundle物件,我們可以將要使用的引數塞進Bundle物件中,需要的時候再取出來使用。
- Bundle的引數是key-value形式儲存的。
最終的設計
- CrimeFragment類中建立一個newInstance的靜態方法用於生成CrimeFragment例項。最重要的是,這個方法裡包含了Bundle物件的生成和引數的設定。
public static CrimeFragment newInstance(UUID crimeId) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_CRIME_ID, crimeId);
CrimeFragment fragment = new CrimeFragment();
fragment.setArguments(args);
return fragment;
}
- 這時,我們可以在包含fragment的CrimeActivity類中,獲取Intent中的引數。然後呼叫newInstance生成CrimeFragment例項,並且將Intent中的引數設定進Bundle中。
public class CrimeActivity extends SingleFragmentActivity {
@Override
protected Fragment createFragment() {
UUID crimeId = (UUID)this.getIntent().getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
return CrimeFragment.newInstance(crimeId);
}
}
- 我們再在CrimeFragment類的onCreate函式中,獲取Bundle中的引數,並生成重新整理介面需要的Crime物件。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID crimeId = (UUID)getArguments().getSerializable(EXTRA_CRIME_ID);
mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);
}
- 在CrimeFragment類的onCreateView函式中設定要顯示的介面
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_crime, parent, false);
mTitleField = (EditText)v.findViewById(R.id.crime_title);
mTitleField.setText(mCrime.getTitle());
..........................................................
mSolvedCheckBox = (CheckBox)v.findViewById(R.id.crime_solved);
mSolvedCheckBox.setChecked(mCrime.isSolved());
...........................................................
return v;
}
最終效果
選中列表的Cime 4點選,出現如下明細介面
列表介面顯示明細的修改
- 我們在明細介面可以修改Title這樣的引數,點選返回按鈕,預設是不會顯示修改資訊的。如果需要顯示,則需要做相關的處理。
- 我們只需要一行程式碼就可以實現這樣的功能了。
((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
這確實挺神奇的,畢竟在明細介面完全沒有配置相關程式碼,Adapter是需要好好研究的類。
-
實現功能語句放在哪?
當我們跳轉到CrimeFragment(CrimeActiviy)時,CrimeListActivity和CrimeListFragment是處於暫停的狀態。所以當返回時,系統會呼叫onResume來進行恢復。
也就是說實現顯示變化的語句應該放在CrimeListFragment類的onResume函式中。
@Override
public void onResume() {
super.onResume();
((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
}
通過fragment獲取返回結果
- 在CrimeListFragment類中,啟動時用的是Fragment的startActivityForResult方法,而不是Activity的此方法;獲取返回值並處理時,覆寫的是Fragment的onActivityResult方法,而不是Activity的此方法。
public class CrimeListFragment extends ListFragment {
private ArrayList<Crime> mCrimes;
private static final String TAG = "CrimeListFragment";
private static final int REQUEST_CRIME = 1;
@Override
public void onListItemClick(ListView a, View v, int position, long id) {
Crime c = ((CrimeAdapter)getListAdapter()).getItem(position);
Log.d(TAG, c.getTitle() + " was clicked.");
// Start CrimeActivity
Intent i = new Intent(getActivity(), CrimeActivity.class);
i.putExtra(CrimeFragment.EXTRA_CRIME_ID, c.getId());
startActivityForResult(i, REQUEST_CRIME);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CRIME) {
// Handle result
}
}
}
- Fragment可以獲取返回結果,但是不能產生返回結果。只能通知託管其的Activity來設定返回結果。
public class CrimeFragment extends Fragment {
public void returnResult() {
getActivity().setResult(Activity.RESULT_OK, null);
}
}
具體的應用在20章才會詳細介紹*
更新後的程式結構圖
相關文章
- Android程式設計權威指南(第2版)—第14章挑戰練習Android程式設計
- Android程式設計權威指南(第2版)—第15章挑戰練習Android程式設計
- Android程式設計權威指南(第2版)—第12章挑戰練習Android程式設計
- Android程式設計權威指南(第二版)— 第10章挑戰練習Android程式設計
- Android程式設計權威指南(第二版)— 第13章挑戰練習-13.6Android程式設計
- Android程式設計權威指南(第二版)— 第13章挑戰練習-13.8Android程式設計
- Android程式設計權威指南(第二版)學習筆記(十六)—— 第16章 使用 intent 拍照Android程式設計筆記Intent
- Android程式設計權威指南(第二版)學習筆記(十五)—— 第15章 隱式 IntentAndroid程式設計筆記Intent
- 《Android程式設計權威指南 第3版》PDF版電子書下載Android程式設計
- Swift程式設計權威指南第2版 讀後收穫Swift程式設計
- Hadoop權威指南 第4章 關於YARNHadoopYarn
- CUDA C 程式設計權威指南 學習筆記:第二章 CUDA程式設計模型程式設計筆記模型
- HTTP權威指南學習-第12章 基本認證機制HTTP
- HTML5權威指南讀書筆記25(完結)(第37章)--使用拖放HTML筆記
- 小記《SQL權威指南(第4版)》SQL
- Android程式設計基礎 • 【第1章 Android程式入門】Android程式設計
- 安卓權威指南第三版第16章拍照閃退問題安卓
- 《HTML5與CSS3權威指南(第3版·下冊)》——第19章選 擇 器HTMLCSSS3
- HTTP權威指南學習--第8章 整合點:閘道器、隧道及中繼HTTP中繼
- 《HTML5與CSS3權威指南(第3版·下冊)》——第18章CSS3概述HTMLCSSS3
- 高質量C++/C程式設計指南(第6章 函式設計) (轉)C++C程式程式設計函式
- 高質量C++/C程式設計指南(第11章 其它程式設計經驗) (轉)C++C程式程式設計
- Git權威指南Git
- HTTP權威指南HTTP
- 高質量C++/C程式設計指南(第5章 常量) (轉)C++C程式程式設計
- JavaScript物件程式設計-第3章JavaScript物件程式設計
- 第12章、網路程式設計程式設計
- 第1章 程式設計的方法程式設計
- 《HTML5與CSS3權威指南(第3版·上冊)》——第1章Web時代的變遷HTMLCSSS3Web
- 高質量C++/C程式設計指南(第2章 程式的版式) (轉)C++C程式程式設計
- 《HTML5與CSS3權威指南(第3版·上冊)》——第3章HTML5的結構HTMLCSSS3
- JavaScript 日期權威指南JavaScript
- Netty權威指南Netty
- 《ZeroC Ice權威指南》
- 讀《Cassandra權威指南》
- JAVA 程式設計思想 第13章 字串Java程式設計字串
- 高質量C++/C程式設計指南(第10章 類的繼承與組合) (轉)C++C程式程式設計繼承
- 《IDA Pro權威指南(第2版)》編輯手記