Dagger - Coding Infinite https://codinginfinite.com/dagger/ Your infinite Coding Solutions Fri, 11 Oct 2019 08:00:59 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.3 https://codinginfinite.com/wp-content/uploads/2018/07/CODING-INFINITE-FAVICON.png Dagger - Coding Infinite https://codinginfinite.com/dagger/ 32 32 Android Paging Library With Example https://codinginfinite.com/android-paging-library-example-with-recycler-view-load-more/ https://codinginfinite.com/android-paging-library-example-with-recycler-view-load-more/#comments Sun, 03 Jun 2018 18:10:34 +0000 http://codinginfinite.com/?p=505 Hello, guys today we’re gonna look out a new Android Architecture Component library called Paging. In this blog, I try to explain the different components of the library and tell how they interact. Paging library makes it easier to load data gradually and gracefully in your app. The paging library supports both large bounded list...

The post Android Paging Library With Example appeared first on Coding Infinite.

]]>
Hello, guys today we’re gonna look out a new Android Architecture Component library called Paging. In this blog, I try to explain the different components of the library and tell how they interact. Paging library makes it easier to load data gradually and gracefully in your app. The paging library supports both large bounded list and unbounded lists, such as continuously updating feeds. The paging library is based on the idea of sending lists to the UI with the live data of a list that is observed by RecyclerView.Adapter.

 Scenario

Ok, let’s say our client want’s to make a movie app. In this app he wants to show a list of movies and fetch new movies when the user reaches at the end of a list. So, what you think first in mind. Alright, that’s simple I can make it with RecyclerView.ScrollListener and fetch the new movies when the user reaches at the end of the list. But let me tell you a keynote here, with the ScrollListener approach you might request data actually you don’t need, wasting user battery and bandwidth. The most important is, you have to check every time when the user scrolls down and see whether it’s appropriate to fetch new movies or not.

Example

So, let’s see how we gonna tackle the previous problem with the paging library. In this app, we simply wanna show some movie content fetched with API and of course our app using paging library. For this example, we’re gonna use TheMovieDB API for fetching the movies.

Movie API Response

Before to start I wanna show you the response. Please see this link for API response.

Android App Setup

First, add the Paging dependency in the app level build.gradle file.

// Paging
implementation 'android.arch.paging:runtime:1.0.0-alpha4-1'    // Change it current dependency version
implementation 'android.arch.lifecycle:runtime:1.1.1'
implementation 'android.arch.lifecycle:extensions:1.1.1'

Now you guy’s must have to see the response and you noticed that every time we need to request TheMovieDB. We need to add the page number in the query. So, for this type of paging requests, we can easily use PageKeyedDataSource. To use paged keyed data sourcewe need to extend it to our class.

MovieDataSource

The following shows how we can create a paged keyed data source for our MovieDataSource class.

class MovieDataSource(private val serviceApi: ServiceApi) : PageKeyedDataSource<Int, MovieResponse.Movie>() {

    val loadDataState = MutableLiveData<DataLoadState>()

    companion object {
        const val MOVIE_API_KEY = "e5c7041343c99********8b720e80c7"   // Change it with your API_kye
    }

    override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, MovieResponse.Movie>) {
        loadDataState.postValue(DataLoadState.LOADING)
        val movieCallback: Call<MovieResponse> = serviceApi.getPopular(MOVIE_API_KEY, 1)
        Completable.fromRunnable {
            val response = movieCallback.execute()
            if (response != null && response.isSuccessful && response.body() != null)
                callback.onResult(response.body()!!.movies, 1, 2)
            else
                loadDataState.postValue(DataLoadState.FAILED)
        }.subscribeOn(Schedulers.io())
                .subscribe({ loadDataState.postValue(DataLoadState.COMPLETED) },
                        { loadDataState.postValue(DataLoadState.FAILED) })
    }

    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, MovieResponse.Movie>) {
        val movieCallback = serviceApi.getPopular(MOVIE_API_KEY, params.key)
        Completable.fromRunnable {
            val response = movieCallback.execute()
            if (response != null && response.isSuccessful && response.body() != null)
                callback.onResult(response.body()!!.movies, params.key + 1)
        }.subscribeOn(Schedulers.io())
                .subscribe({
                    Log.e("Call Response", "Paged Call Complete")
                }, { it.printStackTrace() })
    }
}

You see we’re passing ServiceApi instance to our MovieDataSource. ServiceApi is the Retorift interface instance. This blog is about paging, I’m not gonna show you how to create Retrofit instance.

So, loadInitial is the overridden method which will be called only first time. In this method, we’re executing our network request to fetch movies. You see I’m passing 1 in the getPopular method. This is because loadInitial will only be called the first time and that’s why it will only fetch the first page of popular movies list. When the response came from a server then we need to setResult in on LoadInitialCallbackThe onResult method takes three parameters. First, is the actual result came from the server, second the page number that we’ve just executed. And the parameter is the next page number which is 2.

Now the second overridden method is loadAfter which will be called every time when a user scrolls down at the end of a list. In this method, we’re doing the same work as we do in loadInitial except for incrementing the page number every time request execute.

Now that we successfully create DataSource, it’s time to see how we can create DataSource.FactoryTo create the data source factory we need to extend it with DataSource.Factory class.

MovieDataFactory

The following shows how to create DataSource.Factory.

class MovieDataSourceFactory(private val serviceApi: ServiceApi) : DataSource.Factory<Int, MovieResponse.Movie> {

    private val mutableDataSource = MutableLiveData<MovieDataSource>()

    override fun create(): DataSource<Int, MovieResponse.Movie> {
        val dataSource = MovieDataSource(serviceApi)
        mutableDataSource.postValue(dataSource)
        return dataSource
    }
}

The paging library provides the LivePagedListBuilder class for getting a LiveData object of type PagedListTo create a live paged list builder pass in the data source factory object and the paging configuration.

MovieRepositoryImp

The following shows how to create LivePagedListBuilder.

class MovieRepositoryImp(private val movieDataSourceFactory: MovieDataSourceFactory) : MovieRepository {

    companion object {
        const val PAGE_SIZE = 15
    }

    @MainThread
    override fun getMovies(): LiveData<PagedList<MovieResponse.Movie>> {
        val config = PagedList.Config.Builder()
                .setInitialLoadSizeHint(PAGE_SIZE)
                .setPageSize(PAGE_SIZE)
                .build()
        return LivePagedListBuilder(movieDataSourceFactory, config)
                .setInitialLoadKey(1)
                .setBackgroundThreadExecutor(Executors.newFixedThreadPool(3))
                .build()
    }
}

That’s the basic way of creating LivePagedListBuilder.

MovieRepository

Below is the MovieRepository interface.

interface MovieRepository {

    fun getMovies(): LiveData<PagedList<MovieResponse.Movie>>

}

The paging library also provides PagedListAdapterwhich helps you present data from PagedList inside recycler viewThe paged list adapter notifies when the pages are loaded.

MovieAdapter

Now let’s see how can we create PagedListAdapter.

class MovieAdapter(context: Context) : PagedListAdapter<MovieResponse.Movie, MovieViewHolder>(object : DiffUtil.ItemCallback<MovieResponse.Movie>() {
    override fun areItemsTheSame(oldItem: MovieResponse.Movie, newItem: MovieResponse.Movie) = oldItem.title == newItem.title

    override fun areContentsTheSame(oldItem: MovieResponse.Movie, newItem: MovieResponse.Movie) = oldItem.title == newItem.title

}) {

    private val layoutInflater = LayoutInflater.from(context)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
       // return ViewHolder Object
    }

    override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
        val movie = getItem(position)
        // Show data in to ViewHolder
    }
}

You see PagedListAdapter is accepting DiffUtil.ItemCallbackThe callback computes fine grains update as new data received.

MainActivity

Now everything is done for creating paging stuff. Let’s see how can we use this in our activity class.

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)        
        movieRecyclerView.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false)
        movieRecyclerView.setHasFixedSize(true)
        val movieAdapter = MovieAdapter(this)
        movieRecyclerView.adapter = movieAdapter
        movieRepo.getMovies()        // First create MovieRepositoryImp first
                .observe(this, Observer<PagedList<MovieResponse.Movie>> {
                    movieAdapter.submitList(it)
                })
    }

You guys must be thinking why on earth, I did not create a movie repository instance. If you remember our movie repo needs MovieDataSourceFactory and the factory needs ServiceApi. You see all of these are depending on another object, that’s why I wrote the above application with DepedencyInjection. 

Note: I wrote a pretty good article on how the work with dependency injection and how we can use it in our Android app.

Now it’s a good approach that you stop listening to the new movies list in onStop or onDestroy. 

override fun onStop() {
       super.onStop()
       movieRepo.getMovies()
               .removeObservers(this)
   }

That’s it guys, this is my demonstration about how to work with the paging library. I’m sure there’s a lot more about this library and I encouraged you to read about it. If you wanna see the complete code of the above example see it on GitHub.

Thanks for being here and keep reading.

The post Android Paging Library With Example appeared first on Coding Infinite.

]]>
https://codinginfinite.com/android-paging-library-example-with-recycler-view-load-more/feed/ 7
Android Room Persistence Example https://codinginfinite.com/android-room-tutorial-persistence/ https://codinginfinite.com/android-room-tutorial-persistence/#comments Fri, 25 May 2018 00:23:27 +0000 http://codinginfinite.com/?p=451 Today we’re gonna look out a new Android Architecture Component library called Room. The room is basically a “Persistence library that provides an abstraction over SQLite“. The room is a new way to create the database in your Android apps. Although the Android framework provides built-in support for SQLite database, there are many drawbacks working with SQLite....

The post Android Room Persistence Example appeared first on Coding Infinite.

]]>
Today we’re gonna look out a new Android Architecture Component library called Room. The room is basically a “Persistence library that provides an abstraction over SQLite“. The room is a new way to create the database in your Android apps. Although the Android framework provides built-in support for SQLite database, there are many drawbacks working with SQLite.

Drawbacks Of SQLite

Before the start, I want to clarify the drawbacks of SQLite database.

  1. You have to write a lot of boilerplate code.
  2. You have to implement object mapping for every query you write.
  3. Difficult to implement database migrations.
  4. Database operation on the main thread.

Components of Room

Now there are three main components for creating the database with the room.

  1. EntityEntity is an annotated class. This annotation is used to create the database table. After adding Entity annotation room will take care of creating the database table for you.
  2. Dao: Dao is also an annotated class. To access the data from the database you used Dao (Data Access Object). In Dao interface, you declare all the methods needed to work with the database.
  3. DatabaseDatabase is an annotated class. In database class, we define all of our Entity class and tell the version of the database.

Android App Coding

So, enough of this theory let’s build a real-life scenario app. We’re going to create a Book Library app. In this app, the user adds a book name and select the who is the author then insert the book along with author name into the database.

Alright first create a new project in Android Studio with empty activity. Now add the Room dependency into a build.gradle file.

// Room database dependencies
implementation 'android.arch.persistence.room:runtime:1.1.0'   // Use current library version
kapt 'android.arch.persistence.room:compiler:$versions.1.1.0'  // If language is kotlin remain same else use annotationProcessor instead of kapt

Note: If you’re using Kotlin language please add kapt annotation plugin at the top of a build.gradle file.

Now let’s create our first component which is EntityIn our example, we need two Entity classes one for Author of a book and one for Book itself. It means we have two tables in our database.

The following shows how to create our first Entity of Author class.

AuthorModel

@Entity(tableName = "authors")
data class AuthorModel(@PrimaryKey(autoGenerate = true)
                       @ColumnInfo(name = "author_id")
                       val authorId: Long = 0,
                       @ColumnInfo(name = "author_name")
                       var authorName: String)

For Entity, we add the annotation to our class and tell the name of a table. Now in every Entity class, one Primary Key is necessary. In order to tell which value is the primary key annotate with @PrimaryKey. The @ColumnName is for describing the name of table values. The @ColumnName is not necessary for every field if the not defined room will use the variable name when creating the table.

Below is another Entity for BookItem class.

BookItem

@Entity(tableName = "books"
        , indices = [(Index(value = ["book_id"], name = "idx_books_book_id"))],
        foreignKeys =
        [(ForeignKey(
                entity = AuthorModel::class
                , childColumns = ["author_id"]
                , onUpdate = ForeignKey.CASCADE
                , onDelete = ForeignKey.CASCADE))]
)
data class BookItem(@PrimaryKey @ColumnInfo(name = "author_id") val authorId: Long, @ColumnInfo(name = "book_id") val bookId: Long, val name: String)

Now, this Entity class is complicated than the previous one. In BookItem we use a Foreign Key relation with the Author class table. You see every book has an author that’s why we need the authorId to specify who is the author of the book.

We create database tables right, how do we access the data. For accessing the data here comes the Dao’s annotation. For creating a Dao you need to create an interface and annotate with Dao and declares all the methods needed to work with the database. There are four annotations when declaring the methods in Dao’s

  1. InsertInsert for inserting the data.
  2. Update:  For updating the data.
  3. Delete: For deleting the data.
  4. QueryThis annotation is for SQL statement and this checked at compile time. If the query has an error it will tell you at compile time instead of when executing the query.

Note: All of these queries is Synchronous meaning that they will be run on the same thread you’re triggering from. If that’s Main Thread your app will crash IllegalStateExceptionSo, the best approach is that you’ve to run these queries from Background Thread and get the result in Main Thread. For this, you can use RxJava and Kotlin Co-routines.

Now let’s see how we can create a basic Dao interface.

@Dao
interface BaseDao<in T> {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(t: T): Long

    @Delete
    fun delete(type : T)

    @Update
    fun update(type : T)

}

See every database table has some base methods like insert, delete, update etc. So, I create a generic Dao interface and we just need to extend this BaseDao interface.

Below is the AuthorDao interface.

AuthorDao

@Dao
interface AuthorDao : BaseDao<AuthorModel> {

    @Query(value = "SELECT * FROM authors")
    fun getAllAuthors(): List<AuthorModel>

    @Query(value = "SELECT * FROM authors WHERE author_id = :authorId")
    fun getAuthorWithId(authorId: Long): AuthorModel?

    @Query(value = "SELECT author_id FROM authors")
    fun getAllIds(): List<Long>
}

You see with Query annotation we’re providing a SQL query and Room will be able to provide the data according to SQL query.

Below is the BookDao interface.

BookDao

@Dao
interface BookDao : BaseDao<BookItem> {

    @Query(value = "SELECT * FROM books")
    fun getAllBooks(): List<BookItem>

    @Query(value = "SELECT * FROM books WHERE author_id = :authorId")
    fun getBooksWithAuthorId(authorId: Long): List<BookItem>
}

The class, that’s put the Entities and Dao’s together is the RoomDatabaseIn the database class, we define all the Entities and the Version of the database.

Below show’s how to create RoomDatabase class.

BookLibraryDatabase

@Database(entities = [AuthorModel::class, BookItem::class], version = 1)
abstract class BookLibraryDatabase : RoomDatabase() {

    abstract fun authorDao(): AuthorDao

    abstract fun bookDao(): BookDao
}

Everything is done for creating a RoomDatabaseIt’s time to see how can we create RoomLibraryDatabase instance and get the Dao’s object.

Below shows how to create RoomLibraryDatabase instance.

val database = Room.databaseBuilder(context, BookLibraryDatabase::class.java, DATABASE_NAME).build()

So, we have a database object. Now It’s time to use all of the database utility methods that we write in Dao class.

// For inserting the author
Observable.just(database.authorDao().insert(AuthorModel(authorName = "Ahsen Saeed")))
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe({// Author inserted},{it.printStacktrace()})

// Author with Id
Observable.just(database.authorDao().getAuthorWithId(id))
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe({System.out.println(it)},{it.printStacktrace()})

// Get all authors
Observable.just(database.authorDao().getAllAuthors())
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe({ // Here you all authors},{it.printStacktrace()})

// Get books of authors with id
Observable.just(database.bookDao().getBooksWithAuthorId(id))
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe({ // Here you have all books with author id},{it.printStacktrace()})

// Delete the book
Observable.just(database.bookDao().delete(book))
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe({ // Book deleted successfully},{it.printStacktrace()})

// Similarly you can perform all the utility the functions

You guys must be remembered that we need to call these methods from Background Thread and get the result on the Main Thread.

So that’s it, I’m going to end this blog here. I hope you guys, have learned something from this post. If you’ve any queries regarding Room persistence, please do comment below.

I have also written some articles on Room Persistence with RxJava2 and Room Persistence with LiveData.

Thank you for being here and keep reading…

The post Android Room Persistence Example appeared first on Coding Infinite.

]]>
https://codinginfinite.com/android-room-tutorial-persistence/feed/ 2
Dagger With Retrofit And RxJava Example | RecyclerView https://codinginfinite.com/dagger-retrofit-rxjava-example-recyclerview/ https://codinginfinite.com/dagger-retrofit-rxjava-example-recyclerview/#comments Wed, 11 Apr 2018 22:02:37 +0000 http://codinginfinite.com/?p=91 This is the third part of Dagger with Retrofit tutorial. In this part, we’re going to make our network request with RxJava and simply show data in RecyclerView. Note: I strongly recommend you to see my previous blogs this series. If you haven’t seen my previous blogs, then I’m afraid you will not understand. So, without further ado...

The post Dagger With Retrofit And RxJava Example | RecyclerView appeared first on Coding Infinite.

]]>
This is the third part of Dagger with Retrofit tutorial. In this part, we’re going to make our network request with RxJava and simply show data in RecyclerView.

Note: I strongly recommend you to see my previous blogs this series. If you haven’t seen my previous blogs, then I’m afraid you will not understand.

So, without further ado let’s dive into coding.

Below are the libraries we need to add to our build. Gradle file to make a network request with RxJava and also to work with the retrofit.

// Rx java dependency
implementation 'io.reactivex.rxjava2:rxjava:2.1.8' // please add current version of dependencies.

// Rx Android dependency
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' 

// Rx java adapter version
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

Now we need little more improvement in ServiceUtilModule to tell the retrofit builder that we want you to enable RxJava in a network request. By the way, ServiceUtilModule is a part of the dagger which I discussed in the first tutorial.

Below is the code for creating retrofit with RxJava Adapter which is in ServiceUtilModule.

@Provides
@CustomApplicationScope
Retrofit getRetrofit(OkHttpClient okHttpClient, Gson gson) {
    return new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // RxJava Adapter Factory instance for network request.
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .build();
}

Here we need to update our ServiceUtil interface. We have to change the return type of our Network Method from Call to Observable.

ServiceUtil

public interface ServiceUtil {

    @GET("GetCarsCategories.php")
    Observable<CarCategoryResponse> getCarCategories();
}

So, you guys holding just want to make sure because interesting part comes in where we are actually going to see the magic of RxJava. In here we need to update our MainActivity code. In MainActivity we are only updating retrofit network request code, remaining code will be pretty much same.

Below is network call with RxJava, and I believe you guys know lambda’s as well.

disposable = serviceUtil.getCarCategories()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(carCategoryResponse -> {
                    if (carCategoryResponse.getCarCategories() != null && carCategoryResponse.getCarCategories().size() > 0) {
                        this.carCategories.addAll(carCategoryResponse.getCarCategories());
                        carCategoryAdapter.notifyDataSetChanged();
                    } else
                        Toast.makeText(this, "No data found!", Toast.LENGTH_SHORT).show();
                }, throwable -> {
                    if (mainProgressBar.getVisibility() == View.VISIBLE)
                        mainProgressBar.setVisibility(View.GONE);
                    Toast.makeText(this, "Internet not connect", Toast.LENGTH_SHORT).show();
                }, () -> {
                    if (mainProgressBar.getVisibility() == View.VISIBLE)
                        mainProgressBar.setVisibility(View.GONE);
                });

I believe many of you really don’t understand what is just happened. So, don’t worry I’m going to explain this line by line, because this is our main topic RxJava right. So, let’s do it.

Below is the first line of calling getCarCategories function.

serviceUtil.getCarCategories()

In here we actually making our network request with RxJava and getting observable as return type nothing fancy.

The following shows the second line of code.

.subscribeOn(Schedulers.io())

The subscribeOn function basically asking in which thread you want to run your network request. So, we are telling that we want to run our network request in a background thread bypassing Schedulers.io. If we do not execute network request in background thread then our app crashes and we get an error by saying NetworkOnMainThreadException.

The following shows the third line of code.

.observeOn(AndroidSchedulers.mainThread())

The observeOn function asking in which thread you want your response back. So, we’re telling that we want our response back in main thread by passing AndroidSchedulers.mainThread. If we do not listen in the main thread then our app crashes and we get an error by saying CalledFromWrongThreadException.

Below is the fourth line code. The first parameter of subscribes function.

subscribe(carCategoryResponse -> {
                    if (carCategoryResponse.getCarCategories() != null && carCategoryResponse.getCarCategories().size() > 0) {
                        this.carCategories.addAll(carCategoryResponse.getCarCategories());
                        carCategoryAdapter.notifyDataSetChanged();
                    } else
                        Toast.makeText(this, "No data found!", Toast.LENGTH_SHORT).show();
                }

The subscribe method in which we are actually getting our response back. Subscribe function accepting Consumer Interface as a parameter. The consumer interface accepting CarCategoryResponse object and with that, we’re performing some basics stuff like setting RecyclerView data.

The second parameter of subscribes function.

throwable -> {
                    if (mainProgressBar.getVisibility() == View.VISIBLE)
                        mainProgressBar.setVisibility(View.GONE);
                    Toast.makeText(this, "Internet not connect", Toast.LENGTH_SHORT).show();
                }

The second parameter of subscribes method accepting consumer interface but here consumer Interface accepting a Throwable. If any error occurred during the network request this interface will be hit. So, that’s why we’re setting visibility gone to our ProgressBar and show some Toast.

The third parameter of subscribes function.

() -> {
                   if (mainProgressBar.getVisibility() == View.VISIBLE)
                       mainProgressBar.setVisibility(View.GONE);
               }

The third parameter of subscribes method accepting Action interface. This will be called if everything goes right. So, in here we just need to hide the ProgressBar.

Note: Action interface will not be called if the error occurred during the network request. It will only call Consumer with accepting Throwable object interface.

Now one last thing remains which is DisposableThe subscribes method return type is Disposable. We can use disposable to dispose of the running task in onStop.

@Override
protected void onStop(){
    if(disposable != null && !disposable.isDisposed())
        disposable.dispose();
}

This is how we can stop our currently running tasks with disposable in RxJava.

So, this is it our example with Dagger and RxJava is complete. I hope you guys have a good understanding of how to make a network request with RxJava

Download Complete Code

If you’ve any queries regarding this post, please do comment below.

Thank you for being here and keep reading…

Previous Part

The post Dagger With Retrofit And RxJava Example | RecyclerView appeared first on Coding Infinite.

]]>
https://codinginfinite.com/dagger-retrofit-rxjava-example-recyclerview/feed/ 3
Dagger with Retrofit Example – Using Dependency Injection in Activity https://codinginfinite.com/dagger-retrofit-example-dependency-injection-activity/ Wed, 11 Apr 2018 07:06:30 +0000 http://codinginfinite.com/?p=64 This is the second part of Dagger with Retrofit tutorial. In the first part, we’ve achieved the hard part of how to set up dependency injection. In this article, we’re gonna see how we can use the dependencies in our Activity. So, let’s begin with adding Dagger to our Activity. Below is the MainActivity. @Override protected void...

The post Dagger with Retrofit Example – Using Dependency Injection in Activity appeared first on Coding Infinite.

]]>
This is the second part of Dagger with Retrofit tutorial. In the first part, we’ve achieved the hard part of how to set up dependency injection. In this article, we’re gonna see how we can use the dependencies in our Activity.

So, let’s begin with adding Dagger to our Activity. Below is the MainActivity.

@Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       ServiceApplicationComponent component = DaggerServiceApplicationComponent.builder()
               .applicationContextModule(new ApplicationContextModule(this))
               .build()
       component.inject(this);
       initViews();
       setRecyclerViewProperties();
       carCategoriesCallback = serviceUtil.getCarCategories();
   }

The interesting part of this code is DaggerApplicationComponentBuilder. You see dagger automatically create a builder pattern for our Component class. In our builder class, we are providing a new instance of ApplicationContextModule because dagger restricted us to provide an instance of that Module which has a constructor parameter.

Dagger provide a way for the fields in your activity, fragments or services to be assigned references simply by annotating the field with an @Inject. After injecting the field dagger2 locate the singletons in the dependency graph to try to find the matching return type. Below is an example of how to @Inject annotation in the field.

@Inject
Picasso picasso;
@Inject
ServiceUtil serviceUtil;

This is how you can @inject your fields into activity at the top. Now, lets’ move how you can enqueue your network request with the retrofit.

carCategoriesCallback.enqueue(this);

In enqueue function this represents callback, and for that our MainActivity has to implement callback. One more thing by doing enqueue you are using synchronous call. The synchronous method provides the ability to use return value directly because the operation blocks everything else during the network request.

Note: For non-blocking UI you have to handle the request execution in the separate thread.

Below is the code for retrofit callback interface methods.

@Override
public void onResponse(@NonNull Call<CarCategoryResponse> call, @NonNull Response<CarCategoryResponse> response) {
    if (mainProgressBar.getVisibility() == View.VISIBLE)
        mainProgressBar.setVisibility(View.GONE);
    if (response.isSuccessful()) {
        if (response.body().getCarCategories() != null && response.body().getCarCategories().size() > 0) {
            this.carCategories.addAll(response.body().getCarCategories());
            carCategoryAdapter.notifyDataSetChanged();
        } else 
            Toast.makeText(this, "No data found!", Toast.LENGTH_SHORT).show();        
    } else 
        Toast.makeText(this, "Communication error internet not connect!", Toast.LENGTH_SHORT).show();    
}

@Override
public void onFailure(@NonNull Call<CarCategoryResponse> call, @NonNull Throwable t) {
    if (mainProgressBar.getVisibility() == View.VISIBLE)
        mainProgressBar.setVisibility(View.GONE);
    Toast.makeText(this, "Communication error internet not connect!", Toast.LENGTH_SHORT).show();
}

If the call succeeds the callback will come into the onResponse method. If any error occurs in the request callback will go into the onFailure method. Now in the onResponse method, we need to add data in the  RecyclerView Adapter.

RecyclerViewAdapter

public class CarCategoryAdapter extends RecyclerView.Adapter<CarCategoryViewHolder> {

    private List<CarCategoryResponse.CarCategory> carCategories;
    private final LayoutInflater layoutInflater;

    public CarCategoryAdapter(List<CarCategoryResponse.CarCategory> carCategories, final Context context) {
        this.carCategories = carCategories;
        this.layoutInflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public CarCategoryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new CarCategoryViewHolder(layoutInflater.inflate(R.layout.list_item_single_view, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull CarCategoryViewHolder holder, int position) {
        CarCategoryResponse.CarCategory carCategory = carCategories.get(position);
        holder.getBase_fare().setText(String.valueOf("Rs ").concat(carCategory.getBaseFare()));
        holder.getCar_category().setText(carCategory.getName());
        holder.getRate_per_km().setText(String.valueOf("Rs ").concat(carCategory.getRatePerKm()));
        holder.getRate_per_min().setText(String.valueOf("Rs ").concat(carCategory.getRatePerMin()));
    }

    @Override
    public int getItemCount() {
        return carCategories.size();
    }
}

The Adapter provides a binding for an app specific data set to views that are displayed in a RecyclerView. In the onBindViewHolderwe update the contents of itemView to reflect the item at the given position.

RecyclerViewHolder

public class CarCategoryViewHolder extends RecyclerView.ViewHolder {

    private TextView car_category, rate_per_min, rate_per_km, base_fare;

    public CarCategoryViewHolder(View itemView) {
        super(itemView);
        car_category = itemView.findViewById(R.id.car_category);
        rate_per_min = itemView.findViewById(R.id.rate_per_min);
        rate_per_km = itemView.findViewById(R.id.rate_per_km);
        base_fare = itemView.findViewById(R.id.base_fare);
    }

    public TextView getCar_category() {
        return car_category;
    }

    public TextView getRate_per_min() {
        return rate_per_min;
    }

    public TextView getRate_per_km() {
        return rate_per_km;
    }

    public TextView getBase_fare() {
        return base_fare;
    }
}

The ViewHolder describes an itemView and metadata about its place within a RecyclerView. In CarCategoryViewHolder we’re simply finding the views and set it to its relevant field.

CarCategoryResponse

public class CarCategoryResponse {

    @SerializedName("car_categories")
    @Expose
    private List<CarCategory> carCategories;

    public List<CarCategory> getCarCategories() {
        return carCategories;
    }

    public class CarCategory {

        @SerializedName("id")
        @Expose
        private int id;
        @SerializedName("name")
        @Expose
        private String name;
        @SerializedName("rate_per_km")
        @Expose
        private String ratePerKm;
        @SerializedName("rate_per_min")
        @Expose
        private String ratePerMin;
        @SerializedName("base_fare")
        @Expose
        private String baseFare;

        @Override
        public String toString() {
            return "CarCategory{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", ratePerKm=" + ratePerKm +
                    ", ratePerMin='" + ratePerMin + '\'' +
                    ", baseFare='" + baseFare + '\'' +
                    '}';
        }

        public int getId() {
            return id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getRatePerKm() {
            return ratePerKm;
        }

        public String getRatePerMin() {
            return ratePerMin;
        }

        public String getBaseFare() {
            return baseFare;
        }
    }
}

Alright, this was the complete example of a dagger with the retrofit. If you guys want to learn how to make a network call with retrofit and Rx-Java check out the next article.

I hope this blog gives you a good understanding of the dagger and retrofit. If you’ve any queries regarding this please do comment below.

Thank you for being here and keep reading…

 

The post Dagger with Retrofit Example – Using Dependency Injection in Activity appeared first on Coding Infinite.

]]>
Dagger with Retrofit Example – Set up Dependency Injection https://codinginfinite.com/dagger-retrofit-example-dependency-injection/ Mon, 09 Apr 2018 12:56:44 +0000 http://codinginfinite.com/?p=51  Today, we’re going to learn about Dagger 2. Dagger 2, first of all, is really an annotation processor or just the code generator. Many of the people seem to think that Dagger 2 is how you do dependency injection, actually, it’s not. It is just a boilerplate code generator and dependency injection is something...

The post Dagger with Retrofit Example – Set up Dependency Injection appeared first on Coding Infinite.

]]>

Today, we’re going to learn about Dagger 2. Dagger 2, first of all, is really an annotation processor or just the code generator. Many of the people seem to think that Dagger 2 is how you do dependency injection, actually, it’s not. It is just a boilerplate code generator and dependency injection is something that you code yourself.

Dagger use these following annotations.

  1. @Module and @Provide: Module classes are basically there for providing an object which can be injected in future.
  2. @Component: Component is an interface and knows everything about object creation. Every object we want to use delivered by the component in some way.
  3. @Inject: Inject can be used on a constructor, object and on a field.
  4. @Qualifier: A Qualifier is an annotation tells you the difference between the two objects.

So, without further ado, we are going to start our example in which we learn how to work with Dagger2. In this example, we simply hit a URL and download some JSON text and display them into RecyclerView.

Android App Setup

For the libraries, we are using a sort of standard libraries. Below is the app level build.gradle file.

apply plugin: 'com.android.application'
apply plugin: 'com.jakewharton.butterknife'

android {
    compileSdkVersion 27
    buildToolsVersion "27.0.3"
    defaultConfig {
        applicationId "Change with your project name"
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    } // For to enable java8
}

ext {
    supportVersion = '27.1.0'
    daggerVersion = '2.13'
    retrofitVersion = '2.3.0'
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    // Dagger dependencies
    implementation "com.google.dagger:dagger-android:$daggerVersion"
    implementation "com.google.dagger:dagger:$daggerVersion"
    implementation "com.google.dagger:dagger-android-support:$daggerVersion"
    annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
    annotationProcessor "com.google.dagger:dagger-android-processor:$daggerVersion"

    // Timber dependency
    implementation'com.jakewharton.timber:timber:4.6.0'

    // Retrofit dependencies
    implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
    implementation "com.squareup.retrofit2:converter-gson:$retrofitVersion"

    // OkHttp3 dependencies
    implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
    implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'

    // Picasso dependency
    implementation 'com.squareup.picasso:picasso:2.5.2'

    // Android support dependencies
    implementation "com.android.support:appcompat-v7:$supportVersion"
    implementation "com.android.support:recyclerview-v7:$supportVersion"
    implementation "com.android.support:cardview-v7:$supportVersion"
    implementation "com.android.support:design:$supportVersion"
    implementation "com.android.support:support-v4:$supportVersion"
    implementation "com.android.support:animated-vector-drawable:$supportVersion"

    // Ui constraint dependency
    implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta6'

    testImplementation 'junit:junit:4.12'
}

All the dependencies which we require through the app are written in components.

Main App level Component.

@CustomApplicationScope
@Component(modules = {ServiceUtilModule.class, PicassoModule.class})
public interface ServiceApplicationComponent {

    Picasso getPicasso();

    ServiceUtil getServiceUtil();  
}

We are telling our component in order to generate these instances you need ServiceUtilModule.class and PicasoModule.class.

You see all the internal stuff should be kept internally. We don’t want that stuff flying off the sunset. We don’t want people to use our dependency graph to know about the how do we make Picasso and ServiceUtil Object. It should be automated and under the hood.

Now we need to provide Picasso and ServiceUtil instance where does he get that from because dagger can’t magically generate all this stuff. This is where Module comes to play.

One last thing you guys noticed in code is a CustomApplicationScope annotation. Scope means any instance we got of that object should be a single instance. This is what a scope does.

CustomApplicationScope

@Scope
@Retention(RetentionPolicy.CLASS)
public @interface CustomApplicationScope {
}

Now in which object, class or method you include @CustomApplicationScope that means you need a single instance of that object throughout the app.

ServiceUtilModule

@Module(includes = NetworkModule.class)
public class ServiceUtilModule {

    private static final String BASE_URL = "https://www.frisbeego.com/secure/index.php/";

    @Provides
    @CustomApplicationScope
    ServiceUtil getServiceUtil(Retrofit retrofit) {   // How does the retrofit object came as a parameter to this function.You see @Provides annotation on every method this means it providing that object.
        return retrofit.create(ServiceUtil.class);
    }

    @Provides
    @CustomApplicationScope
    Gson getGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        return gsonBuilder.create();
    }

    @Provides
    @CustomApplicationScope
    Retrofit getRetrofit(OkHttpClient okHttpClient, Gson gson) {
        return new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(BASE_URL)
                .client(okHttpClient)
                .build();
    }
}

Now our ServiceUtilModule class also depends on NetworkModule and for that we need NetworkModule.

NetworkModule

@Module(includes = ApplicationContextModule.class)
public class NetworkModule {

    @Provides
    @CustomApplicationScope
    HttpLoggingInterceptor getInterceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(message -> Timber.i(message));
        interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
        return interceptor;
    }

    @Provides
    @CustomApplicationScope
    Cache getCache(File cacheFile) {
        return new Cache(cacheFile, 10 * 1000 * 1000);  // 10 MiB cache
    }

    @Provides
    @CustomApplicationScope
    File getFile(@ApplicationContextQualifier Context context) {
        File file = new File(context.getFilesDir(), "cache_dir");
        if (!file.exists())
            file.mkdirs();
        return file;
    }

    @Provides
    @CustomApplicationScope
    OkHttpClient getOkHttpClient(HttpLoggingInterceptor interceptor, Cache cache) {
        return new OkHttpClient.Builder()
                .writeTimeout(15, TimeUnit.SECONDS)
                .readTimeout(15, TimeUnit.SECONDS)
                .connectTimeout(15, TimeUnit.SECONDS)
                .cache(cache)
                .addInterceptor(interceptor)
                .build();
    }
}

NetworkModule also depends on ApplicationContextModule class. Now you guys are getting the clear picture that our graph of dependencies are getting bigger and bigger and we need to structure it.

ApplicationContextModule

@Module
public class ApplicationContextModule {

    private final Context context;

    public ApplicationContextModule(Context context) {
        this.context = context.getApplicationContext();
    }

    @Provides
    @CustomApplicationScope
    @ApplicationContextQualifier
    Context getContext() {
        return context;
    }
}

You see in here we have a new annotation called @AppilcationContextQualifier. Now why we need @Qualifer here because in an android app there are two types of context that’s why we need to specify which context we are providing.

ApplicationContextQualifier

@Qualifier
public @interface ApplicationContextQualifier {

}

Here’s everything is done for ServiceUtilModule.

PicassoModule

@Module(includes = NetworkModule.class)
public class PicassoModule {

    @Provides
    @CustomApplicationScope
    Picasso getPicasso(@ApplicationContextQualifier Context context, OkHttp3Downloader okHttp3Downloader) {
        return new Picasso.Builder(context)
                .downloader(okHttp3Downloader)
                .build();
    }

    @Provides
    @CustomApplicationScope
    OkHttp3Downloader getOkHttp3Downloader(OkHttpClient okHttpClient) {
        return new OkHttp3Downloader(okHttpClient);
    }
}

You see in here PicassoModule also depends on NetworkModule. Here we are going to reuse our NetworkModule for PicassoModule which we previously use in ServiceUtilModule.

This was all for the dependency injection. Let’s clap your hand with joy because you guys have learned something which people uses in the huge application.

Alright, guys, I’m going to end this blog here, for further reading see my next blog.

I hope this blog gives you a good understanding of Dagger. If you’ve any queries regarding this post please do comment below.

Thank you for being here and keep reading…

Next Part

The post Dagger with Retrofit Example – Set up Dependency Injection appeared first on Coding Infinite.

]]>