2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.example.android.apis.support.app;
19 import com.example.android.apis.R;
21 import android.support.v4.app.Fragment;
22 import android.support.v4.app.FragmentActivity;
23 import android.support.v4.app.FragmentManager;
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;
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.
39 public class FragmentRetainInstanceSupport extends FragmentActivity {
41 protected void onCreate(Bundle savedInstanceState) {
42 super.onCreate(savedInstanceState);
44 // First time init, create the UI.
45 if (savedInstanceState == null) {
46 getSupportFragmentManager().beginTransaction().add(android.R.id.content,
47 new UiFragment()).commit();
52 * This is a fragment showing UI that will be updated from work done
53 * in the retained fragment.
55 public static class UiFragment extends Fragment {
56 RetainedFragment mWorkFragment;
59 public View onCreateView(LayoutInflater inflater, ViewGroup container,
60 Bundle savedInstanceState) {
61 View v = inflater.inflate(R.layout.fragment_retain_instance, container, false);
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();
75 public void onActivityCreated(Bundle savedInstanceState) {
76 super.onActivityCreated(savedInstanceState);
78 FragmentManager fm = getFragmentManager();
80 // Check to see if we have retained the worker fragment.
81 mWorkFragment = (RetainedFragment)fm.findFragmentByTag("work");
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();
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.
99 public static class RetainedFragment extends Fragment {
100 ProgressBar mProgressBar;
102 boolean mReady = false;
103 boolean mQuiting = false;
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.
109 final Thread mThread = new Thread() {
112 // We'll figure the real value out later.
115 // This thread runs almost forever.
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) {
128 } catch (InterruptedException e) {
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.
136 max = mProgressBar.getMax();
137 mProgressBar.setProgress(mPosition);
140 // Normally we would be doing some work, but put a kludge
141 // here to pretend like we are.
142 synchronized (this) {
145 } catch (InterruptedException e) {
153 * Fragment initialization. We way we want to be retained and
157 public void onCreate(Bundle savedInstanceState) {
158 super.onCreate(savedInstanceState);
160 // Tell the framework to try to keep this fragment around
161 // during a configuration change.
162 setRetainInstance(true);
164 // Start up the worker thread.
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
175 public void onActivityCreated(Bundle savedInstanceState) {
176 super.onActivityCreated(savedInstanceState);
178 // Retrieve the progress bar from the target's view hierarchy.
179 mProgressBar = (ProgressBar)getTargetFragment().getView().findViewById(
180 R.id.progress_horizontal);
182 // We are ready for our thread to go.
183 synchronized (mThread) {
190 * This is called when the fragment is going away. It is NOT called
191 * when the fragment is being propagated between activity instances.
194 public void onDestroy() {
195 // Make the thread go away.
196 synchronized (mThread) {
206 * This is called right before the fragment is detached from its
207 * current activity instance.
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) {
224 * API for our UI to restart the progress thread.
226 public void restart() {
227 synchronized (mThread) {