package org.tvbrowser.tvbrowser; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import android.os.Handler; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.util.Log; public class LoaderUpdater { private static final int TIME_UPDATE_DELAY = 400; private Fragment mFragment; private boolean mIsRunning; private long mLastUpdateStart; private Thread mUpdateWaitingThread; private Handler mHandler; public LoaderUpdater(Fragment fragment, Handler handler) throws UnsupportedFragmentException, NullPointerException { if(fragment instanceof LoaderManager.LoaderCallbacks<?>) { mFragment = fragment; } else { throw new UnsupportedFragmentException(); } if(handler == null) { throw new NullPointerException("Handler cannot be null"); } mHandler = handler; mLastUpdateStart = 0; /*final Class<?>[] interfaces = mFragment.getClass().getInterfaces(); final String interfaceClassName = LoaderManager.LoaderCallbacks.class.getCanonicalName(); * * for(Class<?> test : interfaces) { if(test.getCanonicalName().equals(interfaceClassName)) { mFragment = fragment; mLoaderCallback = (LoaderManager.LoaderCallbacks<?>)fragment; break; } }*/ } public void setIsRunning() { mIsRunning = true; } public void setIsNotRunning() { mIsRunning = false; } public boolean isRunning() { return mIsRunning; } public void startUpdate() { startUpdate(0, null); } public void startUpdate(final CallbackObjects callbackObjects) { startUpdate(0, callbackObjects); } public void startUpdate(long nextUpdate) { startUpdate(nextUpdate, null); } public synchronized void startUpdate(long nextUpdate, final CallbackObjects callbackObjects) { mLastUpdateStart = System.currentTimeMillis(); if((nextUpdate == 0 || nextUpdate >= System.currentTimeMillis()) && (mUpdateWaitingThread == null || !mUpdateWaitingThread.isAlive())) { mUpdateWaitingThread = new Thread("LoaderUpdate UPDATE WAITING THREAD") { @Override public void run() { while(mLastUpdateStart + TIME_UPDATE_DELAY > System.currentTimeMillis()) { try { sleep(TIME_UPDATE_DELAY); } catch (InterruptedException e) { // Ignore } } if(!mFragment.isDetached() && mFragment.getActivity() != null && mIsRunning) { if(mFragment instanceof Callback) { ((Callback) mFragment).handleCallback(callbackObjects); } if(mFragment.getLoaderManager().hasRunningLoaders()) { try { mFragment.getLoaderManager().getLoader(0).stopLoading(); }catch(Throwable t) {} } Log.d("info14", "update Fragment: " + mFragment.getClass().getCanonicalName() + " " + System.currentTimeMillis()); mHandler.post(new Runnable() { @Override public void run() { if(!mFragment.isDetached() && mFragment.getActivity() != null && mIsRunning) { mFragment.getLoaderManager().restartLoader(0, null, (LoaderManager.LoaderCallbacks<?>)mFragment); } } }); } } }; mUpdateWaitingThread.start(); } } public static final class UnsupportedFragmentException extends Exception { public UnsupportedFragmentException() { super("Fragment not supported, must implement android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor>"); } } public static final class CallbackObject<T> { private String mName; private T mValue; public CallbackObject(String name, T value) throws NullPointerException { if(name == null) { throw new NullPointerException("No null values for name allowed."); } mName = name; mValue = value; } public String getName() { return mName; } public T getValue() { return mValue; } @Override public int hashCode() { return Arrays.hashCode(mName.getBytes()); } @Override public boolean equals(Object o) { if(o instanceof CallbackObject) { return mName.equals(((CallbackObject<?>) o).mName); } return super.equals(o); } } public static final class CallbackObjects { private HashSet<CallbackObject<?>> mCallbackObjects; public CallbackObjects(CallbackObject<?>... initialObjects) { mCallbackObjects = new HashSet<LoaderUpdater.CallbackObject<?>>(); if(initialObjects != null) { Collections.addAll(mCallbackObjects, initialObjects); } } public void addOrReplace(CallbackObject<?> callbackObject) { synchronized (mCallbackObjects) { mCallbackObjects.remove(callbackObject); mCallbackObjects.add(callbackObject); } } public CallbackObject<?>[] getCallbackObjects() { synchronized (mCallbackObjects) { return mCallbackObjects.toArray(new CallbackObject[mCallbackObjects.size()]); } } public Object getCallbackObjectValue(String name, Object defaultValue) { final CallbackObject<?> result = getCallbackObject(name, null); if(result != null) { defaultValue = result.mValue; } return defaultValue; } public CallbackObject<?> getCallbackObject(String name, CallbackObject<?> defaultValue) { synchronized (mCallbackObjects) { for(CallbackObject<?> test : mCallbackObjects) { if(name.equals(test.mName)) { defaultValue = test; break; } } } return defaultValue; } } public static interface Callback { public void handleCallback(CallbackObjects callbackObjects); } }