本博客代碼地址 : html
-- 單一 Fragment 示例 : https://github.com/han1202012/Octopus-Fragement.gitjava
-- 可複用的 Fragment 示例 : https://github.com/han1202012/Octopus-Fragement_TwoModel.gitandroid
Fragment 總結 git
1. Fragement 概述
Fragement 與 Activity 生命週期關係 : Fragement 嵌入到 Activity 組件中才可使用, 其生命週期與 Activity 生命週期相關.github
-- stop 與 destroy 狀態 : Activity 暫停 或者 銷燬的時候, 其內部嵌入的全部的 Fragement 也會執行 暫停 或者 銷燬 操做;app
-- 活動狀態 : 只有當 Activity 處於活動狀態的時候, 咱們才能操做 Fragement;ide
Fragement 特徵 : 模塊化
-- Fragement 與 Activity 交互 : Fragement 調用 getActivity() 獲取其 所嵌入的 Activity, Activity 獲取 FragementManager 的findFragementById() 或 findFragementByTag() 獲取 Fragement;函數
-- Activity 增刪 Fragement : Activity 調用 Fragement 的 add(), remove(), replace() 等方法 添加 刪除 替換 Fragement;oop
-- Fragement 與 Activity 對應關係 : 一個 Activity 中能夠嵌入多個 Fragement, 一個 Fragement 能夠嵌入多個 Activity;
-- 生命週期受 Activity 影響 : Fragement 的生命週期 受 Activity 生命週期控制;
Fragement 做用 : Fragement 是爲了 Android 中 平臺電腦 UI 設計, 開發者不用設計 很是負責的 界面, 只須要設計好模塊, 對UI 組件進行分組 和 模塊化的設計和開發, 簡化了 UI 組件;
Fragement 可複用性 : 同一個 app 應用, 能夠在不一樣的 Activity 中加載同一個 Fragement;
2. Fragement 類 和 方法介紹
(1) Fragement 相關類介紹
Fragement 子類 :
-- DialogFragement : 對話框界面的 Fragement, 顯示一個浮動的對話框, 這個對話框能夠方便的與 Activity 進行交互, Activity 能夠管理這個 Fragment;
-- ListFragement : 列表界面的 Fragement, 顯示一個條目列表, 該列表能夠設置一個適配器, 提供了許多管理 列表的函數;
-- PerformanceFragement : 選項設置界面的 Fragement, 該Fragment 建立 相似與 設置 應用程序時很管用;
-- WebViewFragement : WebView 界面的 Fragement;
(2) Fragement 生命週期相關方法介紹
onCreate() :
- onCreate(Bundle savedInstanceState)
-- 回調時機 : 在建立 Fragement 的時候回調;
-- 參數解析 : Bundle savedInstance, 用於保存 Fragment 參數, Fragement 也能夠 重寫 onSaveInstanceState(Bundle outState) 方法, 保存Fragement狀態;
-- 執行的動做 : 獲取 Frgement 顯示的內容, 以及啓動Fragment 傳入的參數, 調用 getArguments() 獲取鍵值對;
onCreateView() :
- onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
-- 回調時機 : Fragement 繪製界面組件 的時候回調, 該方法返回 View, 這個View就是 Fragement 自己;
-- 參數解析 : inflater 佈局加載器, 是上下文傳入, 不用本身建立; container 加載組件的父容器;
-- 執行的操做 : 使用 inflate 佈局加載器 加載佈局文件, 並未組件設置顯示的值;
onPause() :
-- 回調時機 : Fragement 暫停的時候, 即進入後臺的時候 回調;
3. Fragment 建立
Fragment 建立 :
-- 參數準備 : 建立一個 Bundle 對象, 並向其中設置參數 :
- Bundle bundle = new Bundle();
- bundle.putString("key", "value");
-- 建立 Fragment 對象 : 使用 new MyFragment() 建立對象, 並 調用 myFragment.setArguments(bundle) 方法傳入參數;
- MyFragment myFragment = new MyFragment();
- myFragment.setArguments(bundle);
Fragment嵌入Activity方式 : Fragment 添加到 Activity 中才能顯示, 如下是將 Fragment 嵌入 Activity 的方式;
-- 佈局文件嵌入 : 在佈局文件中 使用 <Fragment /> 元素, 經過定義 android:name = "com.example.MyFragment" 屬性指定 Fragment 類;
-- 代碼方式嵌入 : 調用 FragmentTransaction 對象的 add() 方法向 Activity 中添加 Fragment;
4. Fragment 與 Activity 通訊
Fragment 獲取 Activity : 調用 Fragment 對象的 getActivity()方法, 便可獲取 Fragment 嵌入的 Activity 對象;
Activity 獲取 Fragment :
-- Fragment 屬性 : 在佈局文件中, 能夠爲 <Fragment /> 元素指定 android:id 和 android:tag 屬性;
-- 獲取方法 : 調用 Activity 的 findFragmentById(int id) 或者 findFragmentByTag(String tag)方法;
Fragment 向 Activity 傳遞數據 : 將 Activity 看成接口子類對象, Fragment 中調用 Activity 中的接口方法;
-- Fragment 定義接口 : 在 Fragment 內部定義一個 Callback 接口;
-- Activity 實現該接口 : MyActivity extends Activity implement MyFragment.Callback;
-- Fragment 中獲取該接口對象 : 在Fragment 中定義一個 Callback 全局變量, 而後在 onAttach(Activity activity) 方法中, 將activity 強轉爲 Callback 對象;
-- 調用接口方法 : 上面獲取了 Callback 對象, 即Activity對象, 調用 Activity 中的 接口方法, 就能在 Fragment 中調用 Activity 對應的方法了;
Activity 向 Fragment 傳遞數據 :
-- 建立 Bundle 數據包 : 建立一個 Bundle 對象, 把要存放的鍵值對 放到這個對象中;
-- 設置 Bundle 對象給 Fragment : 調用 Fragment 對象的 setArguments(Bundle bundle) 方法, 將 Bundle 對象設置給 Fragment;
5. Fragment 事務管理
FragmentManager 功能 : FragmentManager 對象 能夠經過 activity.getFragmentManager()獲取;
-- 獲取指定 Fragment : 經過 findFragmentById() 或者 findFragmentByTag() 方法獲取指定 Fragment;
-- 彈出棧 : 經過調用 popBackStack(), 將 Fragment 從後臺的 棧 中彈出;
-- 監聽棧 : 經過調用 addOnBackStackChangeListener 註冊監聽器, 監聽 後臺棧變化;
FragmentTransaction 對象獲取途徑 :
-- 獲取 FragmentManager 對象 : 調用 Activity 的 getFragmentManager() 獲取 FragmentManager 對象;
-- 獲取 FragmentTansaction 對象 : 調用 FragmentManager 對象的 beginTransaction() 方法獲取 FragmentTransaction 對象;
FragmentTransaction(Fragment 事務)做用 : 對 Fragement 進行 增, 刪 , 改 操做須要 FragmentTransaction 對象進行操做, 開啓 這個事務, 獲取 事務對象, 而後執行對 Fragment 的操做, 最後提交事務;
-- 開啓事務 : 調用 Fragement 對象的 beginTransaction() 方法能夠獲取 FragementTransaction 對象;
-- 操做碎片 : FragmentTransaction 對象 中 包含了 add(), remove(), replace() 等方法;
-- 提交操做 : 當執行完 Fragement 的操做以後, 能夠調用 FragementTransaction 對象的 commit() 方法提交修改;
addToBackStack()方法做用 : 該方法是 FragementTransaction 的方法, 在提交事務前調用該方法, 能夠將 事務中執行的操做 添加到 back 棧中, 用戶按下 回退鍵, 修改過的 Fragement 會 回退到 事務執行以前的狀態;
6. Fragment 生命週期
(1) Fragment 狀態
活動狀態 : Fragment 處於前臺, 可見, 能夠獲取焦點;
暫停狀態 : Fragment 嵌入的Activity 也處於暫停狀態, 即 Fragment 處於後臺, 可見, 失去焦點;
中止狀態 : Fragement 嵌入的 Activity 處於中止狀態, 不可見, 失去焦點;
銷燬狀態 : Fragement 所在的 Activity 被銷燬, 執行了 onDestroy() 方法, 此時 Fragement 被徹底刪除;
(2) Fragement 生命週期相關方法

紅色方法 與 Activity 相對應, 藍色方法 是 自身對應的方法, 棕色方法 單獨對應;
onAttach() : 嵌入, Fragement 被嵌入到 Activity 時回調該方法, 只會調用一次;
onCreate() : 建立, Fragement 建立的時候回調該方法, 只會回調一次;
onCreateView() : 繪製, 在 Fragement 繪製的時候回調該方法, 該方法會返回 繪製的 View 組件;
onActivityCreated() : 界面建立, Fragement 所嵌入的 Activity 建立完成回調該方法;
onStart() : 啓動, Fragement 啓動時回調, 此時Fragement可見;
onResume() : 激活, Fragement 進入前臺, 可獲取焦點時激活;
onPause() : 暫停, Fragement 進入後臺, 不可獲取焦點時激活;
onStop() : 中止, Fragement 不可見時回調;
onDestroyView() : 銷燬組件, 銷燬 Fragement 繪製的 View 組件時回調;
onDestroy() : 銷燬, 銷燬 Fragement 回調;
onDetach() : 移除, Fragement 從 Activity 中移除的時候回調;
7. 代碼示例
(1) 需求分析
縱向手機屏幕 : 兩個界面, 每一個界面都有一個 Fragement, 一個Fragement顯示新聞列表, 一個Fragement 顯示新聞內容;
橫向手機屏幕 : 一個界面, 兩個Fragement, Fragement 顯示內容與上面相同;
(2) 新聞標題 Fragment
存放新聞標題的 Fragment : NewsTittleFragment.java
- package cn.org.octopus;
-
- import android.app.Activity;
- import android.app.ListFragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ArrayAdapter;
- import android.widget.ListAdapter;
- import android.widget.ListView;
-
- public class NewsTittleFragment extends ListFragment {
-
- private Callbacks activityCallback;
-
-
- public interface Callbacks{
- public void onNewsSelect(int id);
- }
-
-
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- System.out.println("onAttach");
-
- if ( ! ( activity instanceof Callbacks))
- System.out.println("Fragement in wrong Activity !");
-
-
- activityCallback = (Callbacks) activity;
- }
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- System.out.println("onCreate");
-
-
- ListAdapter adapter = new ArrayAdapter<News>(getActivity(), android.R.layout.simple_list_item_activated_1, android.R.id.text1, NewsContent.getInstance().news);
-
- setListAdapter(adapter);
- }
-
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- System.out.println("onCreateView");
- return super.onCreateView(inflater, container, savedInstanceState);
-
- }
-
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- System.out.println("onActivityCreated");
- }
-
-
- @Override
- public void onStart() {
- super.onStart();
- System.out.println("onStart");
- }
-
-
- @Override
- public void onResume() {
- super.onResume();
- System.out.println("onResume");
- }
-
-
- @Override
- public void onPause() {
- super.onPause();
- System.out.println("onPause");
- }
-
-
- @Override
- public void onStop() {
- super.onStop();
- System.out.println("onStop");
- }
-
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- System.out.println("onDestroyView");
- }
-
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- System.out.println("onDestroy");
- }
-
-
- @Override
- public void onDetach() {
- super.onDetach();
- System.out.println("onDetach");
- activityCallback = null;
- }
-
-
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- super.onListItemClick(l, v, position, id);
- activityCallback.onNewsSelect((int) id);
- }
-
-
- public void setChoiceMode(int choiceMode) {
- getListView().setChoiceMode(choiceMode);
- }
-
- }
(3) 新聞內容的 Fragment
存放新聞內容的 Fragment : NewsContentFragement.java;
- package cn.org.octopus;
-
- import android.app.Fragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.TextView;
-
- public class NewsContentFragement extends Fragment {
-
-
- public static final String TAG_NEWS_ID = "cn.org.octopus.news.tittle";
-
- private News news;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
-
- boolean isIllegal = getArguments().containsKey(TAG_NEWS_ID);
-
- if(isIllegal){
-
- int id = getArguments().getInt(TAG_NEWS_ID);
-
- news = NewsContent.getInstance().news_map.get(id);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
-
-
- View rootView = inflater.inflate(R.layout.fragment_news_content, container, false);
-
- TextView news_content_tittle = (TextView) rootView.findViewById(R.id.news_content_tittle);
-
- TextView news_content_content = (TextView) rootView.findViewById(R.id.news_content_content);
- if(null != news){
-
- news_content_tittle.setText(news.getTittle());
-
- news_content_content.setText(news.getContent());
- }
-
- return rootView;
- }
-
- }
(4) 新聞內容存儲相關代碼
新聞實體類 :
- package cn.org.octopus;
-
- public class News {
-
- private int id;
- private String tittle;
- private String content;
-
-
- public News(int id, String tittle, String content) {
- super();
- this.id = id;
- this.tittle = tittle;
- this.content = content;
- }
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getTittle() {
- return tittle;
- }
-
- public void setTittle(String tittle) {
- this.tittle = tittle;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
-
- @Override
- public String toString() {
- return tittle;
- }
-
- }
新聞數據 :
- package cn.org.octopus;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- public class NewsContent {
-
-
-
- private static NewsContent newsContent;
-
- public List<News> news;
- public Map<Integer, News> news_map;
-
- private NewsContent(){
- news = new ArrayList<News>();
- news_map = new HashMap<Integer, News>();
-
- News news1 = new News(0, "郭振璽斂財術", "7月30日,央視紀錄頻道CCTV-9總監劉文被帶走。據相關報道,劉文被帶走的緣由是 「發如今紀錄片對外採購上有財務問題」,另外,在一些高收視率的紀錄片創做上,「涉嫌與隱性的植入廣告有關的利益交換」。");
- News news2 = new News(1, "朝鮮新版5000朝元新鈔無金日成頭像", "韓國網刊《每日朝鮮》8月1日報道,已經開始流通的5000朝元新鈔並未印金日成肖像,意味金日成肖像已從朝鮮貨幣上暫時消失。 舊版朝鮮5000元紙幣上印有金日成頭像。");
- News news3 = new News(2, "美國醫生感染埃博拉", "菲律賓衛生部部長恩裏克·奧尼亞說,目前菲律賓尚無埃博拉疫情。衛生部已通報地方衛生部門,一旦發現返菲海外勞工出現感染埃博拉病毒早期症狀,當即對患者實行隔離治療。衛生部還要求近期即將從海外回國的勞工如出現發燒、頭痛、關節和肌肉疼痛、喉嚨痛等症狀,在回國前應得到所僱傭國家衛生部門的無感染證實,以免埃博拉病毒傳入菲律賓。");
-
- news.add(news1);
- news.add(news2);
- news.add(news3);
-
- news_map.put(news1.getId(), news1);
- news_map.put(news2.getId(), news2);
- news_map.put(news3.getId(), news3);
- }
-
-
- public static NewsContent getInstance() {
-
- if(newsContent != null)
- return newsContent;
- else
- return new NewsContent();
- }
-
- }
(5) 主界面 Actiity 代碼
主界面代碼 : MainActivity.java
- package cn.org.octopus;
-
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import cn.org.octopus.NewsTittleFragment.Callbacks;
-
- public class MainActivity extends Activity implements Callbacks {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
-
- setContentView(R.layout.activity_main);
- }
-
-
- @Override
- public void onNewsSelect(int id) {
-
- Bundle arguments = new Bundle();
-
- arguments.putInt(NewsContentFragement.TAG_NEWS_ID, id);
-
- NewsContentFragement fragement = new NewsContentFragement();
-
- fragement.setArguments(arguments);
-
- FragmentManager manager = getFragmentManager();
-
- FragmentTransaction transaction = manager.beginTransaction();
-
- transaction.replace(R.id.news_content, fragement);
-
- transaction.commit();
- }
-
- }
(6) AndroidManifest.xml 配置文件
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="cn.org.octopus"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="15"
- android:targetSdkVersion="19" />
-
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
-
- <!--
- 設置屏幕方向 android:screenOrientation :
- unspecified : 默認值, 系統自動斷定方向
- landscape : 橫屏顯示
- portrait : 豎屏顯示
- user : 用戶當前首選方向
- behind : 與 以前的 Activity 方向一致;
- sensor : 由物理傳感器決定
- nosenser : 忽略物理傳感器感應
- -->
-
- <activity
- android:name="cn.org.octopus.MainActivity"
- android:label="@string/app_name"
- android:screenOrientation="landscape">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
- </manifest>
(7) 執行結果
跟蹤的 Fragment 生命週期回調函數打印的結果 :
- I/System.out( 8604): onAttach
- I/System.out( 8604): onCreate
- I/System.out( 8604): onCreateView
- I/System.out( 8604): onActivityCreated
- I/System.out( 8604): onStart
- I/System.out( 8604): onResume
- I/System.out( 8604): onPause
- I/System.out( 8604): onStop
- I/System.out( 8604): onDestroyView
- I/System.out( 8604): onDestroy
- I/System.out( 8604): onDetach
界面執行結果 :

.
8. 出錯處理
(1) 引用 不用包中的 Fragment
引用 android.app.ListFragment, 不會出現錯誤, 而 引用 android.support.v4.app.ListFragment 類會出現以下錯誤;
錯誤 :
- 08-06 22:17:12.537: E/AndroidRuntime(3751): FATAL EXCEPTION: main
- 08-06 22:17:12.537: E/AndroidRuntime(3751): java.lang.RuntimeException: Unable to start activity ComponentInfo{cn.org.octopus/cn.org.octopus.MainActivity}: android.view.InflateException: Binary XML file line #11: Error inflating class fragment
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2255)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2309)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.ActivityThread.access$700(ActivityThread.java:157)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1289)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.os.Handler.dispatchMessage(Handler.java:99)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.os.Looper.loop(Looper.java:176)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.ActivityThread.main(ActivityThread.java:5319)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at java.lang.reflect.Method.invokeNative(Native Method)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at java.lang.reflect.Method.invoke(Method.java:511)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at dalvik.system.NativeStart.main(Native Method)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): Caused by: android.view.InflateException: Binary XML file line #11: Error inflating class fragment
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:710)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.view.LayoutInflater.rInflate(LayoutInflater.java:752)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.view.LayoutInflater.inflate(LayoutInflater.java:495)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:360)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.Activity.setContentView(Activity.java:1932)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at cn.org.octopus.MainActivity.onCreate(MainActivity.java:13)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.Activity.performCreate(Activity.java:5326)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1097)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2218)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): ... 11 more
- 08-06 22:17:12.537: E/AndroidRuntime(3751): Caused by: android.app.Fragment$InstantiationException: Trying to instantiate a class cn.org.octopus.NewsTittleFragment that is not a Fragment
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.Fragment.instantiate(Fragment.java:584)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.Fragment.instantiate(Fragment.java:560)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.app.Activity.onCreateView(Activity.java:4908)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:686)
- 08-06 22:17:12.537: E/AndroidRuntime(3751): ... 21 more
- 08-06 22:17:12.537: E/AndroidRuntime(3751): Caused by: java.lang.ClassCastException
- 08-06 22:17:12.537: E/AndroidRuntime(3751): ... 25 more
(2) ListView 適配器設置錯誤
ListView 適配器引用的 組件, 必須是已經加載過的, 經過 onCreate()中的 setContentView()方法加載, 或者經過 LayoutInflater 進行加載;
錯誤 :
- 08-06 22:39:22.139: W/dalvikvm(4413): threadid=1: thread exiting with uncaught exception (group=0x40dc0930)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): FATAL EXCEPTION: main
- 08-06 22:39:22.139: E/AndroidRuntime(4413): android.content.res.Resources$NotFoundException: Resource ID #0x7f080001 type #0x12 is not valid
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.content.res.Resources.loadXmlResourceParser(Resources.java:3033)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.content.res.Resources.getLayout(Resources.java:1722)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.LayoutInflater.inflate(LayoutInflater.java:395)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:371)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.ArrayAdapter.getView(ArrayAdapter.java:362)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.AbsListView.obtainView(AbsListView.java:2603)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.ListView.makeAndAddView(ListView.java:1840)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.ListView.fillDown(ListView.java:681)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.ListView.fillFromTop(ListView.java:742)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.ListView.layoutChildren(ListView.java:1661)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.AbsListView.onLayout(AbsListView.java:2426)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.View.layout(View.java:14905)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewGroup.layout(ViewGroup.java:4601)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.View.layout(View.java:14905)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewGroup.layout(ViewGroup.java:4601)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.View.layout(View.java:14905)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewGroup.layout(ViewGroup.java:4601)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1021)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.View.layout(View.java:14905)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewGroup.layout(ViewGroup.java:4601)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.View.layout(View.java:14905)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewGroup.layout(ViewGroup.java:4601)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1694)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1552)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.LinearLayout.onLayout(LinearLayout.java:1465)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.View.layout(View.java:14905)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewGroup.layout(ViewGroup.java:4601)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.View.layout(View.java:14905)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewGroup.layout(ViewGroup.java:4601)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2213)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2027)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1237)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5162)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.Choreographer.doCallbacks(Choreographer.java:591)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.Choreographer.doFrame(Choreographer.java:561)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.os.Handler.handleCallback(Handler.java:725)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.os.Handler.dispatchMessage(Handler.java:92)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.os.Looper.loop(Looper.java:176)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at android.app.ActivityThread.main(ActivityThread.java:5319)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at java.lang.reflect.Method.invokeNative(Native Method)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at java.lang.reflect.Method.invoke(Method.java:511)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
- 08-06 22:39:22.139: E/AndroidRuntime(4413): at dalvik.system.NativeStart.main(Native Method)
9. Fragement 複用問題
需求 : 在手機豎屏的時候, 新聞列表 和 新聞內容 在兩個 Activity 中, 橫屏的時候, 在一個 Activity 中;
(1) 根據不一樣的環境加載不一樣的佈局
定義實際引用的資源 : 在 Java 代碼中引用資源的時候, 會到 values 中查詢, 是否有定義資源文件, 若是有, 優先按照該定義加載指定資源文件;
-- 定義方式 : 下面的定義, 若是代碼中引用 R.layout.activity_main, 符合條件的話, 使用 R.layout.activity_main_land 佈局文件;
- <resources>
- <item type="layout" name="activity_main">@layout/activity_main_land</item>
- </resources>
-- 屬性說明 : type 資源的類型, name 資源名稱;
(2) 判斷加載的佈局文件
判斷的依據 : 根據 兩個佈局文件的差別, 任意查找一個組件, 或者定義一個 不佔位置的組件, 來進行斷定;
- isLand = findViewById(R.id.news_content) != null;
(3) MainActivity 代碼差別
- package cn.org.octopus;
-
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.content.Intent;
- import android.os.Bundle;
- import cn.org.octopus.NewsTittleFragment.Callbacks;
-
- public class MainActivity extends Activity implements Callbacks {
-
- private boolean isLand;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
-
- setContentView(R.layout.activity_main);
-
-
- isLand = findViewById(R.id.news_content) != null;
- }
-
-
- @Override
- public void onNewsSelect(int id) {
-
-
- if(isLand){
-
- Bundle arguments = new Bundle();
-
- arguments.putInt(NewsContentFragement.TAG_NEWS_ID, id);
-
- NewsContentFragement fragement = new NewsContentFragement();
-
- fragement.setArguments(arguments);
-
- FragmentManager manager = getFragmentManager();
-
- FragmentTransaction transaction = manager.beginTransaction();
-
- transaction.replace(R.id.news_content, fragement);
-
- transaction.commit();
- }else{
- System.out.println("isLand : " + isLand);
- Intent intent = new Intent(getApplicationContext(), NewsContentActivity.class);
-
- intent.putExtra(NewsContentFragement.TAG_NEWS_ID, id);
- startActivity(intent);
- }
-
- }
-
- }
(4) 新增了 NewsContentActivity
- package cn.org.octopus;
-
- import android.app.Activity;
- import android.os.Bundle;
-
- public class NewsContentActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.activity_news_content);
-
-
- NewsContentFragement fragement = new NewsContentFragement();
-
- Bundle bundle = new Bundle();
-
- int id = getIntent().getIntExtra(NewsContentFragement.TAG_NEWS_ID, 0);
- bundle.putInt(NewsContentFragement.TAG_NEWS_ID, id);
-
- fragement.setArguments(bundle);
-
- getFragmentManager().beginTransaction().add(R.id.news_content, fragement).commit();
- }
- }
(5) 新增 或 修改的佈局文件
activity_main.xml :
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context=".MainActivity" >
-
- <fragment
- android:id="@+id/tittle_fragment"
- android:name="cn.org.octopus.NewsTittleFragment"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="match_parent"/>
-
- </LinearLayout>
activity_main_land.xml :
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context=".MainActivity"
- android:orientation="horizontal"
- android:divider="?android:attr/dividerHorizontal"
- android:showDividers="middle">
-
- <!--
- 資源引用方式解析 :
- @+id : 定義一個 id 值, 用於識別組件
- @id : 引用 id 值表明的組件
- @anroid:type : 引用 Android 內部的資源, type 指的是 drawable string 等資源類型
- ?android:attr : 引用 Android 內部的樣式
-
- 分割線解析 :
- 分割線資源 : 在 android:divider 屬性中引入樣式, 這裏經過 ?android:attr 引入一個 android 的自定義樣式
- 分割線樣式 : android:showDivider 屬性中設置, none 不顯示分割線, beginning 在開始處顯示, end 在結尾顯示, middle 中間顯示
- -->
-
- <fragment
- android:id="@+id/tittle_fragment"
- android:name="cn.org.octopus.NewsTittleFragment"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="match_parent"/>
-
- <FrameLayout
- android:id="@+id/news_content"
- android:layout_width="0dp"
- android:layout_weight="3"
- android:layout_height="match_parent"/>
-
- </LinearLayout>
activity_news_content.xml :
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/news_content"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" />
(6) 執行效果
豎屏 :

橫屏 :

做者 : 韓曙亮
轉載請著名出處 : http://blog.csdn.net/shulianghan/article/details/38064191