天天看點

Android Api Demos登頂之路(四十三)Fragment-->Retain Instance

這個Demo示範了如何從另一個Fragment中擷取資料,用到的方法是setTargetFragment方法,該方法允許為fragment設定一個目标fragment,該fragment就可以把目标fragment所需要的結果傳回給目标fragment。

同時示範了fragment另一個強大的功能:儲存fragment執行個體的功能。就是可以在Activity重新建立時可以不完全銷毀Fragment,以便Fragment可以恢複。在onCreate()方法中調用setRetainInstance(true/false)方法是最佳位置。

特别需要注意的是:當在onCreate()方法中調用了setRetainInstance(true)後,Fragment恢複時會跳過onCreate()和onDestroy()方法,是以不能在onCreate()中放置一些初始化邏輯,切忌!

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:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="@string/hello_world" />
    <ProgressBar 
        android:id="@+id/progress"
        android:layout_width="240dp"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_gravity="center"
        android:layout_marginTop="5dp"
        android:max="100"/>
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:id="@+id/restart"
        android:text="restart"/>

</LinearLayout>
           

MainActivity

public class MainActivity extends Activity {
    private RetainFragment mWorkFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            UiFragment ui = new UiFragment();
            getFragmentManager().beginTransaction()
                    .add(android.R.id.content, ui).commit();
        }
    }

    public class UiFragment extends Fragment {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.activity_main, container, false);
            Button restart = (Button) v.findViewById(R.id.restart);
            restart.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    mWorkFragment.restart();
                }
            });
            return v;
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            FragmentManager fm = getFragmentManager();
            mWorkFragment = (RetainFragment) fm.findFragmentByTag("work");
            // 判斷如果RetainFragment沒有被保留,或者是第一次運作,則建立
            // RetainFragment的執行個體
            if (mWorkFragment == null) {
                mWorkFragment = new RetainFragment();
                // 設定目标Fragmnet,設定後目标Fragment就可以直接使用該Fragment運作的結果了。
                mWorkFragment.setTargetFragment(this, );
                fm.beginTransaction().add(mWorkFragment, "work").commit();
            }
        }
    }

    public class RetainFragment extends Fragment {
        private ProgressBar progressBar;
        // 進度條目前的進度值
        private int currentPosition;
        // 進度條的最大值
        private int max = ;
        // 判斷進度條是否準備好(Ui界面是否準備完畢)
        private boolean mReady = false;
        // 判斷應用是否已經退出
        private boolean mQuited = false;

        Thread mThread = new Thread() {
            @Override
            public void run() {
                super.run();
                while (true) {
                    synchronized (this) {
                        // 如果UI沒有準備好或者進度條已經達到最大值,則讓線程處于等待狀态
                        while (!mReady || currentPosition >= max) {
                            // 如果應用已經退出則結束循環
                            if (mQuited) {
                                return;
                            } else {
                                try {
                                    wait();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                        // 更新進度條
                        max = progressBar.getMax();
                        currentPosition++;
                        progressBar.setProgress(currentPosition);
                    }
                    synchronized (this) {
                        // 每隔50毫秒更新一次進度
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }   
                    }
                }
            }

        };

        // 開啟線程用以完成我們要處理的資料,在這裡隻是簡單地示範了一個更新進度條的例子
        // 當進度條達到最大值後停止并使線程處于等待狀态

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            /*
             * Fragment有一個非常強大的功能——就是可以在Activity重新建立時可以
             * 不完全銷毀Fragment,以便Fragment可以恢複。在onCreate()方法中
             * 調用setRetainInstance(true/false)方法是最佳位置。
             */
            setRetainInstance(true);
            mThread.start();
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            // activity建立後,從目标fragment中擷取進度條
            progressBar = (ProgressBar) getTargetFragment().getView()
                    .findViewById(R.id.progress);
            // Ui界面準備完畢,喚醒程序
            synchronized (mThread) {
                mReady = true;
                mThread.notify();
            }
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            synchronized (mThread) {
                mReady = false;
                mQuited = true;
                mThread.notify();
            }
        }

        @Override
        public void onDetach() {
            super.onDetach();
            // 當fragment與activity分離時,将進度條置空
            synchronized (mThread) {
                progressBar = null;
                mReady = false;
                mThread.notify();
            }
        }

        public void restart() {
            synchronized (mThread) {
                currentPosition = ;
                mThread.notify();
            }
        }
    }
}
           

繼續閱讀