From 444ed109fb362b7afee953d6a21bd0ed01adcfab Mon Sep 17 00:00:00 2001 From: "Sreehari.KV" Date: Thu, 23 Aug 2018 18:37:33 +0530 Subject: [PATCH] Dagger multiple dependency changes --- .../java/com/dev/movieapp/app/MovieApp.java | 48 ++++++------------- .../movieapp/components/ContextComponent.java | 18 ------- .../movieapp/components/NetworkComponent.java | 20 -------- .../components/ApplicationComponent.java | 21 ++++++++ .../components/InjectionSubComponent.java | 21 ++++++++ .../customscopes/ApplicationScope.java | 15 ++++++ .../dipinject/modules/ApplicationModule.java | 38 +++++++++++++++ .../modules/NetworkModule.java | 47 +++++++++--------- .../dev/movieapp/modules/ContextModule.java | 27 ----------- .../com/dev/movieapp/modules/GlideModule.java | 9 ---- .../movieapp/ui/activities/BaseActivity.java | 19 ++++++++ .../detail/ResultDetailActivity.java | 21 ++++---- .../landing/ResultListActivity.java | 48 ++++++++++--------- .../ui/activities/splash/SplashActivity.java | 19 ++++---- .../dev/movieapp/ui/fragments/BaseFrag.java | 24 ++++++++-- .../detailfrag/ResultDetailFragment.java | 29 ++++++----- .../ResultDetailTabFragment.java | 17 ++++++- .../com/dev/movieapp/utils/AppLogger.java | 22 +++++++++ .../java/com/dev/movieapp/utils/AppUtils.java | 25 +++++----- app/src/main/res/values/strings.xml | 1 + 20 files changed, 280 insertions(+), 209 deletions(-) delete mode 100644 app/src/main/java/com/dev/movieapp/components/ContextComponent.java delete mode 100644 app/src/main/java/com/dev/movieapp/components/NetworkComponent.java create mode 100644 app/src/main/java/com/dev/movieapp/dipinject/components/ApplicationComponent.java create mode 100644 app/src/main/java/com/dev/movieapp/dipinject/components/InjectionSubComponent.java create mode 100644 app/src/main/java/com/dev/movieapp/dipinject/customscopes/ApplicationScope.java create mode 100644 app/src/main/java/com/dev/movieapp/dipinject/modules/ApplicationModule.java rename app/src/main/java/com/dev/movieapp/{ => dipinject}/modules/NetworkModule.java (77%) delete mode 100644 app/src/main/java/com/dev/movieapp/modules/ContextModule.java delete mode 100644 app/src/main/java/com/dev/movieapp/modules/GlideModule.java create mode 100644 app/src/main/java/com/dev/movieapp/utils/AppLogger.java diff --git a/app/src/main/java/com/dev/movieapp/app/MovieApp.java b/app/src/main/java/com/dev/movieapp/app/MovieApp.java index 16ee900..6b57ab0 100644 --- a/app/src/main/java/com/dev/movieapp/app/MovieApp.java +++ b/app/src/main/java/com/dev/movieapp/app/MovieApp.java @@ -3,41 +3,32 @@ import android.app.Application; import android.content.res.Configuration; -import com.dev.movieapp.components.ContextComponent; -import com.dev.movieapp.components.DaggerContextComponent; -import com.dev.movieapp.components.DaggerNetworkComponent; -import com.dev.movieapp.components.NetworkComponent; -import com.dev.movieapp.modules.ContextModule; -import com.dev.movieapp.modules.NetworkModule; +import com.dev.movieapp.dipinject.components.ApplicationComponent; +import com.dev.movieapp.dipinject.components.DaggerApplicationComponent; +import com.dev.movieapp.dipinject.modules.ApplicationModule; +import com.dev.movieapp.dipinject.modules.NetworkModule; import java.io.File; public class MovieApp extends Application { - private static MovieApp movieAppInstance; - private NetworkComponent mNetworkComponent; - private ContextComponent mContextComponent; + private ApplicationComponent mApplicationComponent; + private File mCacheFile; @Override public void onCreate() { super.onCreate(); - movieAppInstance=this; - - File cacheFile = new File(getCacheDir(), "popularmovieresponses"); - mNetworkComponent = createNetworkComponent(cacheFile); - mContextComponent = createContextComponent(); - } - - public static MovieApp getInstance(){ - return movieAppInstance; - } - - private NetworkComponent createNetworkComponent(File cacheFile) { - return DaggerNetworkComponent.builder().networkModule(new NetworkModule(cacheFile)).build(); + mCacheFile = new File(getCacheDir(), "popular_movie_response"); } - public NetworkComponent getNetworkComponent() { - return mNetworkComponent; + public ApplicationComponent getApplicationComponent() { + if (mApplicationComponent == null) { + mApplicationComponent = DaggerApplicationComponent.builder() + .applicationModule(new ApplicationModule(this)) + .networkModule(new NetworkModule(mCacheFile, this)) + .build(); + } + return mApplicationComponent; } @Override @@ -54,13 +45,4 @@ public void onLowMemory() { public void onTerminate() { super.onTerminate(); } - - private ContextComponent createContextComponent() { - - return DaggerContextComponent.builder().contextModule(new ContextModule(this)).build(); - } - - public ContextComponent getContextComponent(){ - return mContextComponent; - } } diff --git a/app/src/main/java/com/dev/movieapp/components/ContextComponent.java b/app/src/main/java/com/dev/movieapp/components/ContextComponent.java deleted file mode 100644 index fca5536..0000000 --- a/app/src/main/java/com/dev/movieapp/components/ContextComponent.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dev.movieapp.components; - -import com.dev.movieapp.modules.ContextModule; -import com.dev.movieapp.utils.AppUtils; - -import javax.inject.Singleton; - -import dagger.Component; - -/** - * Component to inject Context into interested parties - */ -@Singleton -@Component (modules = ContextModule.class) -public interface ContextComponent { - - void inject(AppUtils appUtils); -} diff --git a/app/src/main/java/com/dev/movieapp/components/NetworkComponent.java b/app/src/main/java/com/dev/movieapp/components/NetworkComponent.java deleted file mode 100644 index f9552f6..0000000 --- a/app/src/main/java/com/dev/movieapp/components/NetworkComponent.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dev.movieapp.components; - - -import com.dev.movieapp.ui.activities.landing.ResultListActivity; -import com.dev.movieapp.modules.NetworkModule; - -import javax.inject.Singleton; - -import dagger.Component; - -/** - * Component for injecting NetworkModule into interested parties - */ - -@Singleton -@Component (modules = NetworkModule.class) -public interface NetworkComponent { - - void inject(ResultListActivity mainActivity); -} diff --git a/app/src/main/java/com/dev/movieapp/dipinject/components/ApplicationComponent.java b/app/src/main/java/com/dev/movieapp/dipinject/components/ApplicationComponent.java new file mode 100644 index 0000000..7e21f43 --- /dev/null +++ b/app/src/main/java/com/dev/movieapp/dipinject/components/ApplicationComponent.java @@ -0,0 +1,21 @@ +package com.dev.movieapp.dipinject.components; + + +import com.dev.movieapp.dipinject.customscopes.ApplicationScope; +import com.dev.movieapp.dipinject.modules.ApplicationModule; +import com.dev.movieapp.dipinject.modules.NetworkModule; + +import dagger.Component; + +@ApplicationScope +@Component + ( + modules = {ApplicationModule.class, NetworkModule.class} + ) +public interface ApplicationComponent { + + + InjectionSubComponent newInjectionComponent(); + + +} diff --git a/app/src/main/java/com/dev/movieapp/dipinject/components/InjectionSubComponent.java b/app/src/main/java/com/dev/movieapp/dipinject/components/InjectionSubComponent.java new file mode 100644 index 0000000..0f9df4b --- /dev/null +++ b/app/src/main/java/com/dev/movieapp/dipinject/components/InjectionSubComponent.java @@ -0,0 +1,21 @@ +package com.dev.movieapp.dipinject.components; + +import com.dev.movieapp.ui.activities.landing.ResultListActivity; +import com.dev.movieapp.ui.activities.splash.SplashActivity; +import com.dev.movieapp.ui.fragments.detailfrag.ResultDetailFragment; +import com.dev.movieapp.ui.fragments.detailtabfrag.ResultDetailTabFragment; + +import dagger.Subcomponent; + +@Subcomponent +public interface InjectionSubComponent { + + void inject(ResultListActivity activity); + + void inject(ResultDetailFragment fragment); + + void inject(SplashActivity activity); + + void inject(ResultDetailTabFragment fragment); + +} diff --git a/app/src/main/java/com/dev/movieapp/dipinject/customscopes/ApplicationScope.java b/app/src/main/java/com/dev/movieapp/dipinject/customscopes/ApplicationScope.java new file mode 100644 index 0000000..8fa4ef6 --- /dev/null +++ b/app/src/main/java/com/dev/movieapp/dipinject/customscopes/ApplicationScope.java @@ -0,0 +1,15 @@ +package com.dev.movieapp.dipinject.customscopes; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +/** + * Custom scope for global application singleton dependencies + */ + +@Scope +@Retention(RetentionPolicy.RUNTIME) +public @interface ApplicationScope { +} diff --git a/app/src/main/java/com/dev/movieapp/dipinject/modules/ApplicationModule.java b/app/src/main/java/com/dev/movieapp/dipinject/modules/ApplicationModule.java new file mode 100644 index 0000000..2075345 --- /dev/null +++ b/app/src/main/java/com/dev/movieapp/dipinject/modules/ApplicationModule.java @@ -0,0 +1,38 @@ +package com.dev.movieapp.dipinject.modules; + +import android.app.Application; + +import com.dev.movieapp.dipinject.customscopes.ApplicationScope; +import com.dev.movieapp.utils.AppLogger; +import com.dev.movieapp.utils.AppUtils; + +import dagger.Module; +import dagger.Provides; + +@Module +public class ApplicationModule { + + private final Application mApplication; + + public ApplicationModule(Application application) { + mApplication = application; + } + + @Provides + @ApplicationScope + Application application() { + return mApplication; + } + + @Provides + @ApplicationScope + AppLogger logger() { + return new AppLogger(); + } + + @Provides + @ApplicationScope + AppUtils getUtils() { + return new AppUtils(mApplication); + } +} diff --git a/app/src/main/java/com/dev/movieapp/modules/NetworkModule.java b/app/src/main/java/com/dev/movieapp/dipinject/modules/NetworkModule.java similarity index 77% rename from app/src/main/java/com/dev/movieapp/modules/NetworkModule.java rename to app/src/main/java/com/dev/movieapp/dipinject/modules/NetworkModule.java index f2c02e1..fc76c3a 100644 --- a/app/src/main/java/com/dev/movieapp/modules/NetworkModule.java +++ b/app/src/main/java/com/dev/movieapp/dipinject/modules/NetworkModule.java @@ -1,8 +1,10 @@ -package com.dev.movieapp.modules; +package com.dev.movieapp.dipinject.modules; +import android.content.Context; import android.util.Log; import com.dev.movieapp.BuildConfig; +import com.dev.movieapp.dipinject.customscopes.ApplicationScope; import com.dev.movieapp.networking.NetworkProcessor; import com.dev.movieapp.networking.NetworkService; import com.dev.movieapp.utils.AppUtils; @@ -14,8 +16,6 @@ import java.util.Collections; import java.util.concurrent.TimeUnit; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; import okhttp3.Cache; @@ -23,7 +23,6 @@ import okhttp3.ConnectionSpec; import okhttp3.Interceptor; import okhttp3.OkHttpClient; -import okhttp3.Request; import okhttp3.Response; import okhttp3.TlsVersion; import retrofit2.Retrofit; @@ -37,18 +36,21 @@ public class NetworkModule { private File mCacheFile; + private Context mContext; /** * Constructor for NetworkModule + * * @param cacheFile */ - public NetworkModule(File cacheFile) { + public NetworkModule(File cacheFile, Context context) { this.mCacheFile = cacheFile; + mContext = context; } @Provides - @Singleton - Retrofit provideCall(){ + @ApplicationScope + Retrofit provideCall() { //Sets up default cache with 10 MB Cache cache = null; @@ -56,7 +58,7 @@ Retrofit provideCall(){ try { cache = new Cache(mCacheFile, cacheSize); } catch (Exception e) { - Log.e("TAG","Cache create error "+e.toString()); + Log.e("TAG", "Cache create error " + e.toString()); } ConnectionSpec spec = new @@ -72,42 +74,42 @@ Retrofit provideCall(){ OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(cache_interceptor) .cache(cache) - .connectTimeout(AppUtils.TIME_OUT , TimeUnit.SECONDS) - .readTimeout(AppUtils.TIME_OUT , TimeUnit.SECONDS) + .connectTimeout(AppUtils.TIME_OUT, TimeUnit.SECONDS) + .readTimeout(AppUtils.TIME_OUT, TimeUnit.SECONDS) .connectionSpecs(Collections.singletonList(spec)) .build(); - // RxJava2 service call support - // Sets OkHttpClient - // Sets Gson converter + // RxJava2 service call support + // Sets OkHttpClient + // Sets Gson converter Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(okHttpClient) .addConverterFactory(providesGsonConverterFactory()) .baseUrl(BuildConfig.BASE_URL).build(); - return retrofit; + return retrofit; } @Provides - @Singleton + @ApplicationScope @SuppressWarnings("unused") public NetworkService providesNetworkService(Retrofit retrofit) { return retrofit.create(NetworkService.class); } @Provides - @Singleton + @ApplicationScope @SuppressWarnings("unused") - public NetworkProcessor providesService( - NetworkService networkService) { + public NetworkProcessor providesService(NetworkService networkService) { return new NetworkProcessor(networkService); } - private static final Interceptor cache_interceptor = new Interceptor() { - @Override public Response intercept(Chain chain) throws IOException { + private final Interceptor cache_interceptor = new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); - if (new AppUtils().isNetworkConnected()) { + if (new AppUtils(mContext).isNetworkConnected()) { int maxAge = 60; // read from cache for 1 minute return originalResponse.newBuilder() .header("Cache-Control", "public, max-age=" + maxAge) @@ -118,7 +120,8 @@ public NetworkProcessor providesService( .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } - }}; + } + }; private GsonConverterFactory providesGsonConverterFactory() { GsonBuilder gsonBuilder = new GsonBuilder(); diff --git a/app/src/main/java/com/dev/movieapp/modules/ContextModule.java b/app/src/main/java/com/dev/movieapp/modules/ContextModule.java deleted file mode 100644 index 270608e..0000000 --- a/app/src/main/java/com/dev/movieapp/modules/ContextModule.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dev.movieapp.modules; - -import android.content.Context; - -import javax.inject.Singleton; - -import dagger.Module; -import dagger.Provides; - -/** - * Dagger module for Context - */ -@Module -public class ContextModule { - - private Context mContext; - - public ContextModule(Context context){ - mContext = context; - } - - @Provides - @Singleton - Context getContext(){ - return mContext; - } -} diff --git a/app/src/main/java/com/dev/movieapp/modules/GlideModule.java b/app/src/main/java/com/dev/movieapp/modules/GlideModule.java deleted file mode 100644 index fa50174..0000000 --- a/app/src/main/java/com/dev/movieapp/modules/GlideModule.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dev.movieapp.modules; - -import com.bumptech.glide.module.AppGlideModule; - -@com.bumptech.glide.annotation.GlideModule -public class GlideModule extends AppGlideModule { - - -} diff --git a/app/src/main/java/com/dev/movieapp/ui/activities/BaseActivity.java b/app/src/main/java/com/dev/movieapp/ui/activities/BaseActivity.java index 73177b9..34862a8 100644 --- a/app/src/main/java/com/dev/movieapp/ui/activities/BaseActivity.java +++ b/app/src/main/java/com/dev/movieapp/ui/activities/BaseActivity.java @@ -13,8 +13,13 @@ import com.bumptech.glide.RequestBuilder; import com.bumptech.glide.request.RequestOptions; import com.dev.movieapp.R; +import com.dev.movieapp.app.MovieApp; +import com.dev.movieapp.dipinject.components.InjectionSubComponent; +import com.dev.movieapp.dipinject.modules.NetworkModule; import com.dev.movieapp.ui.uiinterfaces.AlertCallBack; +import java.io.File; + /** * Base Activity class @@ -24,11 +29,25 @@ */ public abstract class BaseActivity extends AppCompatActivity implements AlertCallBack { + private boolean mIsInjectionComponentUsed = false; + protected AlertDialog mCallBackAlertDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } + + protected InjectionSubComponent getInjectionComponent(){ + + if (mIsInjectionComponentUsed) { + throw new IllegalStateException("should not use Injection more than once."); + } + mIsInjectionComponentUsed=true; + return ((MovieApp)getApplication()) + .getApplicationComponent() + .newInjectionComponent(); + } + public abstract void renderView(); public abstract void init(); diff --git a/app/src/main/java/com/dev/movieapp/ui/activities/detail/ResultDetailActivity.java b/app/src/main/java/com/dev/movieapp/ui/activities/detail/ResultDetailActivity.java index e61010a..bf6038d 100644 --- a/app/src/main/java/com/dev/movieapp/ui/activities/detail/ResultDetailActivity.java +++ b/app/src/main/java/com/dev/movieapp/ui/activities/detail/ResultDetailActivity.java @@ -2,24 +2,18 @@ import android.content.Intent; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; +import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; import android.text.TextUtils; -import android.view.View; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.app.ActionBar; import android.view.MenuItem; import android.widget.ImageView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.dev.movieapp.BuildConfig; import com.dev.movieapp.R; import com.dev.movieapp.models.Result; import com.dev.movieapp.ui.activities.BaseActivity; -import com.dev.movieapp.ui.fragments.detailfrag.ResultDetailFragment; import com.dev.movieapp.ui.activities.landing.ResultListActivity; +import com.dev.movieapp.ui.fragments.detailfrag.ResultDetailFragment; import com.dev.movieapp.utils.AppUtils; import butterknife.BindView; @@ -63,7 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { // Create the detail fragment and add it to the activity // using a fragment transaction. Bundle arguments = new Bundle(); - arguments.putParcelable(AppUtils.RESULT_KEY,mResult); + arguments.putParcelable(AppUtils.RESULT_KEY, mResult); ResultDetailFragment fragment = new ResultDetailFragment(); fragment.setArguments(arguments); @@ -87,9 +81,9 @@ public void init() { if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); } - ResultDetailView detailView=this; + ResultDetailView detailView = this; // Initiate Presenter to manage data - mResultDetailPresenter=new ResultDetailPresenter(mResult); + mResultDetailPresenter = new ResultDetailPresenter(mResult); mResultDetailPresenter.attach(detailView); mResultDetailPresenter.refreshUI(); } @@ -108,15 +102,16 @@ public boolean onOptionsItemSelected(MenuItem item) { /** * Refreshes UI with data + * * @param result */ @Override public void populateUI(Result result) { - if(!TextUtils.isEmpty(result.getBackdropPath())) { + if (!TextUtils.isEmpty(result.getBackdropPath())) { StringBuilder images = new StringBuilder(); images.append(BuildConfig.IMG_BASE_URL + AppUtils.IMG_URL_EXTRA); images.append(result.getBackdropPath()); - loadImage(images.toString(),mImageParallax); + loadImage(images.toString(), mImageParallax); } } diff --git a/app/src/main/java/com/dev/movieapp/ui/activities/landing/ResultListActivity.java b/app/src/main/java/com/dev/movieapp/ui/activities/landing/ResultListActivity.java index 8b5ffbc..fb3b2ce 100644 --- a/app/src/main/java/com/dev/movieapp/ui/activities/landing/ResultListActivity.java +++ b/app/src/main/java/com/dev/movieapp/ui/activities/landing/ResultListActivity.java @@ -8,16 +8,13 @@ import android.view.View; import android.widget.Toast; - import com.dev.movieapp.BuildConfig; import com.dev.movieapp.R; -import com.dev.movieapp.app.MovieApp; import com.dev.movieapp.models.PopularMovies; import com.dev.movieapp.models.Result; import com.dev.movieapp.networking.NetworkProcessor; import com.dev.movieapp.ui.activities.BaseActivity; import com.dev.movieapp.ui.activities.detail.ResultDetailActivity; - import com.dev.movieapp.ui.fragments.detailtabfrag.ResultDetailTabFragment; import com.dev.movieapp.utils.AppUtils; @@ -36,26 +33,31 @@ * item details. On tablets, the activity presents the list of items and * item details side-by-side using two vertical panes. */ -public class ResultListActivity extends BaseActivity implements ResultListActivityView{ +public class ResultListActivity extends BaseActivity implements ResultListActivityView { @Inject public NetworkProcessor mNetworkProcessor; + @Inject + public AppUtils mAppUtils; + @BindView(R.id.toolbar) + Toolbar mToolbar; + private ResultListPresenter mPresenter; - @BindView(R.id.toolbar) Toolbar mToolbar; + /** * Whether or not the activity is in two-pane mode, i.e. running on a tablet * device. */ private boolean mTwoPane; - private int mPage=1; + private int mPage = 1; @Override protected void onCreate(Bundle savedInstanceState) { + getInjectionComponent().inject(this); super.onCreate(savedInstanceState); - MovieApp.getInstance().getNetworkComponent().inject(this); renderView(); init(); - mPresenter =new ResultListPresenter(mNetworkProcessor); + mPresenter = new ResultListPresenter(mNetworkProcessor); mPresenter.attach(this); if (findViewById(R.id.result_detail_container) != null) { @@ -83,37 +85,36 @@ public void init() { @Override public void onFailure(String appErrorMessage) { - Toast.makeText(getApplicationContext(), appErrorMessage, - Toast.LENGTH_LONG).show(); + showMessage(appErrorMessage, R.string.ok, R.string.cancel); } - private void requestMovieList(){ - if(!new AppUtils().isNetworkConnected()){ - showMessage(getString(R.string.network_error),R.string.retry,R.string.cancel); + private void requestMovieList() { + if (!mAppUtils.isNetworkConnected()) { + showMessage(getString(R.string.network_error), R.string.retry, R.string.cancel); return; } - - mPresenter.fetchMovieList(BuildConfig.API_KEY,BuildConfig.API_LANG,mPage); + mPresenter.fetchMovieList(BuildConfig.API_KEY, BuildConfig.API_LANG, mPage); } @Override public void getMovieList(PopularMovies movieList) { - if(movieList==null || movieList.getResults().size()==0){ - Toast.makeText(this,R.string.no_data,Toast.LENGTH_SHORT).show(); - }else{ + if (movieList == null || movieList.getResults().size() == 0) { + Toast.makeText(this, R.string.no_data, Toast.LENGTH_SHORT).show(); + } else { View recyclerView = findViewById(R.id.result_list); assert recyclerView != null; - setupRecyclerView((RecyclerView) recyclerView,movieList.getResults()); + setupRecyclerView((RecyclerView) recyclerView, movieList.getResults()); } } /** * Populates RecyclerView with retrieved data + * * @param recyclerView * @param data */ - private void setupRecyclerView(@NonNull RecyclerView recyclerView,List data) { - recyclerView.setAdapter(new MovieListAdapter(data, new MovieListAdapter.OnItemClickListener(){ + private void setupRecyclerView(@NonNull RecyclerView recyclerView, List data) { + recyclerView.setAdapter(new MovieListAdapter(data, new MovieListAdapter.OnItemClickListener() { @Override public void onClick(Result item) { mPresenter.itemSelected(item); @@ -125,13 +126,14 @@ public void onClick(Result item) { * Check for two pane mode * Pushes Activity if not * Manages Fragment for two pane + * * @param result */ @Override public void pushDetailView(Result result) { if (mTwoPane) { Bundle arguments = new Bundle(); - arguments.putParcelable(AppUtils.RESULT_KEY,result); + arguments.putParcelable(AppUtils.RESULT_KEY, result); ResultDetailTabFragment fragment = new ResultDetailTabFragment(); fragment.setArguments(arguments); getSupportFragmentManager().beginTransaction() @@ -139,7 +141,7 @@ public void pushDetailView(Result result) { .commit(); } else { Intent intent = new Intent(this, ResultDetailActivity.class); - intent.putExtra(AppUtils.RESULT_KEY,result); + intent.putExtra(AppUtils.RESULT_KEY, result); startActivity(intent); } } diff --git a/app/src/main/java/com/dev/movieapp/ui/activities/splash/SplashActivity.java b/app/src/main/java/com/dev/movieapp/ui/activities/splash/SplashActivity.java index 25e5e09..6ba80d7 100644 --- a/app/src/main/java/com/dev/movieapp/ui/activities/splash/SplashActivity.java +++ b/app/src/main/java/com/dev/movieapp/ui/activities/splash/SplashActivity.java @@ -4,10 +4,12 @@ import android.os.Bundle; import com.dev.movieapp.R; -import com.dev.movieapp.ui.activities.landing.ResultListActivity; import com.dev.movieapp.ui.activities.BaseActivity; +import com.dev.movieapp.ui.activities.landing.ResultListActivity; import com.dev.movieapp.utils.AppUtils; +import javax.inject.Inject; + /** * Splash Activity * Validates internet connectivity @@ -16,18 +18,19 @@ public class SplashActivity extends BaseActivity implements SplashView { SplashPresenter splashPresenter; + @Inject + AppUtils mAppUtils; @Override protected void onCreate(Bundle savedInstanceState) { + getInjectionComponent().inject(this); super.onCreate(savedInstanceState); renderView(); - splashPresenter=new SplashPresenter(); + splashPresenter = new SplashPresenter(); splashPresenter.attach(this); splashPresenter.delayedAction(); } - - /** * Sets activity content */ @@ -48,10 +51,10 @@ public void init() { */ @Override public void checkNetwork() { - if(!new AppUtils().isNetworkConnected()){ - showMessage(getString(R.string.network_error),R.string.retry,R.string.exit); + if (!mAppUtils.isNetworkConnected()) { + showMessage(getString(R.string.network_error), R.string.retry, R.string.exit); return; - }else{ + } else { navigateToLanding(); } } @@ -61,7 +64,7 @@ public void checkNetwork() { */ @Override public void navigateToLanding() { - Intent intent= new Intent(this,ResultListActivity.class); + Intent intent = new Intent(this, ResultListActivity.class); startActivity(intent); finish(); } diff --git a/app/src/main/java/com/dev/movieapp/ui/fragments/BaseFrag.java b/app/src/main/java/com/dev/movieapp/ui/fragments/BaseFrag.java index ac15628..c58e34a 100644 --- a/app/src/main/java/com/dev/movieapp/ui/fragments/BaseFrag.java +++ b/app/src/main/java/com/dev/movieapp/ui/fragments/BaseFrag.java @@ -13,6 +13,8 @@ import com.bumptech.glide.RequestBuilder; import com.bumptech.glide.request.RequestOptions; import com.dev.movieapp.R; +import com.dev.movieapp.app.MovieApp; +import com.dev.movieapp.dipinject.components.InjectionSubComponent; import com.dev.movieapp.ui.uiinterfaces.AlertCallBack; /** @@ -24,33 +26,45 @@ public abstract class BaseFrag extends Fragment implements AlertCallBack { + private boolean mIsInjectionComponentUsed = false; protected AlertDialog mCallBackAlertDialog; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + } + + protected InjectionSubComponent getInjectionComponent() { + if (mIsInjectionComponentUsed) { + throw new IllegalStateException("should not use Injection more than once."); + } + mIsInjectionComponentUsed = true; + return ((MovieApp) getActivity().getApplication()) + .getApplicationComponent() + .newInjectionComponent(); } - protected void loadImage(String imagePath, ImageView imageView){ + protected void loadImage(String imagePath, ImageView imageView) { RequestOptions requestOptions = new RequestOptions() .centerCrop() .placeholder(R.mipmap.imdb_icon) .error(R.mipmap.image_error) - .priority(Priority.NORMAL) - ; + .priority(Priority.NORMAL); RequestBuilder requestBuilder = Glide.with(this) .load(imagePath); requestBuilder.apply(requestOptions) .into(imageView); } + /** * Show alert message with call back - * @param message message to show in alert + * + * @param message message to show in alert * @param positiveBtnText positive button text * @param negativeBtnText negative button text */ - void showMessage(String message,int positiveBtnText,int negativeBtnText){ + void showMessage(String message, int positiveBtnText, int negativeBtnText) { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); dialogBuilder.setMessage(message); diff --git a/app/src/main/java/com/dev/movieapp/ui/fragments/detailfrag/ResultDetailFragment.java b/app/src/main/java/com/dev/movieapp/ui/fragments/detailfrag/ResultDetailFragment.java index 01f4196..b953036 100644 --- a/app/src/main/java/com/dev/movieapp/ui/fragments/detailfrag/ResultDetailFragment.java +++ b/app/src/main/java/com/dev/movieapp/ui/fragments/detailfrag/ResultDetailFragment.java @@ -1,11 +1,8 @@ package com.dev.movieapp.ui.fragments.detailfrag; -import android.app.Activity; +import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.CollapsingToolbarLayout; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -18,13 +15,10 @@ import com.dev.movieapp.ui.fragments.BaseFrag; import com.dev.movieapp.utils.AppUtils; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; +import javax.inject.Inject; import butterknife.BindView; import butterknife.ButterKnife; -import butterknife.Optional; import butterknife.Unbinder; /** @@ -49,8 +43,12 @@ public class ResultDetailFragment extends BaseFrag implements ResultDetailView { @BindView(R.id.result_detail) TextView mDescription; @BindView(R.id.toolbar_layout) - @Nullable CollapsingToolbarLayout mAppBarLayout; + @Nullable + CollapsingToolbarLayout mAppBarLayout; ResultDetailPresenter mResultDetailPresenter; + @Inject + AppUtils mAppUtils; + /** * Mandatory empty constructor for the fragment manager to instantiate the * fragment (e.g. upon screen orientation changes). @@ -60,11 +58,12 @@ public ResultDetailFragment() { @Override public void onCreate(Bundle savedInstanceState) { + getInjectionComponent().inject(this); super.onCreate(savedInstanceState); Bundle bundle = this.getArguments(); mResult = bundle.getParcelable(AppUtils.RESULT_KEY); //Initiates Presenter object - mResultDetailPresenter=new ResultDetailPresenter(mResult); + mResultDetailPresenter = new ResultDetailPresenter(mResult); mResultDetailPresenter.attach(this); } @@ -72,23 +71,23 @@ public void onCreate(Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.result_detail, container, false); - mUnbinder= ButterKnife.bind(this, rootView); + mUnbinder = ButterKnife.bind(this, rootView); mResultDetailPresenter.refreshUI(); return rootView; } /** * Repopulates UI + * * @param result */ @Override public void populateUI(Result result) { mTitle.setText(result.getTitle()); - mVotes.setText(result.getVoteAverage() + " "+getString(R.string.percentage)); - mTotalVotes.setText(result.getVoteCount() + " "+getString(R.string.votes)); + mVotes.setText(result.getVoteAverage() + " " + getString(R.string.percentage)); + mTotalVotes.setText(result.getVoteCount() + " " + getString(R.string.votes)); mDescription.setText(result.getOverview()); - AppUtils appUtils = new AppUtils(); - mReleaseDate.setText(getString(R.string.release)+" : " + appUtils.getFormattedDate(result.getReleaseDate())); + mReleaseDate.setText(getString(R.string.release) + " : " + mAppUtils.getFormattedDate(result.getReleaseDate())); } @Override diff --git a/app/src/main/java/com/dev/movieapp/ui/fragments/detailtabfrag/ResultDetailTabFragment.java b/app/src/main/java/com/dev/movieapp/ui/fragments/detailtabfrag/ResultDetailTabFragment.java index 9e8ff06..2330030 100644 --- a/app/src/main/java/com/dev/movieapp/ui/fragments/detailtabfrag/ResultDetailTabFragment.java +++ b/app/src/main/java/com/dev/movieapp/ui/fragments/detailtabfrag/ResultDetailTabFragment.java @@ -4,6 +4,7 @@ import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; +import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -18,12 +19,15 @@ import com.dev.movieapp.models.Result; import com.dev.movieapp.ui.fragments.BaseFrag; import com.dev.movieapp.ui.fragments.detailfrag.ResultDetailFragment; +import com.dev.movieapp.utils.AppLogger; import com.dev.movieapp.utils.AppUtils; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import javax.inject.Inject; + import butterknife.BindView; import butterknife.ButterKnife; import butterknife.Unbinder; @@ -34,6 +38,7 @@ */ public class ResultDetailTabFragment extends BaseFrag implements ResultDetailTabView{ + private static final String TAG = ResultDetailTabFragment.class.getSimpleName(); private Result mResult; @BindView(R.id.title) TextView mTitle; @@ -50,6 +55,12 @@ public class ResultDetailTabFragment extends BaseFrag implements ResultDetailTab Unbinder mUnbinder; ResultDetailTabPresenter mResultDetailTabPresenter; + @Inject + AppUtils mAppUtils; + + @Inject + AppLogger mAppLogger; + /** * Mandatory empty constructor for the fragment manager to instantiate the * fragment (e.g. upon screen orientation changes). @@ -60,6 +71,7 @@ public ResultDetailTabFragment() { @Override public void onCreate(@Nullable Bundle savedInstanceState) { + getInjectionComponent().inject(this); super.onCreate(savedInstanceState); Bundle bundle = this.getArguments(); mResult = bundle.getParcelable(AppUtils.RESULT_KEY); @@ -88,13 +100,14 @@ public void populateUI(Result result) { mVotes.setText(result.getVoteAverage() + " "+getString(R.string.percentage)); mTotalVotes.setText(result.getVoteCount() + " "+getString(R.string.votes)); mDescription.setText(result.getOverview()); - AppUtils appUtils=new AppUtils(); - mReleaseDate.setText(getString(R.string.release)+" : " + appUtils.getFormattedDate(result.getReleaseDate())); + mReleaseDate.setText(getString(R.string.release)+" : " + mAppUtils.getFormattedDate(result.getReleaseDate())); //Created URL for image population with Glide StringBuilder images = new StringBuilder(); images.append(BuildConfig.IMG_BASE_URL+AppUtils.IMG_URL_EXTRA); images.append(result.getBackdropPath()); + + mAppLogger.d(TAG, "IMG:= "+images.toString()); loadImage(images.toString(),mImgMovie); } diff --git a/app/src/main/java/com/dev/movieapp/utils/AppLogger.java b/app/src/main/java/com/dev/movieapp/utils/AppLogger.java new file mode 100644 index 0000000..889c4d9 --- /dev/null +++ b/app/src/main/java/com/dev/movieapp/utils/AppLogger.java @@ -0,0 +1,22 @@ +package com.dev.movieapp.utils; + +import android.util.Log; + +public class AppLogger { + + public void e(String tag, String message) { + Log.e(tag, message); + } + + public void w(String tag, String message) { + Log.w(tag, message); + } + + public void v(String tag, String message) { + Log.v(tag, message); + } + + public void d(String tag, String message) { + Log.d(tag, message); + } +} diff --git a/app/src/main/java/com/dev/movieapp/utils/AppUtils.java b/app/src/main/java/com/dev/movieapp/utils/AppUtils.java index bcddcf5..915754f 100644 --- a/app/src/main/java/com/dev/movieapp/utils/AppUtils.java +++ b/app/src/main/java/com/dev/movieapp/utils/AppUtils.java @@ -5,16 +5,12 @@ import android.net.NetworkInfo; import android.util.Log; -import com.dev.movieapp.BuildConfig; -import com.dev.movieapp.app.MovieApp; import com.dev.movieapp.ui.fragments.detailfrag.ResultDetailFragment; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; -import javax.inject.Inject; - import static android.content.Context.CONNECTIVITY_SERVICE; /** @@ -23,39 +19,40 @@ public class AppUtils { - @Inject public Context mContext; public static final String IMG_URL_EXTRA = "t/p/w500/"; public static final int TIME_OUT = 120; public static final String RESULT_KEY = "RESULT_KEY"; public static final String API_ERROR_PROCESS = "Error in processing request"; - public AppUtils(){ - MovieApp.getInstance().getContextComponent().inject(this); + public AppUtils(Context context) { + mContext = context; } /** * Network connectivity validation + * * @return */ - public boolean isNetworkConnected(){ - boolean status=false; + public boolean isNetworkConnected() { + boolean status = false; ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = manager.getActiveNetworkInfo(); - if(activeNetwork != null && activeNetwork.isConnectedOrConnecting()){ - status=true; + if (activeNetwork != null && activeNetwork.isConnectedOrConnecting()) { + status = true; } return status; } /** * Returns formatted date + * * @param inputDate * @return */ - public String getFormattedDate(String inputDate){ + public String getFormattedDate(String inputDate) { //2018-06-06 - String date=""; + String date = ""; try { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date newDate = format.parse(inputDate); @@ -63,7 +60,7 @@ public String getFormattedDate(String inputDate){ format = new SimpleDateFormat("dd MMM yyyy"); date = format.format(newDate); } catch (ParseException e) { - Log.e(ResultDetailFragment.class.getSimpleName(),"Date ParseException = "+e.toString()); + Log.e(ResultDetailFragment.class.getSimpleName(), "Date ParseException = " + e.toString()); } return date; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1d80c6a..60a5156 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,4 +11,5 @@ Cancel Could not find movie data Error in getting response + OK