Condensed or otherwise, Some Fragment Sample code

satya - 11/1/2013 10:01:27 AM

Should things conspire as I want, I should post some sample code here

For I am a lazy one at heart!! and this should let me steal when I need...

satya - 11/28/2013 8:35:34 PM

MonitoredFragment


/**
 * 1. Encapsulates Key Callbacks
 * 2. Documents them
 * 3. Monitors them
 * 4. Provides a pattern for what to override
 * 5. works as a sample for extending fragment
 * 
 */
public class MonitoredFragment 
extends Fragment
{
   public static String DEBUG_TAG_NAME="com.androidbook.asynctask.debugtag";
   private String tag = "No tag specified yet. Still being constructed";
   
   //Set it on start
   //Reset it on stop
   boolean bUIReady = false;
   
   /*
    * Default constructor required by the framework for rebirth
    */
   public MonitoredFragment(){};
   /**
    * This is for derived classes to put restrictions on
    * what needs to be in the args bundle.
    */
   public void init(String tagname, Bundle argsBundle)
   {
      argsBundle.putString(this.DEBUG_TAG_NAME,tagname);
      this.setArguments(argsBundle);
   }

   /*
    * Order: 1
    * after: onCreate
    * This is the first method that gets called
    */
   @Override
   public void onAttach(Activity activity) {
      super.onAttach(activity);
      reConstructTagNameFromArgsBundle();
      Log.d(tag,"onAttach called. Very first call back");
   }
   
   private void reConstructTagNameFromArgsBundle()
   {
      Bundle args = this.getArguments();
      if (args == null)
      {
         Log.w(tag,"Sorry no args set to collect the tag name");
         return;
      }      
      
      String tagname = args.getString(this.DEBUG_TAG_NAME);
      if (tagname == null)
      {
         Log.w(tag,"Sorry no debug tag specified");
         return;
      }
      else
      {
         //tagname is available
         tag = tagname;
      }
   }
   
   /*
    * Order: 2
    * method before: onAttach
    * method after: onCreateView
    * 
    * Key notes:
    * 1. Activity hasn't finished creating
    * 2. Activitys views are not ready
    * 3. To know that the activitys views are available use
    * onActivityCreated callback
    * 4. You can read the argument bundle to do initializations.
    * 5. Most likely actitivity has been attached to other fragments as well
    * 6. What ever you can do here can do in onCreateView or
    * onActivityCreated
    * 7. However as onCreateView may not get called all the time you 
    * may want to move that work to onActivityCreated
    * 
    */
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Log.d(tag,"onCreate called. Activity creation hasn't finished yet.");
   }
   
   /*
    * Order: 3
    * method before: onCreate
    * this method: onCreateView
    * method after: onActivityCreated
    * 
    * Key notes:
    * 1. Load the view
    * 2. return the view
    * 3. It may not be called if there is parent attached
    * 4. Don't use the view group to directly attach
    * 5. No need to implement for headless fragments
    * 6. Any initialization work you put here is suspect as it
    * may not get called.
    * 7. So put that initialization code in onCreate or the 
    * next method onActivityCreated
    * 
    */
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
         Bundle savedInstanceState) {
      // TODO Auto-generated method stub
      return super.onCreateView(inflater, container, savedInstanceState);
   }
   /*
    * Order: 4
    * method before: onCreateView
    * this method: onActivityCreated
    * method after: onStart
    * 
    * Key notes:
    * 1. Activities views are good
    * 2. Views of the fragment have been integrated
    * 3. Do any initialization based on 1 and 2
    * 4. This is an important equilibrium call
    * 5. retained fragments should do most of their work here
    * 
    */
   @Override
   public void onActivityCreated(Bundle savedInstanceState) 
   {
      super.onActivityCreated(savedInstanceState);
      Log.d(tag,"onActivityCreated called. All views including activity are ready.");
   }


   /*
    * Order: 5
    * method before: onActivityCreated
    * this method: onStart
    * method after: onResume
    * 
    * Key notes:
    * 1. follow the activity
    * 
    */
   @Override
   public void onStart() {
      super.onStart();
      Log.d(tag,"onstart");
      bUIReady = true;
   }

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

   @Override
   public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);
      Log.d(tag,"onConfigChanged");
   }

   @Override
   public void onDestroy() {
      super.onDestroy();
      Log.d(tag,"onDestroy");
      if (getActivity().isFinishing() == true){
         releaseResources();
      }
   }

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

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

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

   @Override
   public void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
      Log.d(tag,"onSaveInstanceState");
   }

   @Override
   public void onStop() {
      super.onStop();
      Log.d(tag,"onstop");
      bUIReady = false;
   }

   @Override
   public void onTrimMemory(int level) {
      super.onTrimMemory(level);
      Log.d(tag,"onTrimMemory. level:" + level);
   }

   @Override
   public void onViewCreated(View view, Bundle savedInstanceState) {
      // TODO Auto-generated method stub
      super.onViewCreated(view, savedInstanceState);
   }

   //***********************************************************
   //* Additional behavior
   //***********************************************************
   public boolean isActivityReady()
   {
      Activity act = getActivity();
      if(act != null) return true;
      return false;
   }
   
   public boolean isUIReady()
   {
      return bUIReady;
   }
   public void releaseResources()
   {
      Log.d(tag,"Fragment release resources");
   }
}

satya - 11/28/2013 8:36:52 PM

BaseTesterFragment: An example


/*
 * Name: BaseTesterFragment
 *
 * 1. will be a retained non-ui fragment
 * 2. acts as a conduit to the parent activity as well
 * 3. provides access to the activity
 * 
 * Notes;
 * Because it is a headless fragment onCreateView won't be called 
 */
public class BaseTesterFragment 
extends MonitoredFragment
implements IReportBack
{
   /*
    * Default constructor required by the framework for rebirth
    */
   public BaseTesterFragment(){};
   
   public void init(String tagname, Bundle argsBundle)
   {
      super.init(tagname, argsBundle);
   }
   

   public void reportBack(String tag, String message) 
   {
      if (!isUIReady())
      {
         Log.d(tag,"sorry activity is not ready during reportback");
         return;
      }
      //activity is good
      getReportBack().reportBack(tag,message);
   }
   
   private IReportBack getReportBack()
   {
      return (IReportBack)getActivity();
   }

   public void reportTransient(String tag, String message) 
   {
      if (!isUIReady())
      {
         Log.d(tag,"sorry activity is not ready during reportback");
         return;
      }
      //activity is good
      getReportBack().reportBack(tag,message);
   }
   
}//eof-class

satya - 11/28/2013 8:37:49 PM

AsyncTesterFragment: Another level of inheritance


public class AsyncTesterFragment
extends BaseTesterFragment
implements IWorkerObjectClient
{
   private final static String tag="AsyncTesterFragment";
   private final static String FRAGMENT_TAG="RetainedAsyncTesterFragment";

   //This pointer is there to coordinate/manage the lifetime
   //Starts when the menu is clicked
   //Sets to null when the activity dialog closes 
   //after the task is done!
   //
   MyLongTaskWithFragment longTaskWithFragment = null;
   
   //invoked by a menu
   //You need to hold on to it because you may need it
   //to tell it that the activity is up
   //during home and back.
   //You needed this for a dialog
   //but you may not need this for a bar!!
   MyLongTaskWithProgressBar longTaskWithProgressBar = null;
   
   /*
    * Default constructor required by the framework for rebirth
    */
   public AsyncTesterFragment(){};
   
   public void init()
   {
      Bundle b = new Bundle();
      super.init(tag, b);
   }   //Call this from a menu item
   
   public static AsyncTesterFragment newInstance()
   {
      AsyncTesterFragment i = new AsyncTesterFragment();
      i.init();
      return i;
   }
   
   @Override
   public void onStart() {
      super.onStart();
      MonitoredActivityWithADOSupport act = (MonitoredActivityWithADOSupport)getActivity();
      if (longTaskWithFragment != null)
      {
         longTaskWithFragment.onStart(act);
      }
      if (longTaskWithProgressBar != null)
      {
         longTaskWithProgressBar.onStart(act);
      }
   }
   
   
   
   
   public void testFragmentProgressDialog()
   {
      //Construction args:
      //arg1: parent fragment
      //   so that the asynctask can get to the activity
      //   or to the dialog fragment
      //arg2: reportback
      //   so that the asynctask can report back errors etc
      //   this test fragment can play that role as well
      //arg3: Just a tag
      longTaskWithFragment = 
         new MyLongTaskWithFragment(this,this,"Task With Dialogs");
      
      longTaskWithFragment.registerClient(this, 0);
      //Execute it
      longTaskWithFragment.execute("String1","String2","String3");
   }
   
   public void testFragmentProgressBar()
   {
      //Construction args:
      //arg1: parent fragment
      //   so that the asynctask can get to the activity
      //   or to the dialog fragment
      //arg2: reportback
      //   so that the asynctask can report back errors etc
      //   this test fragment can play that role as well
      //arg3: Just a tag
      longTaskWithProgressBar = 
         new MyLongTaskWithProgressBar(this,this,"Task With Progress bar");
      
      longTaskWithProgressBar.registerClient(this, 1);
      //Execute it
      longTaskWithProgressBar.execute("String1","String2","String3");
   }
   /*
    * All this does is to create a fragment that I can use to test
    * functionality.
    * this fragment will be retained.
    * I can locate it anytime I want
    * 
    * I can use menus to invoke functions on it
    * 
    */
   public static AsyncTesterFragment createRetainedAsyncTesterFragment(Activity act)
   {
      Log.d(tag,"Creatign the async tester fragment");
      AsyncTesterFragment frag = AsyncTesterFragment.newInstance();
      frag.setRetainInstance(true);
      //set args if there are any
      FragmentManager fm = act.getFragmentManager();
      FragmentTransaction ft = fm.beginTransaction();
      ft.add(frag, AsyncTesterFragment.FRAGMENT_TAG);
      ft.commit();
      return frag;
   }
   public static AsyncTesterFragment establishRetainedAsyncTesterFragment(Activity act)
   {
      AsyncTesterFragment frag = getRetainedAsyncTesterFragment(act);
      if (frag == null)
      {
         return createRetainedAsyncTesterFragment(act);
      }
      Log.d(tag,"Fragment is already there");
      return frag;
   }
   public static AsyncTesterFragment getRetainedAsyncTesterFragment(Activity act)
   {
      Fragment frag = act.getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
      if (frag == null)
      {
         //sorry that frag doesn't exist
         Log.d(tag,"Fragment doesn't exist");
         return null;
      }
      return (AsyncTesterFragment)frag;
   }
   //asynctask callback
   public void done(IWorkerObject wobj, int workerObjectPassthroughIdentifier)
   {
      if (workerObjectPassthroughIdentifier == 0)
      {
         Log.d(tag, "The asynctask has finished. the dialog is closed. release the pointer");
         this.longTaskWithFragment = null;
      }
      else if (workerObjectPassthroughIdentifier == 1)
      {
         Log.d(tag, "The asynctask with pbar has finished. release the pointer");
         this.longTaskWithProgressBar = null;
      }
   }
   public void releaseResources()
   {
      Log.d(tag,"Fragment release resources");
      if (longTaskWithProgressBar != null)
      {
         longTaskWithProgressBar.releaseResources();
      }
   }
   
}//eof-class