package vandy.mooc.model; import java.lang.ref.WeakReference; import vandy.mooc.MVP; import android.net.Uri; /** * This class plays the "Model" role in the Model-View-Presenter (MVP) * pattern by defining an interface for providing data that will be * acted upon by the "Presenter" and "View" layers in the MVP pattern. * It implements the MVP.ProvidedModelOps so it can be created/managed * by the GenericModel framework. This class plays the role of the * "Abstraction" in the Bridge pattern to decouple the interface of * the Model layer from the particular type of Service used to * implement this layer. */ public class ImageModel implements MVP.ProvidedModelOps { /** * Debugging tag used by the Android logger. */ protected final static String TAG = ImageModel.class.getSimpleName(); /** * Indicates the desired type of Service. */ public enum ServiceType { BOUND_SERVICE, // Use a Bound Service to download an image. STARTED_SERVICE // Use a Started Service to download an image. } /** * Type of Service (i.e., BOUND_SERVICE or STARTED_SERVICE) to use * for the ImageModel implementation. */ private ServiceType mServiceType; /** * Reference to the selected implementation. Play the role of the * "Impl" in the Bridge pattern. */ private ImageModelImpl mImageModelImpl; /** * A WeakReference used to access methods in the Presenter layer. * The WeakReference enables garbage collection. */ protected WeakReference<MVP.RequiredPresenterOps> mImagePresenter; /** * Hook method called when a new ImageModel instance is created. * Simply forward to the implementation. * * @param presenter * A reference to the Presenter layer. */ @Override public void onCreate(MVP.RequiredPresenterOps presenter) { // Set the WeakReference. mImagePresenter = new WeakReference<>(presenter); // Create a BOUND_SERVICE by default. setServiceType(ServiceType.BOUND_SERVICE); } /** * Hook method called to shutdown the Presenter layer. */ @Override public void onDestroy(boolean isChangingConfigurations) { // Forward the onDestroy(). mImageModelImpl.onDestroy(isChangingConfigurations); } /** * Start a download. When the download finishes its results are * passed up to the Presentation layer via the * onDownloadComplete() method defined in RequiredPresenterOps. * * @param url * URL of the image to download. * @param directoryPathname * Uri of the directory to store the downloaded image. */ @Override public void startDownload(Uri url, Uri directoryPathname) { mImageModelImpl.startDownload(url, directoryPathname); } /** * Set the type of Service to use for the ImageModel * implementation. * * @param serviceType * Type of Service, i.e., BOUND_SERVICE or STARTED_SERVICE. */ public void setServiceType(ImageModel.ServiceType serviceType) { // Only set the new ServiceType if it's different than the one // that's already in place. if (mServiceType != serviceType) { mServiceType = serviceType; if (mImageModelImpl != null) // Destroy the existing implementation, if any. mImageModelImpl.onDestroy(false); switch (mServiceType) { case BOUND_SERVICE: // Create an implementation that uses a Bound Service. mImageModelImpl = new ImageModelImplBoundService(); break; case STARTED_SERVICE: // Create an implementation that uses a Started // Service. mImageModelImpl = new ImageModelImplStartedService(); break; } // Initialize the ImageModel implementation. mImageModelImpl.onCreate(mImagePresenter.get()); } } }