OSDN Git Service

Add new API demo for -swNNNdp resource qualifier.
[android-x86/development.git] / samples / ApiDemos / src / com / example / android / apis / support / app / FragmentRetainInstanceSupport.java
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.example.android.apis.support.app;
18
19 import com.example.android.apis.R;
20
21 import android.support.v4.app.Fragment;
22 import android.support.v4.app.FragmentActivity;
23 import android.support.v4.app.FragmentManager;
24
25 import android.os.Bundle;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.view.View.OnClickListener;
30 import android.widget.Button;
31 import android.widget.ProgressBar;
32
33 /**
34  * This example shows how you can use a Fragment to easily propagate state
35  * (such as threads) across activity instances when an activity needs to be
36  * restarted due to, for example, a configuration change.  This is a lot
37  * easier than using the raw Activity.onRetainNonConfiguratinInstance() API.
38  */
39 public class FragmentRetainInstanceSupport extends FragmentActivity {
40     @Override
41     protected void onCreate(Bundle savedInstanceState) {
42         super.onCreate(savedInstanceState);
43
44         // First time init, create the UI.
45         if (savedInstanceState == null) {
46             getSupportFragmentManager().beginTransaction().add(android.R.id.content,
47                     new UiFragment()).commit();
48         }
49     }
50
51     /**
52      * This is a fragment showing UI that will be updated from work done
53      * in the retained fragment.
54      */
55     public static class UiFragment extends Fragment {
56         RetainedFragment mWorkFragment;
57
58         @Override
59         public View onCreateView(LayoutInflater inflater, ViewGroup container,
60                 Bundle savedInstanceState) {
61             View v = inflater.inflate(R.layout.fragment_retain_instance, container, false);
62
63             // Watch for button clicks.
64             Button button = (Button)v.findViewById(R.id.restart);
65             button.setOnClickListener(new OnClickListener() {
66                 public void onClick(View v) {
67                     mWorkFragment.restart();
68                 }
69             });
70
71             return v;
72         }
73
74         @Override
75         public void onActivityCreated(Bundle savedInstanceState) {
76             super.onActivityCreated(savedInstanceState);
77
78             FragmentManager fm = getFragmentManager();
79
80             // Check to see if we have retained the worker fragment.
81             mWorkFragment = (RetainedFragment)fm.findFragmentByTag("work");
82
83             // If not retained (or first time running), we need to create it.
84             if (mWorkFragment == null) {
85                 mWorkFragment = new RetainedFragment();
86                 // Tell it who it is working with.
87                 mWorkFragment.setTargetFragment(this, 0);
88                 fm.beginTransaction().add(mWorkFragment, "work").commit();
89             }
90         }
91
92     }
93
94     /**
95      * This is the Fragment implementation that will be retained across
96      * activity instances.  It represents some ongoing work, here a thread
97      * we have that sits around incrementing a progress indicator.
98      */
99     public static class RetainedFragment extends Fragment {
100         ProgressBar mProgressBar;
101         int mPosition;
102         boolean mReady = false;
103         boolean mQuiting = false;
104
105         /**
106          * This is the thread that will do our work.  It sits in a loop running
107          * the progress up until it has reached the top, then stops and waits.
108          */
109         final Thread mThread = new Thread() {
110             @Override
111             public void run() {
112                 // We'll figure the real value out later.
113                 int max = 10000;
114
115                 // This thread runs almost forever.
116                 while (true) {
117
118                     // Update our shared state with the UI.
119                     synchronized (this) {
120                         // Our thread is stopped if the UI is not ready
121                         // or it has completed its work.
122                         while (!mReady || mPosition >= max) {
123                             if (mQuiting) {
124                                 return;
125                             }
126                             try {
127                                 wait();
128                             } catch (InterruptedException e) {
129                             }
130                         }
131
132                         // Now update the progress.  Note it is important that
133                         // we touch the progress bar with the lock held, so it
134                         // doesn't disappear on us.
135                         mPosition++;
136                         max = mProgressBar.getMax();
137                         mProgressBar.setProgress(mPosition);
138                     }
139
140                     // Normally we would be doing some work, but put a kludge
141                     // here to pretend like we are.
142                     synchronized (this) {
143                         try {
144                             wait(50);
145                         } catch (InterruptedException e) {
146                         }
147                     }
148                 }
149             }
150         };
151
152         /**
153          * Fragment initialization.  We way we want to be retained and
154          * start our thread.
155          */
156         @Override
157         public void onCreate(Bundle savedInstanceState) {
158             super.onCreate(savedInstanceState);
159
160             // Tell the framework to try to keep this fragment around
161             // during a configuration change.
162             setRetainInstance(true);
163
164             // Start up the worker thread.
165             mThread.start();
166         }
167
168         /**
169          * This is called when the Fragment's Activity is ready to go, after
170          * its content view has been installed; it is called both after
171          * the initial fragment creation and after the fragment is re-attached
172          * to a new activity.
173          */
174         @Override
175         public void onActivityCreated(Bundle savedInstanceState) {
176             super.onActivityCreated(savedInstanceState);
177
178             // Retrieve the progress bar from the target's view hierarchy.
179             mProgressBar = (ProgressBar)getTargetFragment().getView().findViewById(
180                     R.id.progress_horizontal);
181
182             // We are ready for our thread to go.
183             synchronized (mThread) {
184                 mReady = true;
185                 mThread.notify();
186             }
187         }
188
189         /**
190          * This is called when the fragment is going away.  It is NOT called
191          * when the fragment is being propagated between activity instances.
192          */
193         @Override
194         public void onDestroy() {
195             // Make the thread go away.
196             synchronized (mThread) {
197                 mReady = false;
198                 mQuiting = true;
199                 mThread.notify();
200             }
201
202             super.onDestroy();
203         }
204
205         /**
206          * This is called right before the fragment is detached from its
207          * current activity instance.
208          */
209         @Override
210         public void onDetach() {
211             // This fragment is being detached from its activity.  We need
212             // to make sure its thread is not going to touch any activity
213             // state after returning from this function.
214             synchronized (mThread) {
215                 mProgressBar = null;
216                 mReady = false;
217                 mThread.notify();
218             }
219
220             super.onDetach();
221         }
222
223         /**
224          * API for our UI to restart the progress thread.
225          */
226         public void restart() {
227             synchronized (mThread) {
228                 mPosition = 0;
229                 mThread.notify();
230             }
231         }
232     }
233 }