Java tutorial
/** * Copyright 2011 Gavin Saunders * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package simple.android.compat; import java.io.Serializable; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Date; import simple.android.Command; import simple.android.CommandProcessor; import simple.android.UIWidget; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.util.Log; import android.view.View; public abstract class SimpleFragmentActivity<T extends Serializable> extends FragmentActivity { private SimpleActivityState<T> mState; private CommandProcessor mCommandProcessor; public static class SimpleActivityState<T> implements Serializable { private static final long serialVersionUID = -3547400596204942327L; public T userData; private ArrayList<AsyncTask<Void, Void, Void>> mAsyncTasks; public ArrayList<AsyncTask<Void, Void, Void>> getAsyncTasks() { if (mAsyncTasks == null) { mAsyncTasks = new ArrayList<AsyncTask<Void, Void, Void>>(); } return mAsyncTasks; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { mState = (SimpleActivityState<T>) savedInstanceState.getSerializable("state"); } if (mState == null) { mState = new SimpleActivityState<T>(); mState.userData = onNewState(); } } @Override protected void onStart() { super.onStart(); onRestoreState(mState.userData); } @Override public void setContentView(int layoutResID) { super.setContentView(layoutResID); Class<?> c = getClass(); initUIWidgets(c); } private void initUIWidgets(Class<?> c) { //Log.i("SysMon4A", "---- initUIWidgets ----"); Field[] fields = c.getDeclaredFields(); for (Field field : fields) { UIWidget a = field.getAnnotation(UIWidget.class); if (a != null) { //Log.i("SysMon4A", "---- initUIWidgets ----: found field " + a); field.setAccessible(true); View view = findViewById(a.id()); try { field.set(this, view); } catch (IllegalArgumentException e) { Log.e("SysMon4A", "Failed to set @UIWidget", e); } catch (IllegalAccessException e) { Log.e("SysMon4A", "Failed to set @UIWidget", e); } catch (ClassCastException e) { Log.e("SysMon4A", "Failed to set @UIWidget", e); } } } Class<?> sc = c.getSuperclass(); if (!SimpleFragmentActivity.class.equals(sc)) { initUIWidgets(sc); } } protected CommandProcessor getCommandProcessor() { if (mCommandProcessor == null) { mCommandProcessor = new CommandProcessor() { @Override public void executeAt(Date time, Command command) { } @Override public void executeAsync(Command command) { executeAsyncCommand(command); } @Override public void cancel(Command command) { cancelCommand(command); } }; } return mCommandProcessor; } /** * TODO: fail if command already executing. Should create new instance of command */ private void executeAsyncCommand(final Command command) { final AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { Log.i("SimpleAndroid", command + " executing...."); command.execute(); return null; } @Override protected void onPostExecute(Void result) { mState.getAsyncTasks().remove(this); Log.i("SimpleAndroid", command + " completed"); } @Override protected void onCancelled() { command.cancel(); mState.getAsyncTasks().remove(this); Log.i("SimpleAndroid", command + " cancelled"); } }; mState.getAsyncTasks().add(asyncTask); asyncTask.execute(); } protected void cancelCommand(final Command command) { throw new RuntimeException("Not implemented!"); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putSerializable("state", mState); } /** * TODO: Does this need to be Serializable? */ protected abstract T onNewState(); protected abstract void onRestoreState(T state); protected T getState() { return mState.userData; } @Override protected void onDestroy() { if (isFinishing()) { ArrayList<AsyncTask<Void, Void, Void>> tasks = mState.getAsyncTasks(); for (AsyncTask<Void, Void, Void> asyncTask : tasks) { asyncTask.cancel(false); // TODO: should this be true? } } super.onDestroy(); } }