1. 程式人生 > >第二行程式碼學習筆記——第四章:手機平板要相容——探究碎片

第二行程式碼學習筆記——第四章:手機平板要相容——探究碎片

本章要點

作為一名專業的Android開發人員,能夠同時相容手機和平板的開發時我們必須要做到的事情。

4.1 碎片是什麼

碎片(Fragment)是一種可以巢狀在活動當中的UI片段,它能讓程式更加合理和充分的利用大螢幕的控制元件。

4.2 碎片的使用方式

開始我們的碎片之旅,建立FragmentTest專案。

4.2.1 碎片的簡易用法

最簡單碎片,在一個活動中新增兩個碎片,並讓這兩個碎片平分活動控制元件。

新建左碎片佈局left_fragment.xml,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn" android:text="Button" android:layout_gravity="center_horizontal"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
</LinearLayout>

新建右側碎片,right_fragment.xml,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
android:background="#00ff00" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="20sp" android:text="This is right fragment"/> </LinearLayout>

新建LeftFragment類和RrightFragment類,並讓它們繼承自support-v4包下的Fragment,重寫onCreateView()來載入佈局。
LeftFragment,程式碼如下:

public class LeftFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.left_fragment, container, false);
        return view;
    }
}

RightFragment,程式碼如下:

public class RightFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.right_fragment, container, false);
        return view;
    }
}

修改activity_main.xml中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.hjw.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"/>

    <fragment
        android:id="@+id/right_fragment"
        android:name="com.example.hjw.fragmenttest.RightFragment"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"/>


</LinearLayout>

屬性:
android:name 指明新增碎片的類名(包名+類名)。

執行效果:
tablet1

4.2.2 動態新增碎片

新建another_right_fragment.xml,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#ffff00"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:textSize="20sp"
        android:text="This is another right fragment"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

建立AnotherRightFragment類,程式碼如下:

public class AnotherRightFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.another_right_fragment, container, false);
        return view;
    }
}

修改activity_main.xml中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.hjw.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"/>

    <FrameLayout
        android:id="@+id/right_layout"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="match_parent"></FrameLayout>

</LinearLayout>

實現動態新增Fragment,修改MainActivity中的程式碼如下所示:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn= (Button) findViewById(R.id.btn);
        btn.setOnClickListener(this);
        replaceFragmetn(new RightFragment());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                replaceFragmetn(new AnotherRightFragment());
                break;
            default:
                break;z
        }
    }

    public void replaceFragmetn(Fragment fragment){
        FragmentManager fragmentManager=getSupportFragmentManager();
        FragmentTransaction transaction=fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout,fragment);
        transaction.commit();
    }
}

動態添加布局5步驟:

  1. 建立待新增碎片的例項。
  2. 獲取FragmentManager,在活動中直接通過呼叫getSupportFragmentManager()得到。
  3. 開啟一個事務,通過beginTransaction()開啟。
  4. 向容器新增或替換佈局,一般使用replace()實現,需要傳入容器的id和待添加布局的例項。
  5. 提交事務,commit()。

重啟,點選一下按鈕,效果圖:
df

4.2.3 在碎片中模擬返回棧

模仿類似於返回棧的效果好,Back返回上一個碎片。
FragmentTransaction提供了addToBackStack()方法,一般傳入null。修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    ......
    public void replaceFragmetn(Fragment fragment){
        FragmentManager fragmentManager=getSupportFragmentManager();
        FragmentTransaction transaction=fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout,fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }
}

重新執行程式,點選按鈕將AnotherRightFragment新增到活動中,按下Back鍵,會RightFragment,再按下Back鍵,RightFragment也會消失,再按下Back鍵,程式才會退出。

4.2.4 碎片與活動之間進行通訊

活動中呼叫碎片的方法,FragmentManager提供了一個類似於findFragmentById()的方法,從佈局中獲取碎片的例項,程式碼如下:

RightFragment rightFragment = (RightFragment) getSupportFragmentManager().findFragmentById(R.id.right_fragment);

碎片中呼叫活動的方法,呼叫getActivity()方法來得到和當前碎片相關聯的活動,程式碼如下:

MainActivity activity = (MainActivity) getActivity();

這樣,碎片就可以呼叫活動中的方法了,當碎片需要使用Context物件時,也可以使用getActivity()方法,因為獲取到的活動本身就是一個Context物件。

4.3 碎片的生命週期

碎片自己的生命週期。

4.3.1 碎片的狀態和回撥

碎片和活動一樣,生命週期會有4中狀態:

  1. 執行狀態
    當一個碎片時可見的,並且它關聯的活動正處於執行狀態時,該對片也處於執行狀態。
  2. 暫停狀態
    當一個活動進入暫停狀態時,與它相關聯的可見碎片就會進入到暫停狀態。
  3. 停止狀態
    當一個活動進入停止狀態時,與它相關聯的碎片就會進入停止狀態,或呼叫FragmentTransaction的revome(),replace()將碎片從活動中移除, 如果在提交事務之前呼叫addToBackStack()方法,碎片也會進入停止狀態。
  4. 銷燬狀態
    碎片總是依附於活動而存在的,當活動銷燬時,與它關聯的碎片也會銷燬狀態。或呼叫FragmentTransaction的revome(),replace()將碎片從活動中移除, 如果在提交事務之前並沒有呼叫addToBackStack()方法,這時的碎片就會進入銷燬狀態。

活動中的回撥方法,碎片幾乎都有,碎片還提供了一些附加的回撥方法:

  • onAttach()。 碎片和活動建立關聯的時候呼叫。
  • onCreateView()。 碎片建立檢視(載入佈局)時呼叫。
  • onActivityCreated()。 確保與碎片相關聯的活動一定已經建立完畢呼叫。
  • onDestroyView()。 當與碎片相關聯的檢視被移除的時候呼叫。
  • onDetach()。 當碎片與活動解除關聯的時候呼叫。

碎片完整的生命週期圖:
fsmzq

4.3.2 體驗碎片的生命週期

修改RightFragment中的程式碼,如下:

public class RightFragment extends Fragment {

    private static final String TAG = "RightFragment";

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d(TAG, "onAttach: ");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate: ");
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView: ");
        View view = LayoutInflater.from(getContext()).inflate(R.layout.right_fragment, container, false);
        MainActivity activity = (MainActivity) getActivity();
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, "onActivityCreated: ");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: ");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: ");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: ");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: ");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d(TAG, "onDestroyView: ");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d(TAG, "onDetach: ");
    }
}

執行程式,觀察logcat列印資訊:

ycsmzq

點選LeftFragment中的按鈕,觀察logcat列印資訊:
lb

按下Back鍵,RightFragment重新回到執行狀態,觀察logcat列印資訊:
b1f

再次按下Back鍵,觀察logcat列印資訊:
b2

4.4 動態載入佈局的技巧

Android中動態載入佈局的計技巧。

4.4.1 使用限定符

判斷程式應該是單頁還是雙頁模式:限定符(Qualifiers)。
修改FragmentTest專案中的activity.main.xml檔案,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.hjw.fragmenttest.LeftFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

在res目錄下layout_large資料夾,新建activity.main.xml,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.hjw.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"/>

    <fragment
        android:id="@+id/right_fragment"
        android:name="com.example.hjw.fragmenttest.RightFragment"
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="match_parent"/>

</LinearLayout>

large是一個限定符,修改Macitivty中的程式碼:replaceFragment()程式碼注掉。執行平板效果如下:
xgt

在啟動一個手機模擬器,執行效果如下:
sjxgt

限定符的引數:
這裡寫圖片描述
a

4.4.2 使用最小寬度限定符

最小限定符(Smallest-width-Qualifier)

在res目錄新建layout-sw600dp資料夾,新建activity_main.xml中的檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment
    android:id="@+id/left_fragment"
    android:name="com.example.hjw.fragmenttest.LeftFragment"
    android:layout_width="0dp"
    android:layout_weight="1"
    android:layout_height="match_parent"/>

<fragment
    android:id="@+id/right_fragment"
    android:name="com.example.hjw.fragmenttest.RightFragment"
    android:layout_width="0dp"
    android:layout_weight="3"
    android:layout_height="match_parent"/>

</LinearLayout>

螢幕寬度大於600dp,會載入layout-600dp中的佈局,小於600載入預設佈局。

4.5 碎片的最佳實踐——一個簡易版的新聞應用

新聞應用

新建FragmentBestPractice專案。
新增依賴:

compile 'com.android.support:recyclerview-v7:24.2.1'

新建News實體類:

public class News {

    private String title;
    private String content;


    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }
}

新建佈局檔案news_content_frag.xml,作為新聞內容的佈局,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/visibility_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_news_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="10dp"
            android:textSize="20sp" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#000" />

        <TextView
            android:id="@+id/tv_news_content"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    </LinearLayout>

    <View
        android:layout_width="1dp"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:background="#000" />

</RelativeLayout>

新建NewsContentFragment類載入news_content_frag佈局,繼承自Fragment,程式碼如下:

public class NewsContentFragment extends Fragment {


    private View view;
    private TextView tv_news_title,tv_news_content;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = LayoutInflater.from(getContext()).inflate(R.layout.news_content_frag,container,false);
        return view;
    }

    public void refresh(String newsTitle,String newsContent){
        View visibilityLayout = view.findViewById(R.id.visibility_layout);
        visibilityLayout.setVisibility(View.VISIBLE);
        tv_news_title= (TextView) view.findViewById(R.id.tv_news_title);
        tv_news_content= (TextView) view.findViewById(R.id.tv_news_content);
        tv_news_title.setText(newsTitle);  //重新整理新聞的標題
        tv_news_content.setText(newsContent); //重新整理新聞的頭部
    }
}

單頁模式使用,建立NewsContentActivity,指定佈局名為news_content,引入NewsContentFragment佈局,修改佈局檔案如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <fragment
        android:id="@+id/news_content_fragment"
        android:name="com.example.hjw.fragmentbestpractice.NewsContentFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

修改NewsContentActivity 中的程式碼,如下:

public class NewsContentActivity extends AppCompatActivity {

    public static void actionStart(Context context,String newsTitle,String newsContent){
        Intent intent=new Intent(context,NewsContentActivity.class);
        intent.putExtra("news_title",newsTitle);
        intent.putExtra("news_content",newsContent);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_content);

        Intent intent = getIntent();
        String news_title = intent.getStringExtra("news_title"); //獲取新聞的標題
        String news_content = intent.getStringExtra("news_content"); //獲取新聞的內容
        NewsContentFragment newsContentFragment= (NewsContentFragment) getSupportFragmentManager().findFragmentById(R.id.news_content_fragment);
        newsContentFragment.refresh(news_title,news_content); //重新整理NewsContentFragment介面
    }
}

新建news_title_frag.xml佈局,用於顯示新聞的標題列表的佈局,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/news_title_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

新聞標題的子佈局,新建news_item.xml作為RecyclerView中子項的佈局,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_news_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="end"
    android:paddingBottom="15dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="15dp"
    android:singleLine="true"
    android:textSize="18sp" />

新建NewsTitleFragment作為展示新聞列表的碎片,onCreateView載入news_title_frag.xml佈局,程式碼如下:

public class NewsTitleFragment extends Fragment{

    private boolean isTowPane;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.news_title_frag, container, false);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (getActivity().findViewById(R.id.news_content_layout)!=null){
            isTowPane=true;  //可以找到news_content_layout佈局,為雙頁
        }else{
            isTowPane=false; //找不到news_content_layout佈局,為單頁
        }

}

接下來我們修改main_activity.xml,單頁模式中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/news_title_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/news_title_fragment"
        android:name="com.example.hjw.fragmentbestpractice.NewsTitleFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


</FrameLayout>

新建layout-600dp資料夾,新建main_activity.xml佈局,雙頁模式程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <fragment
        android:id="@+id/news_title_fragment"
        android:name="com.example.hjw.fragmentbestpractice.NewsTitleFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <FrameLayout
        android:id="@+id/news_content_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3">

        <fragment
            android:id="@+id/news_content_fragment"
            android:name="com.example.hjw.fragmentbestpractice.NewsContentFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>

</LinearLayout>

接下來在NewsTitleFragment中通過RecyclerView展示新聞列表,在NewsTitleFragment中新建內部類NewsAdapter作為RecyclerView的介面卡,程式碼如下所示:

public class NewsTitleFragment extends Fragment{

    private boolean isTowPane;

    ......

    class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder>{

        private List<News> mData;

        public NewsAdapter(List<News> mData) {
            this.mData = mData;
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item,parent,false);
            final ViewHolder holder=new ViewHolder(view);
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    News news = mData.get(holder.getAdapterPosition());
                    if (isTowPane){
                        //如果是雙頁,重新整理NewsContentFragment中的內容
                        NewsContentFragment newsContentFragment= (NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment);
                        newsContentFragment.refresh(news.getTitle(),news.getContent());
                    }else{
                        //如果是單頁,直接啟動NewsContentActivity
                        NewsContentActivity.actionStart(getContext(),news.getTitle(),news.getContent());
                    }
                }
            });
            return holder;
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            News news = mData.get(position);
            holder.tv_news_title.setText(news.getTitle());
        }

        @Override
        public int getItemCount() {
            return mData.size();
        }

        class ViewHolder extends RecyclerView.ViewHolder{
            TextView tv_news_title;
            public ViewHolder(View itemView) {
                super(itemView);
                tv_news_title= (TextView) itemView.findViewById(R.id.tv_news_title);
            }
        }

    }

}

通過onCreateViewHolder方法中註冊的點選事件,獲取到點選項News的例項,通過isTwoPane判斷是單頁還是雙頁,更新裡面的資料,修改NewsTitleFragment中的程式碼如下:

public class NewsTitleFragment extends Fragment{

    private boolean isTowPane;
    private RecyclerView news_title_recycler_view;
    List<News> newsList=new ArrayList<>();
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.news_title_frag, container, false);
        news_title_recycler_view = (RecyclerView) view.findViewById(R.id.news_title_recycler_view);
        LinearLayoutManager layoutManager=new LinearLayoutManager(getContext());
        news_title_recycler_view.setLayoutManager(layoutManager);
        NewsAdapter adapter = new NewsAdapter(getNews());
        news_title_recycler_view.setAdapter(adapter);
        return view;
    }


    public List<News> getNews() {
        for (int i = 1; i <= 50; i++) {
            News news=new News();
            news.setTitle("This is news title "+i);
            news.setContent(getRandomLengthContent("This is news content"+i+"."));
            newsList.add(news);
        }
        return newsList;
    }

    private String getRandomLengthContent(String content) {
        Random random=new Random();
        int length = random.nextInt(20)+1;
        StringBuilder builder=new StringBuilder();
        for (int i = 0; i < length; i++) {
            builder.append(content);
        }
        return builder.toString();
    }

    ...

}

執行效果:
單頁模式的執行效果:
d1
點選子選項跳轉:
d2

雙頁模式的執行效果圖:
s

4.5 小結與點評

本章我們瞭解碎片的基本概念,以及使用場景,掌握了碎片的常用方法,學習了碎片的生命週期,以及動態載入佈局。