package com.balch.mocktrade.portfolio; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.support.v4.content.AsyncTaskLoader; import android.support.v4.content.LocalBroadcastManager; import com.balch.mocktrade.account.Account; import com.balch.mocktrade.investment.Investment; import com.balch.mocktrade.order.Order; import com.balch.mocktrade.settings.Settings; import java.util.Date; import java.util.List; /** * Adapted From http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html */ public class PortfolioLoader extends AsyncTaskLoader<PortfolioData> { private static final String TAG = PortfolioLoader.class.getSimpleName(); private final PortfolioModel mPortfolioModel; private final Settings mSettings; private PortfolioData mPortfolioData; private UpdateReceiver mUpdateReceiver; public PortfolioLoader(Context context, PortfolioModel model, Settings settings) { super(context); mPortfolioModel = model; mSettings = settings; } @Override public PortfolioData loadInBackground() { PortfolioData portfolioData = new PortfolioData(); List<Account> accounts = mPortfolioModel.getAccounts(!mSettings.getBoolean(Settings.Key.PREF_HIDE_EXCLUDE_ACCOUNTS)); portfolioData.addAccounts(accounts); portfolioData.addInvestments(mPortfolioModel.getAllInvestments()); portfolioData.setLastSyncTime(new Date(mSettings.getLastSyncTime())); portfolioData.setLastQuoteTime(mPortfolioModel.getLastQuoteTime()); List<Order> openOrders = mPortfolioModel.getOpenOrders(); for (Order o : openOrders) { portfolioData.addToOpenOrderCount(o.getAccount().getId()); } // populate investment account object // hopefully one day investment.account will be set in the model for (Account a : portfolioData.getAccounts()) { List<Investment> investments = portfolioData.getInvestments(a.getId()); if (investments != null) { for (Investment i : investments) { i.setAccount(a); } } } return portfolioData; } @Override public void deliverResult(PortfolioData data) { if (isReset()) { // The Loader has been reset; ignore the result and invalidate the data. return; } // Hold a reference to the old data so it doesn't get garbage collected. // We must protect it until the new data has been delivered. PortfolioData oldData = mPortfolioData; mPortfolioData = data; if (isStarted()) { // If the Loader is in a started state, deliver the results to the // client. The superclass method does this for us. super.deliverResult(data); } } @Override protected void onStartLoading() { if (mPortfolioData != null) { // Deliver any previously loaded data immediately. deliverResult(mPortfolioData); } // Begin monitoring the underlying data source. if (mUpdateReceiver == null) { mUpdateReceiver = new UpdateReceiver(); LocalBroadcastManager.getInstance(getContext()) .registerReceiver(mUpdateReceiver, new IntentFilter(PortfolioUpdateBroadcaster.ACTION)); } if (takeContentChanged() || mPortfolioData == null) { // When the observer detects a change, it should call onContentChanged() // on the Loader, which will cause the next call to takeContentChanged() // to return true. If this is ever the case (or if the current data is // null), we force a new load. forceLoad(); } } @Override protected void onStopLoading() { // The Loader is in a stopped state, so we should attempt to cancel the // current load (if there is one). cancelLoad(); // Note that we leave the observer as is. Loaders in a stopped state // should still monitor the data source for changes so that the Loader // will know to force a new load if it is ever started again. } @Override protected void onReset() { super.onReset(); // Ensure the loader has been stopped. onStopLoading(); // At this point we can release the resources associated with 'mData'. if (mPortfolioData != null) { mPortfolioData = null; } // The Loader is being reset, so we should stop monitoring for changes. if (mUpdateReceiver != null) { LocalBroadcastManager.getInstance(getContext()) .unregisterReceiver(mUpdateReceiver); mUpdateReceiver = null; } } @Override public void onCanceled(PortfolioData data) { // Attempt to cancel the current asynchronous load. super.onCanceled(data); } private class UpdateReceiver extends BroadcastReceiver { private UpdateReceiver() { } @Override public void onReceive(Context context, Intent intent) { onContentChanged(); } } }