天天看点

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();
            }
        }
    }
}
           

继续阅读