diff --git a/android-advance-image-gallery-example/index.html b/android-advance-image-gallery-example/index.html new file mode 100644 index 0000000..e104cb9 --- /dev/null +++ b/android-advance-image-gallery-example/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-annotation-processing-tutorial-part-1-a-practical-approach/index.html b/android-annotation-processing-tutorial-part-1-a-practical-approach/index.html index 17fdc0c..972d10c 100644 --- a/android-annotation-processing-tutorial-part-1-a-practical-approach/index.html +++ b/android-annotation-processing-tutorial-part-1-a-practical-approach/index.html @@ -1,715 +1 @@ - - - - - Android Annotation Processing Tutorial: Part 1: A practical approach - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- - Janishar Ali - - - 29 May 2018 - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- Android Annotation Processing Tutorial: Part 1: A Practical Approach -

-
- Android Annotation Processing Tutorial: Part 1: A practical approach -
- - cover-android-annotation-processing-tutorial-part-1 - -
-
-

- Many famous libraries that you must have come across in Android development such as - - ButterKnife - - , - - Dagger2 - - , - - Room - - , - - GreenDao - - , - - PlaceHolderView - - etc, use annotation processing. -

-

- The motivation for writing this tutorial: -

-

- There are a couple of good annotation processing tutorials and examples available on the internet but it was really difficult for me to search any reference that provided a complete solution, apart from the setup process. So, I decided to write this tutorial that aims to cover the following: -

-
    -
  1. - Basics of annotation processing. -
  2. -
  3. - Create a complete Android library similar to - - ButterKnife. - -
  4. -
  5. - Provide an introduction to - - JavaPoet - - . -
  6. -
  7. - Explains the essentials for the created library. -
  8. -
-

- Introduction -

-

- Annotation processing has become one of the most important language features in the modern Java programming. Java supports annotation processing from the release of Java 5 but its full potential has been realized in the recent years. Annotation processing in simple words is used to generate files during compilation. -

-

- - Limitation: - - - Annotation processing can only be used to generate new files and not to modify old ones. - -

-

- - - Note - - : Annotation processing is not only used for writing .java files but all kinds of files. Example - metadata text files. - -

-
- The real beauty is not in the fancy outer looks but in the simple within. -
-

- Let’s explore if it’s a fancy way to write code or it really does solve some problems that we encounter in software development. -

-

- - Case Study : - -

-

- - - Remove the codes that use Java Reflection APIs and make it safe from runtime exceptions - - -

-

- Reflection is a process in which we read a class and it’s member properties during runtime and try to modify these properties. This process though helps ous in creating a generic or implementation independent program but is also prone to lots of exceptions as we do not know the exact condition at the runtime. Class scanning and modification by reflection is a slow process and also an ugly way to isolate the code. -

-

- - Example: - - Suppose we want to map a view object from XML to a Java class. Then by using reflection, we can do something similar to this. -

-
    -
  • - Define an annotation - - BindView - - for mapping. -
  • -
-
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface BindView {
-    int value();
-} 
-
    -
  • - Place - - BindView - - annotation on a - - View - - class variable with the view's id. -
  • -
-
public class MainActivity extends AppCompatActivity {
-    ...
-    @BindView(R.id.txtView)
-    TextView txtView;
-    ...
-}
-
    -
  • - Create a class that does the assignment of the - - TextView - - object defined in the XML with the id - - tv_name - - to the variable - - tvName - - . -
  • -
-
public class ViewBinder {
-    /*
-     * annotations for activity class
-     * @param target is the activity with annotations
-     */
-    public static void bind(final Activity target){
-        bindViews(target, target.getClass().getDeclaredFields(),
-    }
-
-    /*
-     * initiate the view for the annotated public fields
-     * @param obj is any class instance with annotations
-     * @param fields list of methods in the class with annotation
-     * @param rootView is the inflated view from the XML
-     */
-    private static void bindViews(final Object obj, Field[] fields, View rootView){
-        for(final Field field : fields) {
-            Annotation annotation = field.getAnnotation(BindView.class);
-            if (annotation != null) {
-                BindView bindView = (BindView) annotation;
-                int id = bindView.value();
-                View view = rootView.findViewById(id);
-                try {
-                    field.setAccessible(true);
-                    field.set(obj, view);
-                } catch (IllegalAccessException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-}
-
    -
  • - Send the - - Activity - - instance to the - - ViewBinder - - . -
  • -
-
public class MainActivity extends AppCompatActivity {
-
-    @BindView(R.id.txtView)
-    private TextView txtView;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_main);
-        ViewBinder.bind(this);
-        txtView.setText("Testing");
-    }
-    ...
-}
-

- - This works fine but the limitation that we just talked about reflection make it undesirable. - -

-

- So, how can we improve upon it? -

-

- This is an interesting question and the answer to this is the motivation for exploring the powerful APIs of annotation processing. -

-
    -
  1. - We have to eliminate the runtime scan of the MainActivity class and replace it with method calls. -
  2. -
  3. - We would not want to write those methods for every Activity and want them to get generated automatically. -
  4. -
  5. - We would want to eliminate any runtime exceptions and like to move such checks during compile time itself. -
  6. -
-

- - These three conditions can be satisfied with the use of annotation processing. - -

-

- - So, are you excited to explore how to do this? - -

-

- - It is simpler than you might have heard. So, let's break the taboo and understand it. - -

-
- The biggest hurdle in reaching the other side of the tunnel is not the task that is difficult but the lack of efforts. We are limited by the fear developed through the mouth of others. -
-

- How does the annotation processing work? -

-

- The annotation processing takes place in many compilation cycles. In each cycle, the compiler while reading a java source file finds the annotations registered for processing and calls the corresponding annotation processor. This cycle continues with the generation of any file or terminates if no file is generated in that cycle. -

-

- We will divide our learning process into 4 parts: -

-
    -
  1. - Create an Android project for annotation processing. -
  2. -
  3. - Understand the definition of annotations used for processing. -
  4. -
  5. - Write a compiler module that does the code generation through annotation processing. -
  6. -
  7. - Use the code generated through annotation processing. -
  8. -
-

- - After this tutorial, you will be able to write you own android library based on annotation processing. - -

-
- - Hard work and smart work are must for an exceptional life. It is in our hands to make it great or be in the crowd. - -
-

- - We will continue this tutorial in PART 2 - -

-

- - Link to other parts of the tutorial: - -

-
    -
  1. - - - Part 2: The project structure - - -
  2. -
  3. - - - Part 3: Generate Java source code - - -
  4. -
  5. - - - Part 4:Use the generated code - - -
  6. -
-

- - The source code for this tutorial can be found here: - - - - https://github.com/MindorksOpenSource/annotation-processing-example - - -

-

- - Thanks for reading this article. Be sure to share this article if you found it helpful. It would let others get this article and spread the knowledge. - -

-

- Let’s become friends on - - - Twitter - - , - - - - Linkedin - - , - - - - Github - - , - - and - - - Facebook - - . - -

-
- - Learning is a journey, let’s learn together! - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Share this blog and spread the knowledge -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- -
-
- - - \ No newline at end of file + \ No newline at end of file diff --git a/android-annotation-processing-tutorial-part-2-the-project-structure/index.html b/android-annotation-processing-tutorial-part-2-the-project-structure/index.html new file mode 100644 index 0000000..cbd987e --- /dev/null +++ b/android-annotation-processing-tutorial-part-2-the-project-structure/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-annotation-processing-tutorial-part-3-generate-java-source-code/index.html b/android-annotation-processing-tutorial-part-3-generate-java-source-code/index.html new file mode 100644 index 0000000..78af821 --- /dev/null +++ b/android-annotation-processing-tutorial-part-3-generate-java-source-code/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-annotation-processing-tutorial-part-4-use-the-generated-code/index.html b/android-annotation-processing-tutorial-part-4-use-the-generated-code/index.html new file mode 100644 index 0000000..be5e30b --- /dev/null +++ b/android-annotation-processing-tutorial-part-4-use-the-generated-code/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-beginner-image-gallery-example/index.html b/android-beginner-image-gallery-example/index.html new file mode 100644 index 0000000..17fb73b --- /dev/null +++ b/android-beginner-image-gallery-example/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-core-looper-handler-and-handlerthread-bd54d69fe91a/index.html b/android-core-looper-handler-and-handlerthread-bd54d69fe91a/index.html new file mode 100644 index 0000000..455d470 --- /dev/null +++ b/android-core-looper-handler-and-handlerthread-bd54d69fe91a/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-dagger2-critical-things-to-know-before-you-implement-275663aecc3e/index.html b/android-dagger2-critical-things-to-know-before-you-implement-275663aecc3e/index.html new file mode 100644 index 0000000..0663312 --- /dev/null +++ b/android-dagger2-critical-things-to-know-before-you-implement-275663aecc3e/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-expandable-news-feed-example-4b4544e1fe7e/index.html b/android-expandable-news-feed-example-4b4544e1fe7e/index.html new file mode 100644 index 0000000..b7743a6 --- /dev/null +++ b/android-expandable-news-feed-example-4b4544e1fe7e/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-infinite-list-with-load-more-example/index.html b/android-infinite-list-with-load-more-example/index.html new file mode 100644 index 0000000..eff631d --- /dev/null +++ b/android-infinite-list-with-load-more-example/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-mvp-architecture-extension-with-interactors-and-repositories-bd4b51972339/index.html b/android-mvp-architecture-extension-with-interactors-and-repositories-bd4b51972339/index.html index 87ef04d..fbe5fe6 100644 --- a/android-mvp-architecture-extension-with-interactors-and-repositories-bd4b51972339/index.html +++ b/android-mvp-architecture-extension-with-interactors-and-repositories-bd4b51972339/index.html @@ -1,775 +1 @@ - - - - - Android MVP Architecture Extension with Interactors and Repositories - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- - Janishar Ali - - - 24 Jul 2017 - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- Android MVP Architecture Extension with Interactors and Repositories -

-
- Android MVP Architecture Extension with Interactors and Repositories -
-

- Evolution is the truth of nature and new developments are guided by the natural selection. This results in a lot of different species with many similarities and all adapt best in their habitat. The notion that one is better than the other is only valid in bounded conditions where one is more suited for survival. When the conditions change so is the notion. This is also true for any software design. One solution is better than the other in its own scope. -

-

- Sometime back I wrote a series of articles on the design of MVP architecture for Android. The - - project - - was very well received in the community and hundreds of companies and developers added the architecture in their applications. We at - - Mindorks - - have also implemented the same architecture for our Android app. With the exposure of this architecture to many use cases, some enhancements were identified to suit those particular conditions. -

-

- So, as I mentioned some enhancements were identified to adapt better to some situations. All these situations emerged for Android apps having a huge codebase with many developers working on the project simultaneously. -

-

- - The limitations that were identified in those conditions were two: - -

-
    -
  1. - - Centralization of DataManager - - : The DataManager in the MVP architecture is designed to delegate all responsibilities to ApiHelper, DbHelper, and PreferenceHelper. It is a good design for most of the use cases because it empowers to intercept the Helper calls and perform some pre-processing. However, for large projects, this class tends to become very large. -
  2. -
  3. - - Centralization of DbHelper - - : The DbHelper was designed to fetch data from the database using the DAO classes. This is also good for most of the projects with fewer DB queries but for large projects tend to become very large. -
  4. -
-
- - Potentially - - - - Centralization of DataManager - - - - problem could be solved by exposing the Helper instances to the Presenters. This will remove the DataManager delegation calls and hence will reduce the code base to few methods that require cross Helpers calls or series of calls made to a Helper. I would recommend this solution to the current MVP architecture. - -
-
- - Tapping an unbound potential requires taking two steps ahead after we have reached our destination. - -
-

- Now I propose some fundamental changes to the - - existing MVP architecture - - to make it suitable for very large projects with many developers working on it simultaneously. First, let’s identify the challenges to such a projects. -

-
    -
  1. - Large projects have many features and to manage those features, it needs to have a modularize code base. Even in a module, the best approach is to segregate the codes such that all the features are encapsulated, meaning that all the dependencies for that feature can be at most resolved in its package. -
  2. -
  3. - For many developers to work on the same project and to avoid the code merge with each pull request, we need to do the features encapsulation. -
  4. -
-

- Let’s see how can we extend the - - current MVP project - - to incorporate the features encapsulation. -

-

- - - Current Project - - - - has this structure: - -

-
    -
  1. - DataManager has ApiHelper, DbHelper and PreferenceHelper. -
  2. -
  3. - Presenter gets DataManager singleton instance and the DataManager delegates all the Helper calls. -
  4. -
  5. - View is attached with its Presenter. -
  6. -
-

- Before you proceed further I would recommend you to go through the original MVP architecture articles: -

-
    -
  1. - - - Link to MVP Part 1 - - -
  2. -
  3. - - - Link to MVP Part 2 - - -
  4. -
  5. - - - Link to MVP Part 3 - - -
  6. -
-

- - Proposed change for the feature encapsulation is the decentralization of DataManager and DbHelper. - -

-

- DataManager decentralization results in a structure we call it as an - - Interactor - - and DbHelper decentralization results in Repositories. -

-
    -
  1. - - Interactor - - : Each Presenter gets its own instance of an Interactor in place of a singleton DataManager. The interactor is responsible for the same responsibilities as the DataManager but it is only concerned with those data access and processing calls that are required by the feature that it is serving. -
  2. -
  3. - - Repository - - : The DbHelper is broken into Repositories. For example, all the database queries for a User table is made through an UserRepository and not in the DbHelper. UserRepository, similar to DbHelper, makes all its concerned queries through UserDao. An important difference is that the Repository is an on demand instantiation and each Interactor gets a new Repository instance in oppose to a singleton DbHelper. -
  4. -
-

- - Here is the link to this GitHub project: - -

-

- - Let’s see that architecture blueprint with these new components: - -

-
- Android MVP Architecture Extension with Interactors and Repositories -
-

- Comparing it with the original MVP architecture blueprint: - - - Image Link - - -

-

- We can see that the DataManager and DbHelper are replaced by the Interactors and Repositories which are separately available for each Presenter. -

-

- Important changes in the MVP architecture: -

-
    -
  • - - MvpInteractor - - : It is an interface that lists the data access APIs common to all application components and access method for the singleton ApiHelper and PreferencesHelper. -
  • -
-
public interface MvpInteractor {
-
-    ApiHelper getApiHelper();
-
-    PreferencesHelper getPreferencesHelper();
-
-    void setUserAsLoggedOut();
-
-    void setAccessToken(String accessToken);
-    ...
-}
-
    -
  • - - BaseInteractor - - : It implements the MvpInteractor. All the subsequent Interactors extend this BaseInteractor. BaseInteractor gets the singleton ApiHelper, and PreferenceHelper. -
  • -
-
public class BaseInteractor implements MvpInteractor {
-
-    private final PreferencesHelper mPreferencesHelper;
-    private final ApiHelper mApiHelper;
-
-    @Inject
-    public BaseInteractor(PreferencesHelper preferencesHelper, ApiHelper apiHelper) {
-        mPreferencesHelper = preferencesHelper;
-        mApiHelper = apiHelper;
-    }
-
-    @Override
-    public ApiHelper getApiHelper() {
-        return mApiHelper;
-    }
-
-    @Override
-    public PreferencesHelper getPreferencesHelper() {
-        return mPreferencesHelper;
-    }
-
-    @Override
-    public void setAccessToken(String accessToken) {
-        getPreferencesHelper().setAccessToken(accessToken);
-        getApiHelper().getApiHeader()
-                .getProtectedApiHeader()
-                .setAccessToken(accessToken);
-    }
-
    ...   
-}
-
    -
  • - Component wise Interactors extends the BaseInteractor and implement the interface that extends the MvpInteractor that adds its own APIs in them. Example: LoginMvpInteractor extends MvpInteractor and add doServerLoginApiCall, doGoogleLoginApiCall, and doFacebookLoginApiCall. Similarly LoginInteractor extends BaseInteractor and implements LoginMvpInteractor. -
  • -
-

- Example: LoginMvpInteractor -

-
public interface LoginMvpInteractor extends MvpInteractor {
-
-    Observable<LoginResponse> doServerLoginApiCall(
-            LoginRequest.ServerLoginRequest request);
-
-    Observable<LoginResponse> doGoogleLoginApiCall(
-            LoginRequest.GoogleLoginRequest request);
-
-    Observable<LoginResponse> doFacebookLoginApiCall(
-            LoginRequest.FacebookLoginRequest request);
-}
-

- Its implementation by LoginInteractor. Notice that a new instance of the UserRepository is provided to this Interactor. -

-
public class LoginInteractor extends BaseInteractor
-implements LoginMvpInteractor {
-
-    private UserRepository mUserRepository;
-
-    @Inject
-    public LoginInteractor(PreferencesHelper preferencesHelper, ApiHelper apiHelper, UserRepository userRepository) {
-        super(preferencesHelper, apiHelper);
-        mUserRepository = userRepository;
-    }
-
-    @Override
-    public Observable<LoginResponse> doServerLoginApiCall(
-            LoginRequest.ServerLoginRequest request) {
-        return getApiHelper().doServerLoginApiCall(request);
-   }
-
   ...
-}
-
    -
  • - The Presenter has the same structure as the - - original MVP architecture - - , with only difference is the DataManager is replaced by the component’s interactor. Example: LoginMvpPresenter interface. Notice the addition of Interactor along with View in the definition. -
  • -
-
@PerActivity
-public interface LoginMvpPresenter<V extends LoginMvpView,
-        I extends LoginMvpInteractor> extends MvpPresenter<V, I> {
-
-    void onServerLoginClick(String email, String password);
-
-    void onGoogleLoginClick();
-
-    void onFacebookLoginClick();
-}
-

- Its implementation by the LoginPresenter: -

-
public class LoginPresenter<V extends LoginMvpView, I extends LoginMvpInteractor>
-extends BasePresenter<V, I> implements LoginMvpPresenter<V, I> {
-
-    private static final String TAG = "LoginPresenter";
-
-    @Inject
-    public LoginPresenter(I mvpInteractor,
-                          SchedulerProvider schedulerProvider,
-                          CompositeDisposable compositeDisposable) {
-        super(mvpInteractor, schedulerProvider, compositeDisposable);
-    }
-
    ...
-}
-
    -
  • - Repository is created for each Db Table wrapper Object. DAO in this project is generated by the - - - greenDAO library - - - . -
  • -
-

- Example UserRepository: -

-
public class UserRepository {
-
-private final DaoSession mDaoSession;
-
-    @Inject
-    public UserRepository(DaoSession daoSession) {
-        mDaoSession = daoSession;
-    }
-
-    public Observable<Long> insertUser(final User user) {
-        return Observable.fromCallable(new Callable<Long>() {
-            @Override
-            public Long call() throws Exception {
-                return mDaoSession.getUserDao().insert(user);
-            }
-        });
-    }
-
-    ...
-}
-

- - The new project structure: - -

-
- Android MVP Architecture Extension with Interactors and Repositories -
-

- Compare this with the original MVP project structure: - - - Image Link - - -

-

- You can observe that the login feature components are independent of other application components and has all the dependencies encapsulated. Any developer working on the login feature can work independently to other developers working on separate features. -

-
- - You don’t need an atom bomb to kill an ant. - -
-

- These components make the architecture more extensible and flexible but at the cost of more work. I must repeat again - - original MVP architecture - - is suited for most projects of decent complexity and this extended version is suited to very large projects with hundreds of features and many developers working on it simultaneously. We are using the original architecture very happily in our own code base of our app. -

-

- - Note: - -

-

- ApiHelper and PreferenceHelper are not broken into parts because the Android app dependency on them is very limited. -

-

- - The - - - - link - - - - to the sample app project of MVP extended with Interactor and Repository. - -

-

- Also, Let’s become friends on - - - Twitter - - , - - - - Linkedin - - , - - - - Github - - , - - and - - - Facebook - - . - -

-
- - Learning is a journey, let’s learn together! - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Share this blog and spread the knowledge -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- -
-
- - - \ No newline at end of file + \ No newline at end of file diff --git a/android-networking-bare-skin-understanding-jpost/index.html b/android-networking-bare-skin-understanding-jpost/index.html new file mode 100644 index 0000000..cf48dd2 --- /dev/null +++ b/android-networking-bare-skin-understanding-jpost/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-task-and-back-stack-review-5017f2c18196/index.html b/android-task-and-back-stack-review-5017f2c18196/index.html new file mode 100644 index 0000000..bc512df --- /dev/null +++ b/android-task-and-back-stack-review-5017f2c18196/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-tinder-swipe-view-example-3eca9b0d4794/index.html b/android-tinder-swipe-view-example-3eca9b0d4794/index.html new file mode 100644 index 0000000..fc5d0dc --- /dev/null +++ b/android-tinder-swipe-view-example-3eca9b0d4794/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android-view-evolution-placeholderview/index.html b/android-view-evolution-placeholderview/index.html new file mode 100644 index 0000000..6fbfbc6 --- /dev/null +++ b/android-view-evolution-placeholderview/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/essential-guide-for-designing-your-android-app-architecture-mvp-part-1-74efaf1cda40/index.html b/essential-guide-for-designing-your-android-app-architecture-mvp-part-1-74efaf1cda40/index.html index f8c3213..d8d24c1 100644 --- a/essential-guide-for-designing-your-android-app-architecture-mvp-part-1-74efaf1cda40/index.html +++ b/essential-guide-for-designing-your-android-app-architecture-mvp-part-1-74efaf1cda40/index.html @@ -1,667 +1 @@ - - - - - Essential Guide For Designing Your Android App Architecture: MVP: Part 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- - Janishar Ali - - - 3 Feb 2017 - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- Essential Guide For Designing Your Android App Architecture: MVP: Part 1 -

-
- Essential Guide For Designing Your Android App Architecture: MVP: Part 1 -
-
- - If you make your foundations strong, then you can rise high and touch the sky. - -
-

- Android framework does not advocate any specific way to design your application. That in a way, make us more powerful and vulnerable at the same time. -

-

- - Why am I even thinking about this, when I am provided with Activity and I can, in essence, write my entire implementation using few Activities? - -

-

- Over the years writing code for Android, I have realized that solving a problem or implementing a feature at that point of time is not enough. Your app goes through a lot of change cycles and features addition/removal. Incorporating these over a period of time creates havoc in your application if not designed properly with separation of concern. That is why I have come up with a guide that I follow religiously for all my architectural designs from the very single code I write for that application. -

-
- - The principles presented in the MVP philosophy is by far the best I have come across. - -
-

- - What is an MVP and why should we explore it? - -

-

- Let’s take a ride into the past. Most of us started creating an Android app with Activity at the center and capable of deciding what to do and how to fetch data. Activity code over a period of time started to grow and became a collection of non-reusable components. We then started packaging those components and the Activity could use them through the exposed apis of these components. We started to take pride and began breaking codes into pieces as much as possible. Then we found ourselves in an ocean of components with hard to trace dependencies and usage. Also, we later got introduced to the concept of testability and found that regression is much safer if it’s written with tests. We felt that the jumbled code that we have developed in the above process is very tightly coupled with the Android apis, preventing us to do JVM tests and also hindering an easy design of test cases. This is the classic MVC with Activity or Fragment acting as a Controller. -

-

- So, we formulated few principles that solved most of the above-mentioned problems if implemented carefully. Those principles, we call as MVP (Model-View-Presenter) design pattern. -

-

- - What is an MVP design pattern? - -

-

- MVP design pattern is a set of guidelines that if followed, decouples the code for reusability and testability. It divides the application components based on its role, called separation of concern. - - MVP divides the application into three basic components: - -

-
    -
  1. - - Model - - : It is responsible for handling the data part of the application. -
  2. -
  3. - - View - - : It is responsible for laying out the views with specific data on the screen. -
  4. -
  5. - - Presenter - - : It is a bridge that connects a Model and a View. It also acts as an instructor to the View. -
  6. -
-

- - MVP lays few ground rules for the above mentioned components, as listed below: - -

-
    -
  1. - A View’s sole responsibility is to draw UI as instructed by the Presenter. It is a dumb part of the application. -
  2. -
  3. - View delegates all the user interactions to its Presenter. -
  4. -
  5. - The View never communicates with Model directly. -
  6. -
  7. - The Presenter is responsible for delegating View’s requirements to Model and instructing View with actions for specific events. -
  8. -
  9. - Model is responsible for fetching the data from server, database and file system. -
  10. -
-
- - The above-mentioned principles can be implemented in a number of ways. Each developer will have its own vision of it. But in the nutshell, basic nuts and bolts are common with minor modification. - -
-

-

-
- - With great power, comes great responsibility. - -
-

- - Now, I lay down the preamble, I follow for MVP. - -

-
    -
  1. - Activity, Fragment, and a CustomView act as the View part of the application. -
  2. -
  3. - Each View has a Presenter in a one-to-one relationship. -
  4. -
  5. - View communicates with its Presenter through an interface and vice versa. -
  6. -
  7. - The Model is broken into few parts: ApiHelper, PreferenceHelper, DatabaseHelper, and FileHelper. These are all helpers to a DataManager, which in essence binds all Model parts. -
  8. -
  9. - Presenter communicates with the DataManager through an interface. -
  10. -
  11. - DataManager only serves when asked. -
  12. -
  13. - Presenter does not have access to any of the Android’s apis. -
  14. -
-

- - Now, all these information can evidently be found on any blog or Android guide for MVP. Then what’s the point of this article? - -

-
- - The reason that this article is written is to solve a very important challenge with MVP. - - - - How to actually implement it as an entire application? - - -
-

- MVP appears to be very simple when explained with a simple Activity example but makes us feel lost when we try binding all the components of an application together. -

-
- - If you want to dive deep into a world of beautiful coding and be mesmerized then follow along with this article. It’s not a news article, so get involved with it, put on your shoes with your back straight and away from all distractions. - -
-

- - Let’s sketch the blueprint of the architecture first. - -

-
- Essential Guide For Designing Your Android App Architecture: MVP: Part 1 -
-

- Architecture is the first thing you should work on for any software. A carefully crafted architecture will minimize a lot of rework in future while providing the scalability ease. Most of the project today is developed in a team, hence the code readability and modularity should be taken as utmost important elements of the architecture. We also rely heavily on 3rd party libraries and we keep switching between alternatives because of use cases, bugs or support. So, our architecture should be designed with plug and play design. The interfaces for classes serves this purpose. -

-

- The blueprint of the Android architecture drawn above contains all these features and is based on the principles of MVP. -

-
- - The following contents might feel overwhelming at first but as you go through an active example in the Next part of this article, concepts will become obvious to you. - -
-

-

-
- - Knowledge comes to those who crave for it. - -
-

- Let’s understand each part of the sketched architecture. -

-
    -
  • - - View - - : It is the part of the application which renders the UI and receives interactions from the user. Activity, Fragment, and CustomView constitute this part. -
  • -
  • - - MvpView - - : It is an interface, that is implemented by the View. It contains methods that are exposed to its Presenter for the communication. -
  • -
  • - - Presenter - - : It is the decision-making counterpart of the View and is a pure java class, with no access to Android APIs. It receives the user interactions passed on from its View and then takes the decision based on the business logic, finally instructing the View to perform specific actions. It also communicates with the DataManager for any data it needs to perform business logic. -
  • -
  • - - MvpPresenter - - : It is an interface, that is implemented by the Presenter. It contains methods that are exposed to its View for the communication. -
  • -
  • - - AppDbHelper - - : Database management and all the data handling related to a database is done in this part of the application. -
  • -
  • - - DbHelper - - : It is an interface implemented by the AppDbHelper and contains methods exposed to the application components. This layer decouples any specific implementation of the DbHelper and hence makes AppDbHelper as plug and play unit. -
  • -
  • - - AppPreferenceHelper - - : It is like AppDbHelper but is given the job to read and write the data from android shared preferences. -
  • -
  • - - PreferenceHelper - - : Interface just like DbHelper but implemented by AppPreferenceHelper. -
  • -
  • - - AppApiHelper - - : It manages the network API calls and API data handling. -
  • -
  • - - ApiHelper - - : It is an interface just like DbHelper but implemented by AppApiHelper. -
  • -
  • - - DataManager - - : It is an interface that is implemented by the AppDataManager. It contains methods, exposed for all the data handling operations. Ideally, it delegates the services provided by all the Helper classes. For this DataManager interface extends DbHelper, PreferenceHelper and ApiHelper interfaces. -
  • -
  • - - AppDataManager - - : It is the one point of contact for any data related operation in the application. DbHelper, PreferenceHelper, and ApiHelper only work for DataManager. It delegates all the operations specific to any Helper. -
  • -
-

- - Now, we are familiar with all the components and their roles in the application. We will now formulate the communication pattern within various components. - -

-
    -
  • - Application class instantiates the AppDbHelper (into DbHelper variable), AppPreferenceHelper (into PreferenceHelper variable), AppApiHelper (into ApiHelper variable) and finally AppDataManager (into DataManager variable) by passing the DbHelper, PreferenceHelper and ApiHelper reference to it. -
  • -
  • - The View components instantiate its Presenter through the MvpPresenter reference. -
  • -
  • - Presenter receives it View component and refers to it through MvpView. The Presenter also receives the DataManager. -
  • -
  • - DataManager exists as a singleton instance. -
  • -
-

- - These are the basic guidelines for an application to implement MVP. - -

-
- - Just like a surgeon taught with all the surgery procedures, won’t be of any use until he actually performs and practices it. We won’t be able to comprehend the ideas and implementations until we actually do it. - -
-

- In the next part, we will explore an actual working app example and hopefully be able to understand and grasp the concepts well. -

-

- - Here is the link to the second part of this article: - -

-

- Let’s become friends on - - - Twitter - - , - - - - Linkedin - - , - - - - Github - - , - - and - - - Facebook - - . - -

-

- Coder’s Rock -

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Share this blog and spread the knowledge -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- -
-
- - - \ No newline at end of file + \ No newline at end of file diff --git a/essential-guide-for-designing-your-android-app-architecture-mvp-part-2-b2ac6f3f9637/index.html b/essential-guide-for-designing-your-android-app-architecture-mvp-part-2-b2ac6f3f9637/index.html index a29fae9..698465d 100644 --- a/essential-guide-for-designing-your-android-app-architecture-mvp-part-2-b2ac6f3f9637/index.html +++ b/essential-guide-for-designing-your-android-app-architecture-mvp-part-2-b2ac6f3f9637/index.html @@ -1,602 +1 @@ - - - - - Essential Guide For Designing Your Android App Architecture: MVP: Part 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- - Janishar Ali - - - 3 Feb 2017 - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- Essential Guide For Designing Your Android App Architecture: MVP: Part 2 -

-
- Essential Guide For Designing Your Android App Architecture: MVP: Part 2 -
-

- This is the second part of the article series. In the first part, we developed the concept of MVP and worked out a blueprint for the android application architecture. If you haven’t read the first part then most of the following article will not make much sense. So, go through the first part before proceeding forward. -

-

- - Here is the link to the first part - - : -

-

- We will implement the MVP architecture by developing a full-fledged android application based on the blueprint sketched in the first part of this article series. -

-

- - The GitHub repo of the MVP project - - : - - - Link - - -

-

- This project is developed to provide a proper way of structuring an android app. It contains all the code pieces required for most part of the android app. -

-

- The project will appear very complex at first but as you will spend time exploring, it will become most obvious to you. This project is built using Dagger2, Rxjava, FastAndroidNetworking and PlaceHolderView. -

-
- - Take this project as a case study. Study each and every code of it. If there is some bug or you can come up with a better logical implementation then create a pull request. We are writing tests gradually, so feel free to contribute in it and create pull request for them too. - -
-

- The screens of the developed app are provided below: -

-
- Essential Guide For Designing Your Android App Architecture: MVP: Part 2 -
-

- This app has a login screen and a main screen. Login screen implements google, facebook and server login. The google and facebook login is implemented through a dummy api. The login is based on access token retrieval and subsequent api calls are protected with this token. The main screen creates flashcards with questions relevant to MVP. This repo contains codes that demonstrate most of the possible application components in terms of skeleton for any app. -

-

- Let’s take a look at the project structure: -

-

- The entire app is packaged into five parts: -

-
    -
  1. - - data - - : It contains all the data accessing and manipulating components. -
  2. -
  3. - - di - - : Dependency providing classes using Dagger2. -
  4. -
  5. - - ui - - : View classes along with their corresponding Presenters. -
  6. -
  7. - - service - - : Services for the application. -
  8. -
  9. - - utils - - : Utility classes. -
  10. -
-

- Classes have been designed in such a way that it could be inherited and could maximize the code reuse. -

-

- - project structure diagram: - -

-
- Essential Guide For Designing Your Android App Architecture: MVP: Part 2 -
-
- - Simplest ideas are most complex in their conception. - -
-

- There are a lot of interesting parts. But if I try explaining all of them at once then it will become too much information at a time. So, I think best approach will be to explain the core philosophies and then the reader can make sense of the code through navigating the project repo. I advise you to take this project study spanned over at least a week. Study the main classes in reverse chronological order. -

-
    -
  1. - Study build.gradle and look for all the dependencies used. -
  2. -
  3. - Explore data package and the implementations of helper classes. -
  4. -
  5. - ui base package creates the base implementations of Activity, Fragment, SubView and Presenter. All other related components should be derived from these classes. -
  6. -
  7. - di package is the dependency providing classes for the application. To understand dependency injection, go through the two-part article published by me, - - - Dagger2 part 1 - - - and - - - Dagger2 part 2 - - -
  8. -
  9. - Resources: Styles, fonts, drawable. -
  10. -
-

- Read the part 3 of this Article series here: It covers Dialogs, ViewPager, RecyclerView and Adapters in MVP. -

-

- - https://blog.mindorks.com/essential-guide-for-designing-your-android-app-architecture-mvp-part-3-dialog-viewpager-and-7bdfab86aabb - -

-

- If your project is very large with many developers working on it simultaneously then read the extension of this MVP architecture with Interactors and Repositories: -

-

- - https://blog.mindorks.com/android-mvp-architecture-extension-with-interactors-and-repositories-bd4b51972339 - -

-

- - Reference resources: - -

- -

- Let’s become friends on - - - Twitter - - , - - - - Linkedin - - , - - - - Github - - , - - and - - - Facebook - - . - -

-

- Coder’s Rock -

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Share this blog and spread the knowledge -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- -
-
- - - \ No newline at end of file + \ No newline at end of file diff --git a/essential-guide-for-designing-your-android-app-architecture-mvp-part-3-dialog-viewpager-and-7bdfab86aabb/index.html b/essential-guide-for-designing-your-android-app-architecture-mvp-part-3-dialog-viewpager-and-7bdfab86aabb/index.html index b61c1fb..c6bf670 100644 --- a/essential-guide-for-designing-your-android-app-architecture-mvp-part-3-dialog-viewpager-and-7bdfab86aabb/index.html +++ b/essential-guide-for-designing-your-android-app-architecture-mvp-part-3-dialog-viewpager-and-7bdfab86aabb/index.html @@ -1,662 +1 @@ - - - - - Essential Guide For Designing Your Android App Architecture: MVP: Part 3 (Dialog, ViewPager, and Adapters) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- - Janishar Ali - - - 26 May 2017 - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- Essential Guide For Designing Your Android App Architecture: MVP: Part 3 (Dialog, ViewPager, and Adapters) -

-
- Essential Guide For Designing Your Android App Architecture: MVP: Part 3 (Dialog, ViewPager, and Adapters) -
-

- I am extremely happy that the MVP architecture that we built in part 1 and part 2 together in this article series was very well received and the project repository itself got polished since its release, through your inputs and pull requests. -

-

- During the course of this development, many of you inquired about the implementation of Dialogs and Adapter based views in this architecture. So, I am writing this article to explain the place-holding for these. -

-

- In case you have not read the earlier resources then I would highly recommend reading those before going along this article. Here are the links for the resources: -

-

- - https://blog.mindorks.com/essential-guide-for-designing-your-android-app-architecture-mvp-part-1-74efaf1cda40 - -

-

- - https://blog.mindorks.com/essential-guide-for-designing-your-android-app-architecture-mvp-part-2-b2ac6f3f9637 - -

-

- - https://github.com/MindorksOpenSource/android-mvp-architecture - -

-

- In this article, we will extend the architecture with the addition of a rating dialog and feed Activity. -

-
- - Beauty lies in precision. - -
-

- Let’s list down all the features and use cases first: -

-

- - RateUs Dialog - -

-
    -
  1. - The rating dialog will display 5 starts for selection to the user as per his app experience. -
  2. -
  3. - If stars < 5 then we modify the dialog to reveal a feedback form asking the improvements. -
  4. -
  5. - If stars = 5 then we will modify the dialog to show play-store rating option to take the user there to add review. -
  6. -
  7. - The rating information will be send to the app’s backend server. -
  8. -
-

- Note: The rating dialog is non-required featured from the user’s end but is highly valuable from the developer’s end. So, the app has to be very subtle to enforce this. -

-
- - I recommend using large spaced intervals between two consecutive programmatically rating dialog display. - -
-
- Essential Guide For Designing Your Android App Architecture: MVP: Part 3 (Dialog, ViewPager, and Adapters) -
-

- - Feed Activity - -

-
    -
  1. - This activity will display two tabs. -
  2. -
  3. - Tab 1: Blog feed cards. -
  4. -
  5. - Tab 2: OpenSource feed cards. -
  6. -
-

- - Blog Feed Tab - -

-
    -
  1. - It will fetch the blog data from server API. -
  2. -
  3. - The blog data will be populated as cards in the RecyclerView. -
  4. -
-

- - OpenSource Feed Tab - -

-
    -
  1. - It will fetch the repositories data from server API. -
  2. -
  3. - The repositories data will be populated as cards in the RecyclerView. -
  4. -
-

- Now that we have defined our features list and use-cases, let’s sketch the architecture for their realization. -

-
- - I won’t be adding the entire class code snippet here because it obstruct the focus because of the length. So, what we will do instead is that, we will open the - - - - MVP project - - - - in the next tab and switch between them. - -
-

- Sketch: -

-

- We will add below-mentioned base classes -

-

- (see inside - - - com.mindorks.framework.mvp.ui.base - - - package in the - - project - - ) -

-
    -
  1. - - BaseDialog - - : This handles most of the boiler plate and adds common functionality for the actual dialogs that will be built upon them. -
  2. -
  3. - - DialogMvpView - - : This interface defines the APIs for the Presenter classes to interact with the Dialogs. -
  4. -
  5. - - BaseViewHolder - - : It defines the framework for RecyclerView binding and auto clearing the views when the ViewHolder is recycled. -
  6. -
-

-

-
- Essential Guide For Designing Your Android App Architecture: MVP: Part 3 (Dialog, ViewPager, and Adapters) -
-
public abstract class BaseDialog extends DialogFragment implements DialogMvpView
-
- - A note for the architecture: All the relevant features should be grouped together I call is - - - encapsulating the features, making them independent from each other. - -
-

- - - RateUs Dialog - - : - -

-
    -
  1. - The dialog access is made available through the Drawer. -
  2. -
  3. - The implementation is similar to any MVP view component that we saw in - - - part 2 - - - of the article. -
  4. -
-

- - Switch to the next tab on your browser and study it’s implementation in the - - - - project repo - - - - thoroughly. - -

-

- A note for the Dialog -

-
- - Sometimes there may be a case for many small dialogs, then we could create a common mvpview, mvppresenter and presenter to share between them. - -
-

- - - Feed: - - -

-
    -
  1. - This package contains the FeedActivity and its MVP components along this FeedPagerAdapter, blog package and opensource package. -
  2. -
  3. - - blog - - : This package contains BlogFragment and it’s MVP components and BlogAdapter for RecyclerView. -
  4. -
  5. - - opensource - - : This package contains OpenSourceFragment and it’s MVP components and OpenSourceAdapter for RecyclerView. -
  6. -
  7. - The FragmentStatePagerAdapter creates BlogFragment and OpenSourceFragment. -
  8. -
-
- - Never instantiate any class in any Adapter or else where using - - - - new - - operator instead provide them through modules as a dependency. - -
-

- OpenSourceAdapter and BlogAdapter is an implementation of - - RecyclerView.Adapter<BaseViewHolder> - - . In the case where no data is available then an empty view is shown that displays forced retry for the user and is removed when the data appears. -

-
- - The pagination for API data and network state handling is left as an exercise. - -
-

- - Go through the project now to study the code. Focus on the branching and also how view is defined in XML as well as programmatically. - -

-

- If you find any difficulties or need any explanation or improvement then join mindorks community and put questions there: - - - click here - - - to become a part of Android community at Mindorks and learn from each other. -

-

- Also, Let’s become friends on - - - Twitter - - , - - - - Linkedin - - , - - - - Github - - , - - and - - - Facebook - - . - -

-

- Coder’s Rock -

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Share this blog and spread the knowledge -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- -
-
- - - \ No newline at end of file + \ No newline at end of file diff --git a/getting-started-with-retrofit-using-kotlin-and-rxjava-android-networking-library/index.html b/getting-started-with-retrofit-using-kotlin-and-rxjava-android-networking-library/index.html new file mode 100644 index 0000000..2fb07cc --- /dev/null +++ b/getting-started-with-retrofit-using-kotlin-and-rxjava-android-networking-library/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/handle-ssl-https-certification-path-exception-for-java-applications-1b13c751f1e7/index.html b/handle-ssl-https-certification-path-exception-for-java-applications-1b13c751f1e7/index.html new file mode 100644 index 0000000..c9c64f5 --- /dev/null +++ b/handle-ssl-https-certification-path-exception-for-java-applications-1b13c751f1e7/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/introduction-to-dagger-2-using-dependency-injection-in-android-part-1-223289c2a01b/index.html b/introduction-to-dagger-2-using-dependency-injection-in-android-part-1-223289c2a01b/index.html index 39534e5..6e87875 100644 --- a/introduction-to-dagger-2-using-dependency-injection-in-android-part-1-223289c2a01b/index.html +++ b/introduction-to-dagger-2-using-dependency-injection-in-android-part-1-223289c2a01b/index.html @@ -1,637 +1 @@ - - - - - Introduction to Dagger 2, Using Dependency Injection in Android: Part 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- - Janishar Ali - - - 26 Dec 2016 - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- Introduction to Dagger 2, Using Dependency Injection in Android: Part 1 -

-
- Introduction to Dagger 2, Using Dependency Injection in Android: Part 1 -
-

- This article contains a lot of information. So for the purpose of readability I have broken it into two parts. -

-

- - Part 1: - - Deals with the introduction to the concept and overview of Dagger 2. -

-

- - Part 2: - - Contains Dagger implementation through an example. -

-

- To understand the Dagger usage in Android, let’s first try to understand the need for it. The important question is: -

-

- - Why do we need Dependency Injection? - -

-

- - Dependency Injection - - in build upon the concept of - - Inversion of Control - - . Which says that a class should get its dependencies from outside. In simple words, no class should instantiate another class but should get the instances from a configuration class. -

-

- If a java class creates an instance of another class via the - - - new - - - operator, then it cannot be used and tested independently from that class and is called a - - hard dependency - - . -

-

- - So, what are the benefits of providing the dependencies from outside the class? - -

-

- The most important advantage is that it increases the possibility of reusing the class and to be able to test them independent of other classes. -

-

- This sounds awesome to create a class that is not a specific implementation of a business logic. -

-

- Now that we understand a bit, we can go forward with dependency injection exploration. -

-

- - The big question now is that, how do we do DI (Dependency Injection)? - -

-

- To answer this question, we have to look back into the past. -

-

- A framework class called dependency container was used to analyzes the dependencies of a class. With this analysis, it was able to create an instance of the class and inject the objects into the defined dependencies via - - Java Reflections - - . This eliminated the hard dependencies. That way the class could be tested in isolation, ex. by using mock objects. This was - - Dagger 1 - - . -

-

- Main - - disadvantages - - of this process were two folds. First, the - - Reflection is slow - - in itself and second, it used to perform dependency - - resolution at runtime - - , leading to - - unexpected crashes - - . -

-

- - This lead to the birth of Dagger 2 forked from Square Dagger 1 by Google. - -

-

- The big changes that were brought in Dagger 2 were generating the dependency graph using annotation processor. The classes providing the dependencies were now generated at build time using javax inject package. This facilitated the possible error checking before the application runs. The generated code is highly readable as if written by hand. -

-

- - Note: Annotation Processor - - - is a way to read the compiled files during build time to generate source code files to be used in the project. - -

-

- If the above paragraph overwhelmed you then hang on till we start a real Android example. -

-

- For information purposes, I would like to mention some facts on DI. -

-

- The standard java annotations for describing the dependencies of a class are defined in the - - Java Specification Request 330 (JSR 330) - -

-

- Mode of Injection: -

-
    -
  1. - Constructor Injection: Injecting the method parameters. -
  2. -
  3. - Field Injection: Injecting the member variable (must not be private). -
  4. -
  5. - Method Injection: Injecting the method parameter. -
  6. -
-

- Order of dependency injection according to - - JSR330 - -

-
    -
  1. - Constructor -
  2. -
  3. - Field -
  4. -
  5. - Method -
  6. -
-

- - Notes: - -

-
    -
  1. - The order in which the methods or fields annotated with - - @Inject - - are called is not defined by - - JSR330 - - . You cannot assume that the methods or fields are called in the order of their declaration in the class. -
  2. -
  3. - As fields and method parameters are injected after the constructor is called, you cannot use injected member variables in the constructor. -
  4. -
-

- Now that we have sufficient background and justifications, we can proceed to understand Dagger. -

-

- I tend to visualize the dependency injection process with Dagger as follows: -

-

- - A dependency consumer asks for the dependency(Object) from a dependency provider through a connector. - -

-
    -
  1. - - Dependency provider: - - Classes annotated with - - @Module - - are responsible for providing objects which can be injected. Such classes define methods annotated with - - @Provides - - . The returned objects from these methods are available for dependency injection. -
  2. -
  3. - - Dependency consumer: - - The - - @Inject - - annotation is used to define a dependency. -
  4. -
  5. - - Connecting consumer and producer: - - A - - @Component - - annotated interface defines the connection between the provider of objects (modules) and the objects which express a dependency. The class for this connection is generated by the Dagger. -
  6. -
-

- - Limitations of Dagger : - -

-
    -
  1. - Dagger does not inject fields automatically. -
  2. -
  3. - It cannot inject private fields. -
  4. -
  5. - If you want to use field injection you have to define a method in your - - @Component - - annotated interface which takes the instance of the class into which you want to inject the member variable. -
  6. -
-

- - Now let’s move to the Part 2 of this article and experience Dagger in action. For Part 2 please follow this - - - - link - - . - -

-

- Let’s become friends on - - - Twitter - - , - - - - Linkedin - - , - - - - Github - - , - - and - - - Facebook - - . - -

-
- - Learning is a journey, let’s learn together! - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Share this blog and spread the knowledge -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- -
-
- - - \ No newline at end of file + \ No newline at end of file diff --git a/introduction-to-dagger-2-using-dependency-injection-in-android-part-2-b55857911bcd/index.html b/introduction-to-dagger-2-using-dependency-injection-in-android-part-2-b55857911bcd/index.html index 876da15..fe232bf 100644 --- a/introduction-to-dagger-2-using-dependency-injection-in-android-part-2-b55857911bcd/index.html +++ b/introduction-to-dagger-2-using-dependency-injection-in-android-part-2-b55857911bcd/index.html @@ -1,1695 +1 @@ - - - - - Introduction to Dagger 2, Using Dependency Injection in Android: Part 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- - Janishar Ali - - - 26 Dec 2016 - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- Introduction to Dagger 2, Using Dependency Injection in Android: Part 2 -

-
- Introduction to Dagger 2, Using Dependency Injection in Android: Part 2 -
-

- This is the - - part 2 - - of the article series. In - - - part 1 - - - we understood the need and advantages of dependency injection. We also got an overview of Dagger 2. In this part, we will focus on implementing the DI using Dagger 2 in an android app. -

-

- Check Part 1 - - here - - . -

-

- For the sake of this tutorial, we will break the process in steps and analyze each step one by one. Remember Dagger requires a concentrated approach. So actively follow the below tutorial, asking a lot of questions. For the project structure, see the project repo mentioned below. -

-

- - let’s get started. - -

-

- The GitHub repo for the project: - - https://github.com/MindorksOpenSource/android-dagger2-example - -

-

- First, we have to define the structure of the Android App. The core classes are as follows: -

-
    -
  1. - - DataManager - - class will provide access to the data of the application. -
  2. -
  3. - - DbHelper - - class will be used by DataManager to access the SQLite database. -
  4. -
  5. - - SharedPrefsHelper - - will be used by - - DataManager - - to access the - - SharedPreferences - - . -
  6. -
  7. - Model classes for retrieving the DB table. -
  8. -
-

- - Step 1: - -

-

- Create a project in android studio with an empty Activity and add the following dependencies in app’s - - build.gradle - -

-
dependencies {
-    ...
-    compile "com.google.dagger:dagger:2.8"
-    annotationProcessor "com.google.dagger:dagger-compiler:2.8"
-    provided 'javax.annotation:jsr250-api:1.0'
-    compile 'javax.inject:javax.inject:1'
-}
-

- Notes: We are using the annotation processor provided by gradle for android. dagger-compiler is the annotation processing repo for generating the dependency graph classes during build time. Other gradle dependencies are provided for the sake of Dagger. -

-

- - Step 2: - -

-

- The data part we will be building first. So, create a model class - - User - - . -

-
public class User {
-
-    private Long id;
-    private String name;
-    private String address;
-    private String createdAt;
-    private String updatedAt;
-
-    public User() {
-    }
-
-    public User(String name, String address) {
-        this.name = name;
-        this.address = address;
-    }
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getAddress() {
-        return address;
-    }
-
-    public void setAddress(String address) {
-        this.address = address;
-    }
-
-    public String getCreatedAt() {
-        return createdAt;
-    }
-
-    public void setCreatedAt(String createdAt) {
-        this.createdAt = createdAt;
-    }
-
-    public String getUpdatedAt() {
-        return updatedAt;
-    }
-
-    public void setUpdatedAt(String updatedAt) {
-        this.updatedAt = updatedAt;
-    }
-
-    @Override
-    public String toString() {
-        return "User{" +
-                "id=" + id +
-                ", name='" + name + '\'' +
-                ", address='" + address + '\'' +
-                ", createdAt='" + createdAt + '\'' +
-                ", updatedAt='" + updatedAt + '\'' +
-                '}';
-    }
-}
-

- - Notes - - : This class will bind the DB table data. -

-

- - Step 3: - -

-

- Create few custom annotations: - - ActivityContext - - , - - ApplicationContext - - , - - DatabaseInfo - - , - - PerActivity - -

-
@Qualifier
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ActivityContext {
-}
-
@Qualifier
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ApplicationContext {
-}
-
@Qualifier
-@Retention(RetentionPolicy.RUNTIME)
-public @interface DatabaseInfo {
-}
-
@Scope
-@Retention(RetentionPolicy.RUNTIME)
-public @interface PerActivity {
-}
-

- - Notes: - -

-

- - Why are we creating these annotations and what is - - - - @Qualifier - - - - and - - @Scope - - ? - -

-

- - @Qualifier - - annotation is provided by - - javax inject package - - and is used to qualify the dependency. For example, a class can ask both, an Application Context and an Activity Context. But both these Objects will be of type Context. So, for Dagger to figure out which variable is to be provided with what, we have to explicitly specify the identifier for it. -

-

- Thus - - @Qualifier - - is used to distinguish between objects of the same type but with different instances. In the above code, we have - - ActivityContext - - and - - ApplicationContext - - so that the - - Context - - object being injected can refer to the respective - - Context - - type. - - DatabaseInfo - - is used to provide the database - - name - - in the class dependency. Since a - - String - - class in being provided as a dependency, it always a good idea to qualify it so that the Dagger can explicitly resolve it. -

-

- An alternative to this is - - @Named - - annotation provided by Dagger. - - @Named - - itself is annotated with - - @Qualifier - - . With - - @Named - - we have to provide string identifier for similar class objects and this identifier is used to map the dependency of a class. We will explore the - - @Named - - at the end of this example. -

-

- - @Scope - - is used to specify the scope in which a dependency object persists. If a class getting dependencies, have members injected with classes annotated with a scope, then each instance of that class asking for dependencies will get its own set of member variables. -

-

- - Step 4: - -

-

- Create a - - DbHelper - - class that extends the - - SQLiteOpenHelper - - . This class will be responsible for all the DB related operations. -

-
@Singleton
-public class DbHelper extends SQLiteOpenHelper {
-
-    //USER TABLE
-    public static final String USER_TABLE_NAME = "users";
-    public static final String USER_COLUMN_USER_ID = "id";
-    public static final String USER_COLUMN_USER_NAME = "usr_name";
-    public static final String USER_COLUMN_USER_ADDRESS = "usr_add";
-    public static final String USER_COLUMN_USER_CREATED_AT = "created_at";
-    public static final String USER_COLUMN_USER_UPDATED_AT = "updated_at";
-
-    @Inject
-    public DbHelper(@ApplicationContext Context context,
-                    @DatabaseInfo String dbName,
-                    @DatabaseInfo Integer version) {
-        super(context, dbName, null, version);
-    }
-
-    @Override
-    public void onCreate(SQLiteDatabase db) {
-        tableCreateStatements(db);
-    }
-
-    @Override
-    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-        db.execSQL("DROP TABLE IF EXISTS " + USER_TABLE_NAME);
-        onCreate(db);
-    }
-
-    private void tableCreateStatements(SQLiteDatabase db) {
-        try {
-            db.execSQL(
-                    "CREATE TABLE IF NOT EXISTS "
-                            + USER_TABLE_NAME + "("
-                            + USER_COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
-                            + USER_COLUMN_USER_NAME + " VARCHAR(20), "
-                            + USER_COLUMN_USER_ADDRESS + " VARCHAR(50), "
-                            + USER_COLUMN_USER_CREATED_AT + " VARCHAR(10) DEFAULT " + getCurrentTimeStamp() + ", "
-                            + USER_COLUMN_USER_UPDATED_AT + " VARCHAR(10) DEFAULT " + getCurrentTimeStamp() + ")"
-            );
-
-        } catch (SQLException e) {
-            e.printStackTrace();
-        }
-    }
-
-    protected User getUser(Long userId) throws Resources.NotFoundException, NullPointerException {
-        Cursor cursor = null;
-        try {
-            SQLiteDatabase db = this.getReadableDatabase();
-            cursor = db.rawQuery(
-                    "SELECT * FROM "
-                            + USER_TABLE_NAME
-                            + " WHERE "
-                            + USER_COLUMN_USER_ID
-                            + " = ? ",
-                    new String[]{userId + ""});
-
-            if (cursor.getCount() > 0) {
-                cursor.moveToFirst();
-                User user = new User();
-                user.setId(cursor.getLong(cursor.getColumnIndex(USER_COLUMN_USER_ID)));
-                user.setName(cursor.getString(cursor.getColumnIndex(USER_COLUMN_USER_NAME)));
-                user.setAddress(cursor.getString(cursor.getColumnIndex(USER_COLUMN_USER_ADDRESS)));
-                user.setCreatedAt(cursor.getString(cursor.getColumnIndex(USER_COLUMN_USER_CREATED_AT)));
-                user.setUpdatedAt(cursor.getString(cursor.getColumnIndex(USER_COLUMN_USER_UPDATED_AT)));
-                return user;
-            } else {
-                throw new Resources.NotFoundException("User with id " + userId + " does not exists");
-            }
-        } catch (NullPointerException e) {
-            e.printStackTrace();
-            throw e;
-        } finally {
-            if (cursor != null)
-                cursor.close();
-        }
-    }
-
-    protected Long insertUser(User user) throws Exception {
-        try {
-            SQLiteDatabase db = this.getWritableDatabase();
-            ContentValues contentValues = new ContentValues();
-            contentValues.put(USER_COLUMN_USER_NAME, user.getName());
-            contentValues.put(USER_COLUMN_USER_ADDRESS, user.getAddress());
-            return db.insert(USER_TABLE_NAME, null, contentValues);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw e;
-        }
-    }
-
-    private String getCurrentTimeStamp() {
-        return String.valueOf(System.currentTimeMillis() / 1000);
-    }
-}
-

- - Notes - - : This class introduces few annotation. -

-
    -
  1. - - @Singleton - - ensure a single instance of a class globally. So, there will be only one - - DbHelper - - class instance for the app and whenever a class asks for - - DbHelper - - as a dependency, it will be provided with the same instance that is maintained in the Dagger’s dependency graph. -
  2. -
  3. - - @Inject - - on the constructor instructs the Dagger to accumulate all the parameter dependencies when the class is being constructed. -
  4. -
  5. - - @ApplicationContext - - - Qualifier - - facilitates - - DbHelper - - to get the context object of the application from dagger’s dependency graph -
  6. -
  7. - - @DatabaseInfo - - qualifier helps the dagger to distinguish between - - String - - and - - Integer - - Dependencies from existing same types in the dependency graph. -
  8. -
-

- - We will again come back to this discussion when we deal with the module. - -

-

- Rest of the contents of this class is standard - - SQLiteOpenHelper - - . This class creates a - - user - - table and inserts/reads it. -

-

- - Step 5: - -

-

- Create a - - SharedPrefsHelper - - to deal with the shared preferences. -

-
@Singleton
-public class SharedPrefsHelper {
-
-    public static String PREF_KEY_ACCESS_TOKEN = "access-token";
-
-    private SharedPreferences mSharedPreferences;
-
-    @Inject
-    public SharedPrefsHelper(SharedPreferences sharedPreferences) {
-        mSharedPreferences = sharedPreferences;
-    }
-
-    public void put(String key, String value) {
-        mSharedPreferences.edit().putString(key, value).apply();
-    }
-
-    public void put(String key, int value) {
-        mSharedPreferences.edit().putInt(key, value).apply();
-    }
-
-    public void put(String key, float value) {
-        mSharedPreferences.edit().putFloat(key, value).apply();
-    }
-
-    public void put(String key, boolean value) {
-        mSharedPreferences.edit().putBoolean(key, value).apply();
-    }
-
-    public String get(String key, String defaultValue) {
-        return mSharedPreferences.getString(key, defaultValue);
-    }
-
-    public Integer get(String key, int defaultValue) {
-        return mSharedPreferences.getInt(key, defaultValue);
-    }
-
-    public Float get(String key, float defaultValue) {
-        return mSharedPreferences.getFloat(key, defaultValue);
-    }
-
-    public Boolean get(String key, boolean defaultValue) {
-        return mSharedPreferences.getBoolean(key, defaultValue);
-    }
-
-    public void deleteSavedData(String key) {
-        mSharedPreferences.edit().remove(key).apply();
-    }
-}
-

- - Notes - - : This class is annotated with - - @Singleton - - to make this a singleton class in the dependency graph of Dagger. -

-

- This class also gets - - SharedPreferences - - dependency through Dagger which is expressed by the - - @Inject - - on the constructor. -

-

- - How is this dependency provided? It is explained later in this example. - -

-

- - Step 6: - -

-

- Create - - DataManager - - class -

-
@Singleton
-public class DataManager {
-
-    private Context mContext;
-    private DbHelper mDbHelper;
-    private SharedPrefsHelper mSharedPrefsHelper;
-
-    @Inject
-    public DataManager(@ApplicationContext Context context,
-                       DbHelper dbHelper,
-                       SharedPrefsHelper sharedPrefsHelper) {
-        mContext = context;
-        mDbHelper = dbHelper;
-        mSharedPrefsHelper = sharedPrefsHelper;
-    }
-
-    public void saveAccessToken(String accessToken) {
-        mSharedPrefsHelper.put(SharedPrefsHelper.PREF_KEY_ACCESS_TOKEN, accessToken);
-    }
-
-    public String getAccessToken(){
-        return mSharedPrefsHelper.get(SharedPrefsHelper.PREF_KEY_ACCESS_TOKEN, null);
-    }
-
-    public Long createUser(User user) throws Exception {
-        return mDbHelper.insertUser(user);
-    }
-
-    public User getUser(Long userId) throws Resources.NotFoundException, NullPointerException {
-        return mDbHelper.getUser(userId);
-    }
-}
-

- - Notes: - - This class expresses the dependencies of Application - - Context - - , - - DbHelper - - and - - SharedPrefsHelper - - in the contructor. It provides all the apis to access the data of the application. -

-

- - Step 7: - -

-

- Create - - DemoApplication - - class that extends - - android.app.Application - -

-
public class DemoApplication extends Application {
-
-    protected ApplicationComponent applicationComponent;
-
-    @Inject
-    DataManager dataManager;
-
-    public static DemoApplication get(Context context) {
-        return (DemoApplication) context.getApplicationContext();
-    }
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        applicationComponent = DaggerApplicationComponent
-                                    .builder()
-                                    .applicationModule(new ApplicationModule(this))
-                                    .build();
-        applicationComponent.inject(this);
-    }
-
-    public ApplicationComponent getComponent(){
-        return applicationComponent;
-    }
-}
-

- Add this class in - - AndroidManifest.xml - -

-
<application
-    ...
-    android:name=".DemoApplication"
-    ...
-</application>
-

- - Notes - - : This class gets - - DataManager - - through DI. The interesting part in this class is the - - ApplicationComponent - - . Let’s go on with the steps before we cover this point. -

-

- - Step 8: - -

-

- Create class - - MainActivity - -

-
public class MainActivity extends AppCompatActivity {
-
-    @Inject
-    DataManager mDataManager;
-
-    private ActivityComponent activityComponent;
-
-    private TextView mTvUserInfo;
-    private TextView mTvAccessToken;
-
-    public ActivityComponent getActivityComponent() {
-        if (activityComponent == null) {
-            activityComponent = DaggerActivityComponent.builder()
-                    .activityModule(new ActivityModule(this))
-                    .applicationComponent(DemoApplication.get(this).getComponent())
-                    .build();
-        }
-        return activityComponent;
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_main);
-
-        getActivityComponent().inject(this);
-
-        mTvUserInfo = (TextView) findViewById(R.id.tv_user_info);
-        mTvAccessToken = (TextView) findViewById(R.id.tv_access_token);
-    }
-
-    @Override
-    protected void onPostCreate(@Nullable Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-        createUser();
-        getUser();
-        mDataManager.saveAccessToken("ASDR12443JFDJF43543J543H3K543");
-
-        String token = mDataManager.getAccessToken();
-        if(token != null){
-            mTvAccessToken.setText(token);
-        }
-    }
-
-    private void createUser(){
-        try {
-            mDataManager.createUser(new User("Ali", "1367, Gurgaon, Haryana, India"));
-        }catch (Exception e){e.printStackTrace();}
-    }
-
-    private void getUser(){
-        try {
-            User user = mDataManager.getUser(1L);
-            mTvUserInfo.setText(user.toString());
-        }catch (Exception e){e.printStackTrace();}
-    }
-}
-

- Also create - - activity_main.xml - -

-
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/activity_main"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:paddingBottom="@dimen/activity_vertical_margin"
-    android:paddingLeft="@dimen/activity_horizontal_margin"
-    android:paddingRight="@dimen/activity_horizontal_margin"
-    android:paddingTop="@dimen/activity_vertical_margin"
-    android:gravity="center"
-    android:orientation="vertical">
-
-    <TextView
-        android:id="@+id/tv_user_info"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textColor="@android:color/black"
-        android:padding="10dp"/>
-
-    <TextView
-        android:id="@+id/tv_access_token"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textColor="@android:color/black"
-        android:padding="10dp"/>
-</LinearLayout>
-

- - Now let’s hold on for some time and review the Dagger. - -

-
    -
  1. - To provide the dependency for a class we have to create a Module class. This class defines the methods that provide the dependency. A Module class is identified by - - @Module - - and the dependency provider method in identified by - - @Provides - - . -
  2. -
  3. - We then have to create an interface that serves as a connection between a class that expresses the dependency through - - @Inject - - and a class that provides the dependency i.e. annotated with - - @Module - - . -
  4. -
  5. - In order to figure out the dependencies that a Module has to provide, we have to scan all the classes in the graph that needs to be provided with dependencies and then figure out the least number of objects that has to be provided. -
  6. -
-

- Let’s move back to the example steps to understand the above statements. -

-

- - Step 9: - -

-

- We have to provide the dependencies expressed in the - - DemoApplication - - class. This class needs - - DataManager - - and to provide this class we have to provide the dependencies expressed by - - DataManager - - , which as mentioned in the constructor are - - Context - - , - - DbHelper - - , and - - SharedPrefsHelper - - . We then move further in the graph. -

-
    -
  1. - - Context - - has to be - - ApplicationContext - -
  2. -
  3. - - DbHelper - - needs - - Context - - , - - dbName - - , and - - version - - . This does not have any further branching. -
  4. -
  5. - - SharedPrefsHelper - - needs - - SharedPreferences - -
  6. -
-

- We now accumulate the superset of all these dependencies, which turn out to be: - - Context - - , - - dbName - - , - - version - - , and - - SharedPreferences - -

-

- Now to provide these dependencies we create - - ApplicationModule - -

-
@Module
-public class ApplicationModule {
-
-    private final Application mApplication;
-
-    public ApplicationModule(Application app) {
-        mApplication = app;
-    }
-
-    @Provides
-    @ApplicationContext
-    Context provideContext() {
-        return mApplication;
-    }
-
-    @Provides
-    Application provideApplication() {
-        return mApplication;
-    }
-
-    @Provides
-    @DatabaseInfo
-    String provideDatabaseName() {
-        return "demo-dagger.db";
-    }
-
-    @Provides
-    @DatabaseInfo
-    Integer provideDatabaseVersion() {
-        return 2;
-    }
-
-    @Provides
-    SharedPreferences provideSharedPrefs() {
-        return mApplication.getSharedPreferences("demo-prefs", Context.MODE_PRIVATE);
-    }
-}
-

- - Note: - - We have annotated this class with - - @Module - - and all the methods with - - @Provides - - . -

-

- Let’s explore this class: -

-
    -
  1. - In the constructor, we have passed the - - Application - - instance. This instance is used to provide other dependencies. -
  2. -
  3. - This class provides all the dependencies that we listed in the above step. -
  4. -
-

- - Step 10: - -

-

- We create a Component which links the - - DemoApplication - - dependency and the - - ApplicationModule - -

-
@Singleton
-@Component(modules = ApplicationModule.class)
-public interface ApplicationComponent {
-
-    void inject(DemoApplication demoApplication);
-
-    @ApplicationContext
-    Context getContext();
-
-    Application getApplication();
-
-    DataManager getDataManager();
-
-    SharedPrefsHelper getPreferenceHelper();
-
-    DbHelper getDbHelper();
-
-}
-

- - Notes: - - - ApplicationComponent - - is an interface that is implemented by Dagger. Using - - @Component - - we specify the class to be a Component. -

-

- Here we have written a method - - inject - - where we pass the - - DemoApplication - - instance. - - Why do we do it? - -

-

- When the dependencies are provided through field injection i.e. - - @inject - - on the member variables, we have to tell the Dagger to scan this class through the implementation of this interface. -

-

- This class also provides methods that are used to access the dependencies that exist in the dependency graph. -

-

- - Step 11: - -

-

- Similarly, we have to create the module for - - MainActivity - - and it’s component. Which follow the same procedures as in the above step. -

-
@Module
-public class ActivityModule {
-
-    private Activity mActivity;
-
-    public ActivityModule(Activity activity) {
-        mActivity = activity;
-    }
-
-    @Provides
-    @ActivityContext
-    Context provideContext() {
-        return mActivity;
-    }
-
-    @Provides
-    Activity provideActivity() {
-        return mActivity;
-    }
-}
-

-

-
@PerActivity
-@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class)
-public interface ActivityComponent {
-
-    void inject(MainActivity mainActivity);
-
-}
-

- - Note: - - - ActivityComponent - - specify - - ApplicationComponent - - and - - ActivityModule - - . - - ApplicationComponent - - is added to use the graph that has already been generated in the previous step and do exists because the - - DemoApplication - - class persists till the application is running. -

-

- - @PerActivity - - is a scope and is used to tell the Dagger that the - - Context - - and - - Activity - - provided by the - - ActivityModule - - will be instantiated each time an - - Activity - - is created. So, these objects persist till that activity lives and each activity has its own set of these. -

-

- We may ask that the - - DataManager - - will then be created with each - - Activity - - . But that is not true because we have annotated the - - DataManager - - class with - - @Singleton - - . Which brings the class in the global scope and thus is accessed whenever a dependency is expressed. -

-

- Now let’s revisit the - - DemoApplication - - class and - - MainActivity - - class. These classes don’t have a constructor and Android System is responsible for instantiating these. To get the dependency we use the - - OnCreate - - method as it is called once when they are instantiated. -

-
applicationComponent = DaggerApplicationComponent
-                            .builder()
-                            .applicationModule(new ApplicationModule(this))
-                            .build();
-applicationComponent.inject(this);
-

- - DaggerApplicationComponent - - is the generated class by the Dagger, implementing the - - ApplicationComponent - - . We provide the - - ApplicationModule - - class that is used to construct the dependencies. -

-

- We have also called the - - inject - - method of - - applicationComponent - - and passed the instance of the - - DemoApplication - - class. This is done to use it for providing the - - DataManager - - . - - ApplicationComponent - - instance is retained so as to access all the classes that are available in the dependency graph and is express for access. -

-
public ActivityComponent getActivityComponent() {
-if (activityComponent == null) {
-activityComponent = DaggerActivityComponent.builder()
-                .activityModule(new ActivityModule(this))
-                .applicationComponent(DemoApplication.get(this).getComponent())
-                .build();
-    }
-return activityComponent;
-}
-

- Similar process is applied in the - - MainActivity - - as well. The only difference is that, we also provide - - ApplicationComponent - - that is required for dependencies resolution mentioned in - - ActivityModule - - . -

-

- - This completes the Example project. - -

-

- - Hope you have got a working knowledge of Dagger. - -

-

- - The GitHub repo for this example project: - - - https://github.com/MindorksOpenSource/android-dagger2-example - -

-

- As we mentioned about - - @Named("string") - - annotation, we just have to replace - - @ApplicationContext - - and - - @ActivityContext - - with something like - - @Named("application_context") - - and - - @Named("activity_context") - - every where. But personally I don’t like this implementation. It requires to maintain a - - String - - tag. -

-

- - Note: - - If due to some reason we have to inject dependencies through field injection for classes other that android constructed classes then define a component interface for that class and call it’s inject method in class’s constructor. I would suggest to figure out a way not to do this but try to use the constructor with - - @Inject - - for the injection. -

-

- Let’s become friends on - - - Twitter - - , - - - - Linkedin - - , - - - - Github - - , - - and - - - Facebook - - . - -

-
- - Learning is a journey, let’s learn together! - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Share this blog and spread the knowledge -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- -
-
- - - \ No newline at end of file + \ No newline at end of file diff --git a/java-android-multithreaded-programming-runnable-callable-future-executor/index.html b/java-android-multithreaded-programming-runnable-callable-future-executor/index.html new file mode 100644 index 0000000..7bf136e --- /dev/null +++ b/java-android-multithreaded-programming-runnable-callable-future-executor/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modifying-android-tinder-swipe-view-example-to-support-auto-resize/index.html b/modifying-android-tinder-swipe-view-example-to-support-auto-resize/index.html new file mode 100644 index 0000000..e5cf2cb --- /dev/null +++ b/modifying-android-tinder-swipe-view-example-to-support-auto-resize/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/run-parallel-tasks-in-java-or-android-and-get-callback-when-all-complete-video/index.html b/run-parallel-tasks-in-java-or-android-and-get-callback-when-all-complete-video/index.html new file mode 100644 index 0000000..a85555e --- /dev/null +++ b/run-parallel-tasks-in-java-or-android-and-get-callback-when-all-complete-video/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rxjava-anatomy-what-is-rxjava-how-rxjava-is-designed-and-how-rxjava-works-d357b3aca586/index.html b/rxjava-anatomy-what-is-rxjava-how-rxjava-is-designed-and-how-rxjava-works-d357b3aca586/index.html index abb84ad..aa07be8 100644 --- a/rxjava-anatomy-what-is-rxjava-how-rxjava-is-designed-and-how-rxjava-works-d357b3aca586/index.html +++ b/rxjava-anatomy-what-is-rxjava-how-rxjava-is-designed-and-how-rxjava-works-d357b3aca586/index.html @@ -1,1122 +1 @@ - - - - - RxJava Anatomy: What is RxJava, how RxJava is designed, and how RxJava works. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- - Janishar Ali - - - 19 Jul 2017 - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- RxJava Anatomy: What is RxJava, how RxJava is designed, and how RxJava works. -

-
- RxJava Anatomy: What is RxJava, how RxJava is designed, and how RxJava works. -
-

- RxJava has become the single most important skill for Android development. Most of you must have worked with it in some form, either in your own codebase or through other third party libraries, like - - Fast Android Networking - - and Retrofit. -

-

- There are a huge number of articles and tutorials written on how to use RxJava, then why I am writing this redundant article? -

-

- This article is not a guide on how to use RxJava features but a more - - fundamental exploration - - , what it is that RxJava is solving in our codebase and how it is doing it? -

-

- Let’s start with the official definition of RxJava from its GitHub repository: -

-

- - Definition: - -

-

- - RxJava is a Java VM implementation of Reactive Extensions. - -

-

- So, what is - - Reactive Extension? - -

-

- The official doc describes - - Reactive Extension(ReactiveX) as a library for composing asynchronous and event-based programs by using observable sequences. - -

-

- The definition presents three different terms: - - asynchronous, event-based, and observable sequences. It also says composing programs. - -

-
    -
  1. - - Asynchronous - - : It implies that the different parts of a program run simultaneously. -
  2. -
  3. - - Event-Based - - : The program executes the codes based on the events generated while the program is running. For Example, a Button click triggers an event and then the program’s event handler receives this event and does some work. -
  4. -
  5. - - Observable sequences: - - It will be better understood by the mechanics of it. So, we will come back to it later in this article. -
  6. -
  7. - RxJava free us from the callback hell by providing the composing style of programming. We can plug in various transformations that resembles the Functional programming. -
  8. -
-

- - The Reactive Extension is further elaborated: - - It extends the observer pattern to support sequences of data and/or events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety, concurrent data structures, and non-blocking I/O. -

-
- - Here, observer pattern is the key to understand the architecture, which is a software design pattern, where Subject maintains its Observers and notifies them automatically of any state change, usually by calling one of their methods. - -
-

- Now you must think, what’s new about it? We have been doing these for decades. These are just fancy words for a Publisher-Subscriber library. Also to make things look more enhanced, Functional is associated with the RxJava. -

-

- - The doc says: - - It is sometimes called “ - - functional reactive programming - - ” but this is a - - misnomer - - . ReactiveX may be functional, and it may be reactive, but “functional reactive programming” is a different animal. One main point of difference is that functional reactive programming operates on values that change - - continuously - - over time, while ReactiveX operates on - - discrete - - values that are emitted over time. -

-

- - So, RxJava only has some patterns similar to the principles of Functional programming. - -

-

- - Now, you must be thinking why RxJava is so popular then? - -

-

- You will really appreciate the power of RxJava when you write a thread management program. My deep appreciations for RxJava developed when I later explored it in comparison to the - - JPost - - library I wrote. - - JPost - - is an extended publisher-subscriber library for Java and Android which I created sometime back. -

-

- In the - - JPost - - subscribers communicates with each other over controlled channels synchronously/asynchronously. The thread management was done using ExecutorService, carefully designed for preventing memory leaks and enforce Thread safety. If I were to design this system using RxJava now then it would take fewer lines of code and much less effort(but less learning of course). -

-

- Below is the architectural diagram of my - - JPost - - library. -

-
- RxJava Anatomy: What is RxJava, how RxJava is designed, and how RxJava works. -
-
- RxJava Anatomy: What is RxJava, how RxJava is designed, and how RxJava works. -
-

- Now, that I have expresses my deep appreciation for RxJava, let’s try to see and understand the anatomy of it. -

-

- - The RxJava is an implementation of a Reactive Stream specification. I found below paragraph as the best definition or rather summation of a Reactive Stream. - -

-

- Reactive Streams is a programming concept for handling asynchronous data streams in a non-blocking manner while providing backpressure to stream publishers. It has evolved into a specification that is based on the concept of Publisher<T> and Subscriber<T>. A Publisher is the source of events T in the stream, and a Subscriber is a consumer for those events. A Subscriber subscribes to a Publisher by invoking a “ - - factory method - - ” in the Publisher that will push the stream items <T> starting a new Subscription. This is also called Reactor Pattern. -

-

- There are a number of terms in the above definition. -

-
    -
  1. - - Data Stream - - : It is the flow of data(events/objects/items) in a sequence. -
  2. -
  3. - - non-blocking - - : The thread does not have to wait for the monitor lock. In concurrent programming, a - - monitor - - is a synchronization construct that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become true. -
  4. -
  5. - - Backpressure: - - We will try to understand it later when context become favorable for its discussion. -
  6. -
  7. - - Mechanism of Publisher and Subscriber - - : It is described below: -
  8. -
-

- - How does this Reactive Stream implement? - -

-
- RxJava Anatomy: What is RxJava, how RxJava is designed, and how RxJava works. -
-

- The base implementation is based on 4 API components: -

-
    -
  1. - - Publisher: - - These interfaces(APIs) define the structure of RxJava. -
  2. -
-
public interface Publisher<T> {
-    public void subscribe(Subscriber<? super T> s);
-}
-

- 2. - - Subscriber: - - A Subscriber exposes the following callback methods. -

-
public interface Subscriber<T> {
-
   //signals to the Publisher to start sending events
-    public void onSubscribe(Subscription s);     
-
-    public void onNext(T t);
-    public void onError(Throwable t);
-    public void onComplete();
-}
-

- 3. - - Subscription - - : When the Subscriber becomes ready to start handling events, it signals the Publisher through its Subscription -

-

- - Note: - -

-

- To avoid the name clash, the RxJava 1 - - rx.Subscription - - has been renamed into - - io.reactivex.Disposable - - in RxJava 2. -

-
public interface Subscription {
-    public void request(long n); //request n items
-    public void cancel();
-}
-

- Upon receiving this signal, the Publisher begins to invoke - - Subscriber::onNext(T) - - for each event - - T - - . This continues until either completion of the stream ( - - Subscriber::onComplete() - - ) or an error occurs during processing ( - - Subscriber::onError(Throwable) - - ). -

-

- 4. - - Processor - - : It represents a processing stage—which is both a Subscriber and a Publisher and obeys the contracts of both. -

-
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {}
-

- In the Reactive-Streams specification, the Subject-like behavior, namely being a consumer and supplier of events at the same time, is done by the Processor interface. -

-

- - Publishers - -

-

- Let’s see how publishers are structured in RxJava. RxJava provides following types of event publishers: -

-
    -
  • - - Flowable: - - A Publisher that emits 0..N elements, and then completes successfully or with an error. -
  • -
  • - - Observable: - - Similar to Flowables but without a backpressure strategy. They were introduced in RxJava 1.x. -
  • -
  • - - Single: - - It completes with a value successfully or an error.( - - doesn’t have onComplete callback, instead onSuccess(val) - - ). -
  • -
  • - - Maybe: - - It completes with/without a value or completes with an error. -
  • -
  • - - Completable: - - It just signals if it has completed successfully or with an error. -
  • -
-

- To create a stream in RxJava we can use one of the Publisher’s factory methods. -

-
Flowable<Integer> flowable = Flowable.just(6, 4, 10, 20);
-Flowable<String> flowable = Flowable.fromIterable(List.of("red", "green", "blue"));
-

- There are a number of factory methods or we can use Observable.create(…) to implement the emissions of events by calling onNext(val), onComplete(), onError(throwable). -

-
Observable<Integer> stream = Observable.create(subscriber -> {
-    System.out.println("Started emitting");
-
-    System.out.println("Emitting 1st");
-    subscriber.onNext(1);
-
-    System.out.println("Emitting 2nd");
-    subscriber.onNext(2);
-
   System.out.println("Emitting onComplete");
-    subscriber.onComplete();
-});
-

- Remember we came across - - Observable sequences - - when defining - - Reactive Extension - - . Now we can see that the all Publishers like Observable and Flowable take some items and pass onto its subscribers. So, these items are called as - - Observable sequences - - or - - Data Stream. - -

-

- An important property of the - - Stream - - is that it’s lazy, meaning that the code inside create() doesn’t get executed without subscribing to the stream. -

-

- - Cold and Hot Publishers - -

-

- - Cold publishers - - : They only begin emitting when there is a subscriber, and all subscribers receive the exact set of historical data, regardless of when they subscribe. The - - subscriber - - is taking elements only when it is ready to process that item, and items do not need to be buffered in a publishers because they are requested in a - - pull fashion - - . The Flowable and the Observable we created above are cold publishers. -

-

- - Hot publishers - - : They begins generating items and emits them immediately when they are created. They emits items at its own pace, and it is up to its subscriber to keep up. When the subscriber is not able to consume items as quickly as they are produced by a publisher, they need to be buffered or handled in some other way, as they will fill up the memory, finally causing OutOfMemoryException - - . - - They can be considered as - - push scenarios - - . -

-

- - Subjects - - are one way to handle hot observables. Subjects keep the reference to their subscribers and allow ‘multicasting’ an event to them. -

-

- Refer to this article to understand Subjects: - - - Link - - -

-

- - Note: - -

-

- The AsyncSubject, BehaviorSubject, PublishSubject, ReplaySubject and UnicastSubject in 2.x don’t support backpressure (as part of the 2.x Observable family). -

-

- The AsyncProcessor, BehaviorProcessor, PublishProcessor, ReplayProcessor and UnicastProcessor are backpressure-aware. -

-

- - Subscriber - -

-

- The Subscriber as mentioned in the above text subscribes to a Publisher and then receives events in one of its callback methods. -

-

- - Canceling subscription - -

-

- When a Subscriber subscribes a Publisher then in RxJava2, a Disposable instance is returned which can be used to cancelled/disposed a Subscriber externally via Disposable::dispose(). -

-

- Inside the create() method, we can check if there are still active subscribers to our Flowable/Observable. -

-

- There are operators that also unsubscribe from the stream so the source knows to stop producing events. For example, - - take(limit) - - is a simple operator. Its role is to count the number of events and then unsubscribes from its source once it received the specified amount and calls onComplete() to its subscriber. -

-

- - Error handling - -

-

- In reactive, exceptions are first class citizens. Since streams are generally asynchronous, it doesn’t make sense to throw an exception, so instead any exception is passed as an event in the stream. The Observable contract specifies that exceptions are terminal operations. That means in case an error reaches the Subscriber, after invoking the ‘onError’ handler, it also unsubscribes. There are operators to continue the subscription in case it is required. -

-

- - Operators - -

-

- The real power of RxJava is realized in the manipulation of the data streams. There are a lot of - - operators - - available in RxJava that simplifies this process. They are applied between the source Observable / Flowable and the Subscriber. -

-

- Example: - - flatMap: - - It takes the emissions (objects, collections, or arrays) from an Observable, and maps those elements to individual Observables, then flattens the emissions from all of those into a single Observable. -

-
Observable.fromArray("janishar ali anwar")
-        .flatMap(word -> Observable.fromArray(word.split(" ")))
-        .zipWith(Observable.range(1, Integer.MAX_VALUE),
-                (string, count) -> String.format("%2d. %s", count, string))
-        .subscribe(
-                val -> System.out.print(val + " "),
-                err -> {
-                    System.out.println("nerror ");
-                },
-                () -> System.out.println("ncompleted"));
-

- - Output: 1. janishar 2. ali 3. anwar - -
- - completed - -

-

- Other important operators are: -

-

- filter, map, delay, interval, reduce, collect, defer, zipWith, merge, concat, timeout, retry, onErrorReturn, toList. -

-

- To understand these operators through examples refer to this repo: - - - Link - - -

-

- - Schedulers - -

-

- As I mentioned about my library - - JPost - - , where I had to manage the Thread at a low level. RxJava Schedulers are for this purpose. They provide high-level constructs to manage with concurrency and deal with details by itself. They create workers who are responsible for scheduling and running code. By default RxJava will not introduce concurrency and will run the operations on the subscription thread. -

-

- There are two methods through which we can introduce Schedulers into our chain of operations: -

-
    -
  • - - subscribeOn - - : It specify which Scheduler invokes the code contained in Observable.create(). -
  • -
  • - - observeOn: - - It allows control to which Scheduler executes the code in the downstream operators. -
  • -
-

- - RxJava provides some general use Schedulers: - -

-
    -
  • - - Schedulers.computation() - - : Used for CPU intensive tasks. -
  • -
  • - - Schedulers.io() - - : Used for IO bound tasks. -
  • -
  • - - Schedulers.from(Executor) - - : Use with custom ExecutorService. -
  • -
  • - - Schedulers.newThread(): - - It always creates a new thread when a worker is needed. Since it’s not thread pooled and always creates a new thread instead of reusing one, this scheduler is not very useful. -
  • -
-

- - Backpressure - -

-

- In cases where a publisher is emitting items more rapidly than an operator or subscriber can consume them, then the items that are overflowing from the publisher need to be handled. If for example we try to maintain an ever-expanding buffer of items emitted by the faster publisher to eventually combine with items emitted by the slower one. This could result in OutOfMemoryError. -

-
- - Backpressure relates to a feedback mechanism through which the subscriber can signal to the producer how much data it can consume and so to produce only that amount. - -
-

- There are a number of way to handle the backpressure like buffering, batching, skipping etc. and there are operators to deal with them. These are explained in the official reference: - - - Link - - -

-

- Let’s see some scenarios: -

-

- The Subscriber has an onSubscribe(Subscription) method, Subscription::request(long n), it is through this it can signal upstream that it’s ready to receive a number of items and after it processes the items request another batch. There is a default implementation which requests - - Long.MAX_VALUE - - which basically means “ - - send all you have - - ”. But we have not seen the code in the producer that takes consideration of the number of items requested by the subscriber. -

-

- Let’s see the Flowable example: -

-
Flowable.create(subscriber -> {
-int count = 0;
-while (true) {
-        count++;
-        subscriber.onNext(count + "n");
-    }
-
-}, BackpressureStrategy.DROP)
-        .observeOn(Schedulers.newThread(), false, 3)
-        .subscribe(
-                val -> {
-                    Thread.sleep(1000);
-                    System.out.println(val);
-                },
-                err -> {
-                    System.out.println("error ");
-                    err.printStackTrace();
-                },
-                () -> System.out.println("completed")
-        );
-

- The 2nd parameter - - BackpressureStrategy - - allows us to specify what to do in the case of overproduction. -

-
    -
  • - - BackpressureStrategy.BUFFER: - - It buffers in memory the events that overflow. If we don’t provide some threshold, it might lead to OutOfMemoryError. -
  • -
  • - - BackpressureStrategy.DROP - - : It simply drop the overflowing events -
  • -
  • - - BackpressureStrategy.LATEST - - : It keeps only recent event and discards previous unconsumed events. -
  • -
  • - - BackpressureStrategy.ERROR - - : We get an error in the Subscriber immediately. -
  • -
  • - - BackpressureStrategy.MISSING - - : We use this when we don’t care about backpressure(we let one of the downstream operators onBackpressureXXX handle it) -
  • -
-

- By default the subscriber requests - - Long.MAX_VALUE - - since the code flowable.subscribe(onNext, onError, onComplete) uses a default onSubscribe. So unless we override onSubscribe, it would overflow. We can control this through operator - - observeOn() - - that make its own request to the upstream Publisher(256 by default), but can take a parameter to specify the request size. -

-

- In the above example, initially, the Subscriber requests Long.MAX_VALUE, but as the subscription travels upstream through the operators to the source Flowable, the operator observeOn subscribes to the source and requests just 3 items from the source instead. Since we used BackpressureStrategy.DROP, all the items emitted outside the 3, get discarded and thus never reach our subscriber. -

-

- There are also specialized operators to handle backpressure the onBackpressureXXX operators: -

-
    -
  1. - - onBackpressureBuffer - -
  2. -
  3. - - onBackpressureDrop - -
  4. -
  5. - - onBackpressureLatest - -
  6. -
-
.onBackpressureDrop(val -> System.out.println("Dropping " + val))
-

- These operators request Long.MAX_VALUE(unbounded amount) from upstream and then take it upon themselves to manage the requests from downstream. In the case of - - onBackpressureBuffer - - it adds in an internal queue and sends downstream the events as requested, - - onBackpressureDrop - - just discards events that are received from upstream more than requested from downstream, - - onBackpressureLatest - - also drops emitted events excluding the last emitted event(most recent). The last onBackpressureXXX operator overrides the previous one if they are chained. -

-
- - RxJava is really a new way of thinking about writing a program. I am learning new things in RxJava each day. How you use RxJava in your coding will change with experience. So, I would recommend to ease into this subject. - -
-

- If you want to learn RxJava by examples then - - here - - is a tutorial for you. -

-

- Also, Let’s become friends on - - - Twitter - - , - - - - Linkedin - - , - - - - Github - - , - - and - - - Facebook - - . - -

-
- - Learning is a journey, let’s learn together! - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Share this blog and spread the knowledge -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- -
-
- - - \ No newline at end of file + \ No newline at end of file