JetPack - Coding Infinite https://codinginfinite.com/jetpack/ Your infinite Coding Solutions Sun, 23 Jun 2019 13:04:55 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.3 https://codinginfinite.com/wp-content/uploads/2018/07/CODING-INFINITE-FAVICON.png JetPack - Coding Infinite https://codinginfinite.com/jetpack/ 32 32 Android Room Persistence With LiveData https://codinginfinite.com/android-room-persistence-livedata-example/ https://codinginfinite.com/android-room-persistence-livedata-example/#comments Sun, 29 Jul 2018 18:59:51 +0000 https://codinginfinite.com/?p=825 Previously in our Room persistence article, we’ve discussed what are the basics of Room and how to simply work with it. Also, we’ve made a book library app using the Room persistence basic components. (If you haven’t read the previous article, I highly recommend you read it before proceeding it.) In this article, we’re gonna...

The post Android Room Persistence With LiveData appeared first on Coding Infinite.

]]>
Previously in our Room persistence article, we’ve discussed what are the basics of Room and how to simply work with it. Also, we’ve made a book library app using the Room persistence basic components. (If you haven’t read the previous article, I highly recommend you read it before proceeding it.)

In this article, we’re gonna see how we can use the Android Room Persistence library with LiveData. The Room library is built to work well with LiveData. The Room can return LiveData objects which are automatically notified when the database data changes and how their data is loaded in the Background Thread. This makes it easy to update the UI when database updates.

To start using the Room and LiveData together add the dependency in the build. gradle file.

// Room dependency
implementation 'android.arch.persistence.room:runtime:1.1.1'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'

// LiveData dependency
implementation 'android.arch.lifecycle:viewmodel:1.1.1'
annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'

To understand the concept of Room with LiveData, I’m going to use our previous article example. So, in this article, I’m not gonna tell you how to create Entity, Dao, and Database class for Room database. To see how to create basic components of Room see my previous article.

In our book library app, we define the BookDao class like below.

@Dao
interface BookDao : BaseDao<BookItem> {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(book: Book): Long

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

    @Query("SELECT * from books WHERE book_id = :bookId")
    fun getBookWithId(bookId : Int) : Book?

}

By using the above approach our app working is fine. We can store books in the database, we can retrieve all books, and we can successfully delete the books from the database.

Problem:

But we have a problem here let’s say, I want to read all the books from the database and after that whenever the changes happen in books column, I want to update my UI.

If I use the above solution then we’ll face these problems.

  1. Methods are synchronous in BookDao. So, we need to manually call the functions from the Background Thread. Because, if we call these methods from Main Thread, then the IllegalStateException will occur.
  2. Every time whenever the data changes in the database, again we need to call the getAllBooks method for updated books.
  3. After requesting the books from the database we have to listen to the result in the Main Thread.

Solution:

Like I said earlier, Room library is built to work with LiveData. So, the only thing we need to change is our BookDao methods return type. Now the BookDao class will look like this.

@Dao
interface BookDao : BaseDao<BookItem> {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(book: Book): Long

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

    @Query("SELECT * from books WHERE book_id = :bookId")
    fun getBookWithId(bookId : Int) : LiveData<Book>

}

Now our MainActivity will look like this.

class MainActivity : AppCompatActivity() {

    @Inject   // Getting instance from Dependency injection
    lateinit var BookDao bookDao
    private val allBooks : MutableList<BookItem> = ListView()

    override fun onCreate(savedInstanceState: Bundle?) {
        .......
        .......
        bookDao.allBooks()
                .observe(this, object : Observer<List<BookItem>> {
                    override fun onChanged(books: List<BookItem>?) {
                        if(allBooks.isNotEmpty()) 
                           allBooks.clear
                        this.allBooks.addAll(books)
                        showDataInListView(allBooks)
                    }
                })
    }
}

Please pay attention here, first by using the LiveData we don’t need to call database methods from the Background Thread and listen to the result in Main Thread because LiveData does all of this for us under the hood. Second, whenever the changes happen in the database, we don’t need to call every time for an updated result because the onChanged method will be triggered automatically with the updated value. And in third, the LiveData Observer is bound to this Activity lifecycle. It automatically removes the emission if the activity is destroyed.

Another Example

So let’s say if I want to get the BookItem by Id that doesn’t exist in the database. So in that case, LiveData simply return null. To solve this null-ability when the data is missing you can either work with Optional or you can work with Flowable to return List of data. By adding the Optional our BookDao class will look like this.

@Dao
abstract class BookDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun insert(book: BookItem): Long

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

    @Query("SELECT * from books WHERE book_id = :bookId")
    abstract fun getBookWithId(bookId: Int): LiveData<Optional<BookItem>>
}

Now, If I’m trying to read the non-existing BookItem from the database it will return the Optional. empty instead of null. If you want to work with Flowable or other RxJava observers you can check out my article on RxJava2 with Room.

Protip:

Now instead of directly observing the data from the database. We can implement a ViewModel class to fetch the data from the database and after that our UI only needs to observe that LiveData.

Below is the BookViewModel class.

class BookViewModel : ViewModel() {

    @Inject
    lateinit var bookDao : BookDao 

    val bookItems: LiveData<List<BookItem>> = bookDao.allBooks()
}

And now the MainActivity will look like this.

class LiveDataSwitchMapExample : AppCompatActivity() {

    private val bookItems: MutableList<BookItem> = ArrayList()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.live_data_swicth_map_example)
        val bookViewModel = ViewModelProviders.of(this).get(BookViewModel::class.java)
        bookViewModel.bookItems.observe(this, object : Observer<List<BookItem>> {

            override fun onChanged(t: List<BookItem>?) {
                if (bookItems.isNotEmpty())
                    bookItems.clear()
                bookItems.addAll(it!!)
            }
        })
    }
}

The MainActivity is pretty much the same but by adding the ViewModel class, but we add the transparency to our code. By transparency I mean, our UI doesn’t need to know from where the BookItems are coming from. It may be coming from Network source, it may be coming from the local database or may be coming from the Cache. You get my point, UI only needs to worry about how to show data to the user not how to fetch.

To read more about ViewModel you can check out this article on ViewModel

Another Example:

Sometime there may be a case where you need to modify the data and then propagates the result to the downstream. Let’s say we only want bookName instead of a complete BookItem object. Here comes the concept of LiveData Transformations. Below shows how we can use the LiveData Transformations in our ViewModel class.

class BookViewModel : ViewModel() {

    @Inject
    private lateinit var bookDao: BookDao

    val bookItems: LiveData<List<String>> = Transformations.map(bookDao.getAllBooks(), ::getBookName)

    private fun getBookName(books: List<BookItem>): List<String> {
        val booksName: MutableList<String> = ArrayList()
        books.forEach { booksName.add(it.bookName) }
        return booksName
    }
}

Now we’re only emitting the bookNames instead of the complete book object. For to further reading about LiveData Transformation see this article. In that article, I briefly explain how the map and switchMap transformation works.

Below is the MainActivity class.

class LiveDataSwitchMapExample : AppCompatActivity() {

    private val bookNames: MutableList<String> = ArrayList()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.live_data_swicth_map_example)
        val bookViewModel = ViewModelProviders.of(this).get(BookViewModel::class.java)
        bookViewModel.bookItems.observe(this, object : Observer<List<String>> {
            override fun onChanged(t: List<String>?) {
                if (bookNames.isNotEmpty())
                    bookNames.clear()
                bookNames.addAll(t)
                // showBookNames(bookNames)
            }
        })
    }
}

You see in our MainActivity, I’m expecting bookNames instead of complete book objects.

Alright, guys, this is my simple attempt to fetching data from the database with Room Persistence and LiveData. If you’ve any queries regarding the above post or any question about Room Persistence please do comment below.

Thank you for being here and keep reading…

The post Android Room Persistence With LiveData appeared first on Coding Infinite.

]]>
https://codinginfinite.com/android-room-persistence-livedata-example/feed/ 6
Android LiveData Transformation With Example | Map And SwicthMap https://codinginfinite.com/android-livedata-transformation-example/ https://codinginfinite.com/android-livedata-transformation-example/#comments Mon, 23 Jul 2018 23:01:13 +0000 http://codinginfinite.com/?p=804 In this article, we’re going to explore the Transformations of LiveData. Sometime there may be a case where you want to changes in the LiveData value before dispatching it to the Observer or you may need to return different LiveData based on some condition. Here comes the concept of Transformations. In the last article, we’ve...

The post Android LiveData Transformation With Example | Map And SwicthMap appeared first on Coding Infinite.

]]>
In this article, we’re going to explore the Transformations of LiveData. Sometime there may be a case where you want to changes in the LiveData value before dispatching it to the Observer or you may need to return different LiveData based on some condition. Here comes the concept of Transformations.

In the last article, we’ve discussed what are the basics of LiveData and also we look at two different example to implement LiveData.(If you haven’t read the previous article I highly recommended you to read before proceeding.)

Transformations:

Transformation basically applies a function to the values stored in the LiveData object and propagates the result to the downstream. There are currently two types of Transformations we have.

  1. Transformations.map: The map lets you apply a function to the output of LiveData and then propagates the result to the downstream.
  2. Transformations.switchMap: The swicthMap function transformation is a lot like a map but for mapping function that emits LiveData instead of values. Again switchMap functions propagate LiveData to downstream instead of single value.

Example of Transformations.map:

Let’s take a scenario where we need to show Snackbar whenever a new user added to the database. The Snackbar shows data of a custom String with username added in it.

 

You see a demo right, let’s create our ViewModel class to hold the LiveData of User.

TransformationViewModel class:
class TransformationViewModel : ViewModel() {

    private val userLiveData = MutableLiveData<User>()

    val userAddedData: LiveData<String> = Transformations.map(userLiveData, ::someFunc)

    private fun someFunc(user: User) = "New user ${user.username} added to database!"

    fun addNewUser(user: User) = apply { userLiveData.value = user }
}

There are two things noticeable here.

  • First, we are not exposing our user LiveData to publically. We have given a public function to just add the User object. By doing this we’re keeping our Immutability principle.
  • Second, for adding the map Transformations we need to provide source LiveData and function from which you need to return your custom value. You see in our case we’re returning a custom String with username add in it.

So, we create our ViewModel and LiveData with map Transformations, let’s see how we gonna use this ViewModel inside our Activity.

MainActivity:
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val viewModel = ViewModelProviders.of(this).get(TransformationViewModel::class.java)
        viewModel.userAddedData.observe(this, object : Observer<String>{
            override fun onChanged(t: String?) {
                Snackbar.make(mainActivityRootView, t!!, Snackbar.LENGTH_SHORT).show()
            }
        })
        addUserButton.setOnClickListener {
            viewModel.addNewUser(User(addNewEditText.text.toString()))
        }
    }
}

The Activity is very basic, in here we’re only observing our LiveData instance. Whenever the user object added to LiveData it automatically calls the onChanged method with the custom String.

Example of Transformations.switchMap:

Let’s take another scenario where I need to search user by username and show the result inside the RecyclerView.

You see the demo right let’s create our ViewModel class to search users with the name.

class UserRepo{
   fun searchUserWithName(name : String) : LiveData<List<User>>{
      ..... logic for search user
   }
}

class UserViewModel : ViewModel() {

    private val query = MutableLiveData<String>()
    private val userRepo = UserRepo()

    val userNameResult: LiveData<List<User>> = Transformations.map(
            query,
            ::temp
    )

    private fun temp(name: String) = userRepo.searchUserWithName(name)

    fun searchUserByName(name: String) = apply { query.value = name }
}

You see in our ViewModel class we’re getting the data from our UserRepo class. So, whenever something is searched, we’ll get users with the name, then the repository creates a new instance of LiveData and returned the list of users. And finally based on the result we display the data.

To clarify the things between map and switchMapI use map method so that, we could see what happened if we use map method instead of swicthMap when we need to return LiveData.

Problem:

Let’s say we’re looking for the username Alice. The repository is creating a new instance of that User LiveData class and after that, we display the users. After some time we need to look for the username Bob there’s the repository creates a new instance of LiveData and our UI subscribes to that LiveData. So at this moment, our UI subscribes to two instances of LiveData because we never remove the previous one. So it means whenever our repository changes the user’s data it sends two times subscription. Now, how do we solve this problem…?

Solution:

What we actually need is a mechanism that allows us to stop observing from the previous source whenever we want to observe a new one. In order to this, we would use switchMap. Under the hood, switchMap uses the MediatorLiveData that removes the initial source whenever the new source is added. In short, it does all the mechanism removing and adding a new Observer for us.

Now our ViewModel class will look like this.

class UserRepo{
   fun searchUserWithName(name  : String) : LiveData<List<User>>{
         .... logic for search user
   }
}

class UserViewModel : ViewModel() {

    private val query = MutableLiveData<String>()
    private val userRepo = UserRepo()

    val userNameResult: LiveData<List<User>> = Transformations.switchMap(
            query,
            ::temp
    )

    private fun temp(name: String) = userRepo.searchUserWithName(name)

    fun searchUserByName(name: String) = apply { query.value = name }
}

All the code remain the same instead of the switchMap method. Now here we only need our Activity class to observe this LiveData. The following shows the MainActivity class.

class MainActivity : AppCompatActivity() {

    private val userList: MutableList<User> = ArrayList()
    private lateinit var userAdapter: UserAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        userRecyclerView.layoutManager = LinearLayoutManager(this)
        userRecyclerView.setHasFixedSize(true)
        userAdapter = UserAdapter(this, userList)
        userRecyclerView.adapter = userAdapter
        val viewModel = ViewModelProviders.of(this).get(UserViewModel::class.java)
        searchUserButton.setOnClickListener { viewModel.searchUserByName(addNewEditText.text.toString()) }
        viewModel.userNameResult.observe(this, Observer {
            if (userList.isNotEmpty())
                userList.clear()
            userList.addAll(it!!)
            userAdapter.notifyDataSetChanged()
        })
    }
}

The Activity is very basic. After setting the RecyclerView properties, whenever the user clicks the button we’re calling our ViewModel class function to search the users with a username. And in the last, we simply observing the LiveData coming from our ViewModel class.

Alright, guys, I’m going to end this blog here. You can also download the complete source code of the above example.

Download Complete Code

If you’ve any queries regarding this post on Transformations or any problem with LiveData please do comment below.

Thank you for being here and keep reading…

The post Android LiveData Transformation With Example | Map And SwicthMap appeared first on Coding Infinite.

]]>
https://codinginfinite.com/android-livedata-transformation-example/feed/ 5
Android LiveData With Example https://codinginfinite.com/android-livedata-example/ https://codinginfinite.com/android-livedata-example/#comments Mon, 23 Jul 2018 22:52:40 +0000 http://codinginfinite.com/?p=787 Today I wanna tell you about a few solutions that have been developed. Solutions for problems that I think all of us as a developer have been trying to solve again and again in every project. So, let’s say that I want to perform actions in response to changes in lifecycle status of Android Component....

The post Android LiveData With Example appeared first on Coding Infinite.

]]>
Today I wanna tell you about a few solutions that have been developed. Solutions for problems that I think all of us as a developer have been trying to solve again and again in every project.

So, let’s say that I want to perform actions in response to changes in lifecycle status of Android Component. Sometimes you may wanna observe certain values being changed over the configuration change. We all faced these problems somewhere down the road, trying a lot of different patterns MVP, MVVM, and others. But to implement these patterns is also a big problem for beginners.

So, the good news is with the Android Architecture Component and more precisely with the lifecycle LiveData and ViewModel, we can easily overcome these problems.

In my previous article, I briefly explain what is ViewModel and how we can use it in our app with the example. So go ahead and check it out.

LiveData:

LiveData is an observable data holder. It is also a lifecycle aware. By lifecycle aware I mean, it can only be observed in the context of a lifecycle, more precisely in the context of an Activity or Fragment lifecycle. By passing the reference of an Activity or Fragment, it can understand whether your UI onScreen, offScreen or Destroyed. After passing the UI object to LiveData, whenever the data in the live data changes. It notifies the lifecycle owner with updates and then the UI redraw itself with updates.

Advantages of LiveData:

  1. No memory leaks: Observers are bound to Lifecycle objects and clean up after themselves when their associated life cycle destroyed.
  2. No crashes due to stopped activities: It means if an activity is in the back stack, then it doesn’t receive any LiveData stream.
  3. Always up to date: It receives the latest data upon becoming active again.
  4. No more manual life-cycling handle: Observers just observe relevant data and don’t stop or resume observation. LiveData manages all of this under the hood.
  5. Ensures your UI matches the data state: LiveData notifies the observer object whenever lifecycle state changes. Instead of updating the UI every-time when the data changes, your observer can update the UI every time there’s a change.
  6. Proper configuration changes: If an observer is recreated due to a configuration change, like device rotation, it immediately receives the latest available data.
  7. Sharing resources: You can extend LiveData object using the singleton pattern to wrap system services so that they can be shared in your app.

Android App Setup:

So, enough of this theory lets see how we can use this in our Android app. For to use LiveData add the following dependency in the build.gradle file.

implementation "android.arch.lifecycle:extensions:$current_version"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0"

Creating a LiveData:

For creating an instance of LiveData to hold a certain type of data. It usually creates inside the ViewModel class. Now I’m going to use my previous article example where we make the Color Changer app. For color changer app we first need a ViewModel to hold our current background color.

You see the demo right. Let’s create a LiveData inside ViewModel.

class ColorChangerViewModel : ViewModel() {

    val colorResource = MutableLiveData<Int>()

    init {
        colorResource.value = 0xfff
    }
}

If you remembered from the previous article the colorResource is the Int value. In here it is MutableLiveData.

Note: Make sure to store LiveData objects that update the UI in ViewModel objects, as opposed to an activity or fragment. You see our UI controllers are only responsible to store data not for holding data state. By UI controllers mean our ViewModel and LiveData class.

What is MutableLiveData:

MutableLiveData is also a LiveData. Internally MutableLiveData extends LiveData class and exposes the two methods publically which is setValue and getValue. With setValueyou can set the new value and after that, it calls all the active observers with new modified value. And last, with getValue, you can get the recent value stored inside the LiveData instance.

Ways of Setting Data:

There are currently two ways of setting the value inside the LiveData instance. The first one we’ve seen which is setValue and second one is postValue. The setValue method is used to set data from Main Thread. If the code executed inside the Worker Thread or Background Thread you can use the postValue method.

So, we create our ViewModel and LiveData let’s see how we gonna use this ViewModel inside our activity.

MainActivity:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val colorChangerViewModel = ViewModelProviders.of(this).get(ColorChangerViewModel::class.java)
        colorChangerViewModel.colorResource.observe(this, object: Observer<Int> {
            override fun onChanged(t: Int?) {
                mainActivityRootView.setBackgroundColor(t!!)
            }
        })
        changeColorButton.setOnClickListener {
            colorChangerViewModel.colorResource.value = generateRandomColor()
        }
    }

    private fun generateRandomColor(): Int {
        val rnd = Random()
        return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))
    }
}

 

In most cases, the onCreate method is the right place to begin observing a LiveData object. To start observing the data you call the observe method on LiveData instance. For the observe method first argument you pass the UI in this the activity and the second argument Observer which is just a callback.

When setValue is called the onChanged is immediately invoked providing the most recent value stored inside the colorResource. In onChanged you will call the code to update the UI in our case updating the background color.

Like I said earlier you can change LiveData value with setValue or postValue method. In our case, we’re using setValue because we’re updating the data from Main Thread. When we update the data value by calling setValue or postValue, it notifies all the active Observers immediately.

Another Example:

Let’s move a step up and create a real-life problem example. In this example, we’re going to make a timer app. When the app opens it shows the current time and after every 2 seconds time will be updated.

So you see the demo right. Now let’s create our ViewModel class for Timer app.

TimeChangerViewModel:
class TimeChangerViewModel : ViewModel() {
    val timerValue = MutableLiveData<Long>()
    
    init {
        timerValue.value = System.currentTimeMillis()
        startTimer()
    }

    private fun startTimer() {
        disposable = Observable.interval(2, 2, TimeUnit.SECONDS)
                .subscribe({
                    timerValue.postValue(System.currentTimeMillis())
                }, Throwable::printStackTrace)
    }
}

You see when TimeChangerViewModel initializes we start the timer with the interval of 2 seconds. For creating a time interval I use RxJava2 library. One thing noticeable here that I’m using the postValue method because the interval method subscribes the value in the Background Thread. 

MainActivity:
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val timeChangerViewModel = ViewModelProviders.of(this).get(TimeChangerViewModel::class.java)
        val calendar = Calendar.getInstance()
        timeChangerViewModel.timerValue.observe(this, Observer<Long> { t ->
            Log.e("TimeValue", t.toString())
            calendar?.timeInMillis = t!!
            timTextView.text = calendar.time.toString()
        })
    }
}

The activity is very basic after setting the Observer to LiveData when the timerValue inside the TimeChangerViewModel change it immediately called the onChanged with the new time value. The LiveData stop posting the values if our app is in the back stack. I tested the app by adding the Logcat.

Note: When we receive the time value inside the Observer, it gives us data in the Main Thread. Even though our data posting the value in the Background Thread. It automatically converts it for us under the hood.

Stop Listening LiveData:

At some point, you may need to stop observing the data. You can simply remove the observer with the given lifecycle.

someViewModel.liveData.removeObservers(lifecycle : this)

 

That’s it! I hope you like the post. If you’ve any queries regarding this please do comment below.

Download Complete Code

You can also check my next post on LiveData. In that post, I explain how to use map, swicthMap, and MediatorLiveData class for our own custom Transformation

Thank you for being here and keep reading…

LiveData Transformation

The post Android LiveData With Example appeared first on Coding Infinite.

]]>
https://codinginfinite.com/android-livedata-example/feed/ 2
Why Developer Needs To More Concern For Background Process When Targeting Android P https://codinginfinite.com/android-p-developer-battery-preview/ https://codinginfinite.com/android-p-developer-battery-preview/#comments Fri, 20 Jul 2018 15:32:06 +0000 http://codinginfinite.com/?p=781 We all want good power efficiency right..? Like batteries that last a long time. We want to build really cool apps and we do not want the user to manage between these things. Like do I want to build cool apps, or do I want power efficiency. It’s terrifically difficult to make that choice. So,...

The post Why Developer Needs To More Concern For Background Process When Targeting Android P appeared first on Coding Infinite.

]]>
We all want good power efficiency right..? Like batteries that last a long time. We want to build really cool apps and we do not want the user to manage between these things. Like do I want to build cool apps, or do I want power efficiency. It’s terrifically difficult to make that choice. So, as a developer, you should have to closely manage how your apps behave on a user’s device running Android P version.

Android engineers working very hard to optimize the battery performance. This year in I/O 2018 Google introduced Adaptive Battery feature in Android P.

Adaptive Battery In Android P:

Google engineers co-developed this feature in Android P called Adaptive Battery. It intelligently aligns power consumption with app usage. Apps can still run in the background when they need to, and the user doesn’t need to micromanage the app. So, the adaptive battery uses the concepts of App Standby Buckets.

App Standby Buckets:

App standby buckets are for the app which runs in the background. There is four type of buckets which, I’m going to explain below. Each bucket has different limits on background activity. Jobs, Alarms, Firebase Cloud Messaging, and Network are all restricted in Android P, depending on which bucket the app is in. Every app on the device is assigned to one of these buckets.

  1. Active Bucket: Apps in the active buckets have no background restrictions.
  2. Working Set Bucket: The Working set has some restrictions on Jobs and Alarms.
  3. Frequent Bucket: The Frequent has restrictions on Jobs, Alarms and Firebase Messaging with high priority. In the frequent bucket, messages will be treated as the normal priority, so that they batch together with other messages to save battery.
  4. Rare Bucket: Apps in the Rare buckets will have the most restrictions. The rare apps cannot use the Alarms, Jobs, Firebase Messaging and Network also.

Note: One thing to remember is that once this device is plugged into power, all of the restrictions are lifted.

Apps Standby Buckets Example:

Let’s say currently, I’m using the Instagram app. The Instagram app is going to be in the Active Bucket. But in a few days time Adaptive Battery is going to automatically determine that I’m likely not to be using this app and put it into the Rare Bucket. So, it is not necessary for consuming resource like a battery.

Standby Buckets adb Commands:

There are adb commands that you can use to test your app in each bucket to make sure that it performs as expected. If you’re not sure how to work with adb or how to enable adb to go and check out this link. The following shows the adb commands.

adb shell dumpsys battery unplug
adb shell am get-standby-bucket <package-name>
   10 ACTIVE   // bucket value
   20 WORKING_SET
   30 FREQUENT
   40 RARE
// set bucket value
adb shell am set-standby-bucket <package-name> <bucket_value>
adb shell dumpsys battery reset

Machine Learning Model:

The Adaptive Battery use the machine learning model to determine which app will go into which bucket based on their usage. The model is built by Android and DeepMind to predict which app goes into which bucket. The model itself capture the nuance of how the user behaves with their apps. It is used to predict their probability that an app will be opened in a given interval. Now, all of this is happening on the device using Tensorflow. Google engineers said in an I/O presentation.

We are doing this machine learning on a single device. So, we have to be very careful that we’re not spending more power than we’re saving.

Example Of Machine Learning Model:

If I use an app at 8’o clock every morning, then I probably quite likely to open it tomorrow 8’o clock as well. But if you only use a certain app on weekend like a game or a travel app, then you’re probably not going to open it on Monday morning.

Now the model is able to capture this nuance. The model looks at the user’s behavior and outputs a probability of when the user next going to open a particular app.

Fairness & Privacy:

There is no favoritism of one app over another. If you use particular app exactly the same way that you use a different app, then the model will output the same predictions and they will be assigned to the same buckets. It’s privacy-sensitive there’s no personal identification information used by the model. All information is removed before the model is trained.

Background Restrictions For App:

If a user decides to restrict your app from settings then there are few things to know for a developer.

  • Background Jobs, Alarms, Services & Network access is not available to those in the backgrounds.
  • The location will not be delivered.
  • If an application is in the background and restricted, it won’t be able to use foreground services.

There are adb commands that you can test to put your app into a restricted state.

// To apply background restrictions.
adb shell appops set <package-name>

// To remove background restrictions.
add shell appops set <package-name>

 

Best Practices:

  • If you wanna think about doing anything in the background, then WorkManager is the approach.
  • If you think something that is really important and must happen now, of course, you can have the ability to use foreground service. But if you use foreground service you have to tell the user, why you are using it. And you need to justify yourself why you think it is important.
  • So, if none of the above works, think about actually doing the work when the app is launched and being active by the user.

If you like what you read gives it a thumbs up and keep reading.

The post Why Developer Needs To More Concern For Background Process When Targeting Android P appeared first on Coding Infinite.

]]>
https://codinginfinite.com/android-p-developer-battery-preview/feed/ 1
Chaining Worker With Android WorkManager https://codinginfinite.com/chaining-wrokers-workmanager/ https://codinginfinite.com/chaining-wrokers-workmanager/#comments Thu, 19 Jul 2018 16:11:09 +0000 http://codinginfinite.com/?p=776 Chaining the Worker is the most attractive features of WorkManager. With the work manager, we can easily chain multiple workers together and the run workers in a particular order. I’ve written some pretty good articles on WorkManager before. In these articles, I briefly explain how to use the work manager, setting input and output data,...

The post Chaining Worker With Android WorkManager appeared first on Coding Infinite.

]]>
Chaining the Worker is the most attractive features of WorkManager. With the work manager, we can easily chain multiple workers together and the run workers in a particular order.

I’ve written some pretty good articles on WorkManager before. In these articles, I briefly explain how to use the work manager, setting input and output data, and setting data with InputMerger.

When to Chain Works:

  1. Suppose your app wants to run three workers parallel and when these workers complete its execution you want to run another worker.
  2. You want to compress some files before sending it to the server. For this scenario you want to execute compress worker first and then only you need to send it to the server.

Types of Chaining:

  1. Sequential Chaining: It is a simple chaining in which first task start execution then only the second task executes. With sequential chaining, the output data from one worker become input to the next worker.
  2. Parallel Chaining: In this type of chaining we run some parallel task. When this parallel task completes its execution then only the next one start execution. In parallel chaining, the output data from these parallel workers will fall into as input in the next worker.
  3. Multiple Parallel Chaining: WorkManager gives us the ability to executes multiple chains in parallel. With WorkContinuation class we can combine multiple chains and run them in parallel sequence.

Android App Setup:

So, enough of the chaining theory lets see how we can use them in our Android app. First, add the dependency to the build. gradle file.

implementation 'android.arch.work:work-runtime:$current_version'

Now we add the dependency lets see how to use chaining.

1. Sequential Chaining:

For sequential chaining, we can say that, we want to execute the first task and when it completes then only execute the next task. Below shows the example of sequential chaining.

WorkManager.getInstance()
           .beginWith(firstWorker)
           .then(secondWorker)
           .enqueue()
1.1 beginWith:

The beginWith methods indicate the start of the chain. The beginWith method returns WorkContinuation instance.

1.2 then:

With WorkContinuation instance we can add as many then as we want. It’s like the stream of worker executing in the given order.

Note: If the firstWorker failed due to some reason, then the chain won’t run all the next workers in the chain. So in our case, if firstWorker failed then the secondWorker will not run.

For to understand the data flow between these workers see my previous article in which I briefly explain how we can send data from one worker to another worker.

2. Parallel Chaining:

Like I said before with parallel chaining you can execute multiple workers simultaneously and when these workers complete its execution then the next worker start its execution. Below shows the example of parallel chaining.

WorkManager
          .getInstance()
          .beginWith(firstWork,secondWork,thirdWork)
          .then(fourthWorker)
          .then(fifthWorker)
          .enqueue()
2.1 beginWith:

In here beginWith method starts execution of three workers in parallel. When these workers complete its execution then only the fourth worker starts its execution and then the fifth worker.

2.2 then:

Like I said above the then method will start if the previous worker completes its execution.

The same reason applies here if some worker fails due to some error then the next worker will not starts. In parallel chaining, if the keys are the same for input and output then the better approach is to use InputMerger, instead of simple override data.

For to understand data flow between the parallel chaining, I wrote a pretty good article on InputMerger. In this article, I briefly explain why we use InputMerger instead of simple override data inputs.

3. Multiple Parallel Chaining:

You may want to run some parallel workers with chaining. Let’s say you have three large files and before sending them to the server you want to compress them as parallel. And when individual worker chain completes the compressing then only send it to the server. For these types of work chaining, we can use the combine method inside WorkContinuation class. Let’s see an example of how we can use the above scenario with work continuation.

val workManager: WorkManager = WorkManager.getInstance()
        val chain1 = workManager
                .beginWith(firstCompressFileWorker)
                .then(uploadFileWorker)
        val chain2 = workManager
                .beginWith(secondCompressFileWorker)
                .then(uploadFileWorker)
        val chain3 = workManager
                .beginWith(thirdCompressFileWorker)
                .then(uploadFileWorker)
        WorkContinuation.combine(chain1,chain2,chain3)
                .enqueue()

All of these chain workers will execute in parallel when enqueueing the workers. One thing noticeable here that upload file worker will not run before compress file worker.

Now there are a lot of ways of combining the workers and chaining them with parallel and sequential. With your own need, you can easily define the dependencies of the worker or execute them in parallel.

That’s it, this is my demonstration about how to chain your tasks with the work manager and execute them in parallel. If you’ve any queries regarding this post or about work manager please do comment below.

Thank you for being here and keep reading…

The post Chaining Worker With Android WorkManager appeared first on Coding Infinite.

]]>
https://codinginfinite.com/chaining-wrokers-workmanager/feed/ 5
Android Room Persistent And RxJava2 https://codinginfinite.com/android-room-persistent-rxjava/ https://codinginfinite.com/android-room-persistent-rxjava/#comments Thu, 19 Jul 2018 00:47:26 +0000 http://codinginfinite.com/?p=764 We all want to make our app reactive, less boilerplate code, the power of asynchronous and observable queries. The good news is Room library supports async queries which return LiveData or RxJava2 observable types. The LiveData and Observables allow you to get an automatic update whenever the data changes. Now let’s say we need to read all...

The post Android Room Persistent And RxJava2 appeared first on Coding Infinite.

]]>
We all want to make our app reactive, less boilerplate code, the power of asynchronous and observable queries. The good news is Room library supports async queries which return LiveData or RxJava2 observable types. The LiveData and Observables allow you to get an automatic update whenever the data changes.

Now let’s say we need to read all the Employes from our local database. To get employees from the database, we could write the following query in DAO class like this.

@Query(“SELECT * FROM employee”)
fun getAllEmployes() : List<Employe>

 

This query has three disadvantages:

  1. It is a blocking synchronous call.
  2. We need to manually call this query from a Background Thread which is a hard process and listen back in Main Thread.
  3. We need to manually call this method every time when our employee list modified.

So, like I said earlier Room provide asynchronous queries with the help of RxJava Maybe, Single, and Flowable objects.

To start using Room with RxJava2, add the following dependency in the build. gradle file.

// RxJava with Room
implementation “android.arch.persistence.room:rxjava2:$current_version”

 

Note: By the way, I wrote a pretty good article on how to work with Room Persistence go and check it out.

 

Flowable

So, we’re going to use our previous example of reading all employees from the database. In DAO we specify for the method output type Flowable.

@Query("SELECT * FROM employee")
fun getAllEmployees() : Flowable<List<Employee>>

Subscribe and get the data.

roomDb.employeeDao().getAll()
       .observeOn(AndroidSchedulers.mainThread())
       .subscribe(object : Consumer<List<Employee>>()
           @Override
           public void accept(List<Employee> employees){
                 // showListOfEmployess(employees);
           }
       })

The subscribeOn in the case of Flowable will not be needed. The query of the database will not be executed in the UI Thread. But in order to read the stream in the UI, we use observeOn with Main Thread. Now with any data modify in the database, we will receive the latest data in the accept method. Most important we don’t need to call again each time for changes.

Let’s take another example where we need to compose only one record. In this example, we’re also returning the Flowable.

@Query("SELECT * FROM employee WHERE id = :id")
fun getEmployeeById(long id) : Flowable<Employee>

Subscribe and get the data.

roomDb.employeeDao().getById(employeeId)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Consumer<Employee>() {
       @Override
       public void accept(Employee employee) {
            // showEmployee(employee) 
    }
});

If the employee found in the database, it will come to accept method immediately after the subscription. Also whenever the employee modifies in the database, it will also come to accept.

Problem:

If there is no record, immediately after the subscription nothing will come, and even if later employee appears in the database. With this, our Flowable will not send us anything at all. Thus, it will look like it is still executing the request.

The above example can be corrected as follows.

@Query("SELECT * FROM employee WHERE id = :id")
fun getEmployeeById(long id) : Flowable<List<Employee>>

Although we only expect one record if there is no record, then at least we’ll get an empty list instead of complete silence.

Single

Consider the same example with a single record query, but using Single. In DAO we specify method output type as Single.

@Query("SELECT * FROM employee WHERE id = :id")
fun getEmployeeById(long id) : Single<Employee>

Subscribe and get the data.

roomDb.employeeDao().getById(employeeId)
       .subscribeOn(Schedulers.io())
       .observeOn(AndroidSchedulers.mainThread())
       .subscribe(new DisposableSingleObserver<Employee>() {
           @Override
           public void onSuccess(Employee employee) {
                 // showEmployee(employee)
           }
       });

If such a record exists in the database, it will come to onSuccess. After that, Single will be considered complete and on subsequent updates of this record, nothing will come again even if the record modifies.

Note: Unlike Flowable, with Single, you must use onSubscribe to specify the thread to execute the query. Otherwise, an error will occur on the onError: java.lang.IllegalStateException. Cannot access database on the Main Thread.

Problem:

If there is no such entry in the database, then we get an error EmptyResultSetException query returned an empty result. After that, Single will be considered complete, and even if such a record appears in the database, then we will not be coming again.

Maybe

Consider the same example with a single record query, but using Maybe. Once we call subscribe method on Maybe it is considered completes. In DAO we specify method output type Maybe.

@Query("SELECT * FROM employee WHERE id = :id")
fun geEmployeetById(long id) : Maybe<Employee>

Subscribe and get the data.

roomDb.employeeDao().getById(employeeId)
       .subscribeOn(Schedulers.io())
       .observeOn(AndroidSchedulers.mainThread())
       .subscribe(new DisposableMaybeObserver<Employee>() {
           @Override
           public void onSuccess(Employee employee) {
               // showEmployee(employee)
           }
      });

You see with Maybe you also need to specify in which thread you want to execute the query and in which thread you want to observe the result. If an employee found in the database it will come to the onSuccess method. After the subscription the Maybe will be considered completes. It will never be able to listen to the modification of employee.

If there is no employee found in the database then we got onComplete.

Protip

To update the data into the database you can simply return Unit or Int because for update Room did not supports Observables. But you can wrap the method inside the Completable. Let’s see how we can update the employee.

@Update
fun updateEmployee(emp : Employee )

Call method and update the data.

Completable.fromAction {
    roomDb
       .employeeDao()
       .updateEmployee(updatedEmployee)
}.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe {
            // data updated
        }

Conclusion

Single and Maybe are suitable for one-time data retrieval. The difference between that Maybe is admitting that there may be a record. And Single is more logical if the record should be in the database if not you will get an error. Flowable is more suitable if you plan to listen to the data automatically when it changes.

That’s it! This is my demonstration about how we can efficiently use RxJava2 and Room together. I hope you guys have learned something from this post. If you have a question regarding this post please do comment below.

Thank you for being here and keep reading.

The post Android Room Persistent And RxJava2 appeared first on Coding Infinite.

]]>
https://codinginfinite.com/android-room-persistent-rxjava/feed/ 5
InputMerger and ArrayCreatingInputMerger with WorkManager https://codinginfinite.com/inputmerger-workmanager-arraycreatinginputmerger/ https://codinginfinite.com/inputmerger-workmanager-arraycreatinginputmerger/#comments Wed, 18 Jul 2018 20:20:33 +0000 http://codinginfinite.com/?p=758 In the last article, we discussed how we can set input and output data with WorkManager API. (If you haven’t read the previous article I highly recommended you to read before proceeding.)  In this article, we’re going to learn how we can convert multiple output results into one input using InputMerger. I also wrote a pretty...

The post InputMerger and ArrayCreatingInputMerger with WorkManager appeared first on Coding Infinite.

]]>
In the last article, we discussed how we can set input and output data with WorkManager API. (If you haven’t read the previous article I highly recommended you to read before proceeding.) 

In this article, we’re going to learn how we can convert multiple output results into one input using InputMerger.

I also wrote a pretty good article on how to simply work with WorkManager go and check it out.

Why do we need InputMerger…?

First, let’s see an example in which case we need the InputMerger. Let’s take the example from our previous article where two task are executed parallel and the result of these two tasks will fall into the third one.

WorkManager.getInstance()
        .beginWith(firstWorker, secondWorker)
        .then(thirdWorker)
        .enqueue()

The first and second task is performed in parallel, then the third one executed.

Let’s say the first task return such data.

val output = Data.Builder()
       .putString("keyA", "value1")
       .putInt("keyB", 1)
       .putString("keyC", "valueC")
       .build();
setOutputData(output);

And the second – such

val outputData = Data.Builder()
       .putString("keyA", "value2")
       .putInt("keyB", 2)
       .putString("keyD", "valueD")
       .build();
setOutputData(output);

Now we have the same keys, keyA and keyB are the same keys for both tasks. The case here to study which of these keys values will fall into third one – from the first task or from the second task.

Below is the result of these two workers.

Result of Worker3 ->  {keyA = value1, keyB = 1, keyC = valueC, keyD = valueD}

At first, I decided that it happened because of the first task is performed little longer than the second one, and it is logical that its values just overwrote the values from the second task when the keys match.

But then I started this sequence again and got this result.

Result of worker3 -> {keyA = value2, keyB = 2, keyC = valueC, keyD = valueD}

Now we see the values of the second task in the keys keyA and keyB. So, if the tasks are executed in parallel, then if the keys match, it is not known from which task you get the value.

Now, If the keys match, then only one value remains, what if we need all the data instead of overwriting. Here comes the concept of InputMerger with ArrayCreatingInputMerger.

Creating InputMerger With ArrayCreatingInputMerger

To convert multiple output results into one input, use InputMerger. There are several implementations of it, the default is OverwritingInputMerger. Now ArrayCreatingInputMerger creates an array in which all the values of this key are placed.

For verification, we use the same example.

val thirdWorker = OneTimeWorkRequest.Builder(ThirdWorker::class.java)
                          .setInputMerger(ArrayCreatingInputMerger::class.java)
                          .build()  
WorkManager.getInstance()
        .beginWith(firstWorker, secondWorker)
        .then(thirdWorker)
        .enqueue()

Now, when you merge the output data from the previous tasks into the input data of the third worker, ArrayCreatingInputMerger will be used.

The first task will return data like below.

val output = Data.Builder()
       .putString("keyA", "value1")
       .putInt("keyB", 1)
       .putString("keyC", "valueC")
       .build();
setOutputData(output);
Below is the second task returned data.
val outputData = Data.Builder()
       .putString("keyA", "value2")
       .putInt("keyB", 2)
       .putString("keyD", "valueD")
       .build();
setOutputData(output);

In the third task, we get the input data like this.

valueA = [value1, value2] 
valueB = [1, 2] 
valueC = [valueC] 
valueD = [valueD]

With ArrayCreatingInputMerger case, if the keys match, the data is not overwritten but is added to an Array.

Well before ending this blog I want to describe one more case. Let’s say if we have two task running parallel then third and fourth.

val thirdWorker = OneTimeWorkRequest.Builder(ThirdWorker::class.java) 
                        .setInputMerger(ArrayCreatingInputMerger::class.java) 
                        .build() 
val fourthWorker = OneTimeWorkRequest.Builder(ThirdWorker::class.java) 
                        .setInputMerger(ArrayCreatingInputMerger::class.java) 
                        .build()
WorkManager.getInstance()
         .beginWith(firstWorker,secondWorker)
         .then(thirdWorker,fourthWorker)
         .enqueue()

In this case, the input data obtained from the first and second tasks will also arrive in the third and fourth task both, with ArrayCreatingInputMerger will be used.

Alright, this is my demonstration about how do we set InputMerger with ArrayCreatingInputMerger. I hope you guys have learned something from this article. If you any queries according to this article or any other problem regarding WorkManager, please do comment below.

Thank you for being here and keep reading…

The post InputMerger and ArrayCreatingInputMerger with WorkManager appeared first on Coding Infinite.

]]>
https://codinginfinite.com/inputmerger-workmanager-arraycreatinginputmerger/feed/ 1
ViewModel – Android Architecture Component https://codinginfinite.com/architecture-component-viewmodel-example/ https://codinginfinite.com/architecture-component-viewmodel-example/#comments Sat, 14 Jul 2018 09:13:08 +0000 http://codinginfinite.com/?p=714 Couple of years ago, when I’m studying at my University. We have given the assignment to make a color changer app. The app is very basic where we have only one button and when a user clicks the button it changes its background color. So like I said, the app is very basic and I’ve made...

The post ViewModel – Android Architecture Component appeared first on Coding Infinite.

]]>
Couple of years ago, when I’m studying at my University. We have given the assignment to make a color changer app. The app is very basic where we have only one button and when a user clicks the button it changes its background color.

So like I said, the app is very basic and I’ve made the app in just half an hour. When the user presses the button, it perfectly changes its background. But when a user rotates the phone, it vanished the current state of an app and shows a default color instead of the previously shown background color.

So, what happened..? Rotating a phone can cause a configuration change. The configuration changes can cause your whole Activity to tore down and then recreate it. So, to save the current state of the activity we need some kind of UI data holder. As for beginner, I use the onSaveInstanceState trick to store the app state.

The onSaveInstanceState is the best approach to store the small amount of data. Also in my scenario, I only need to store the current background color.

Problem

What happened if I need to store a large amount of data instead of just storing the background color. Let’s say I need to store the list of users and their profile picture when the app going to rotate. In here we cannot use onSaveInstanceState trick because it can only be used to store a small amount of data. Now how we can store the data…?

Thanks to this, at Google I/O 2017 the Android Framework team introduced a new Architecture Component which deals this kind of rotation.

ViewModel

The ViewModel class is designed to store and manage UI-related data in a conscious way. The ViewModel is able to live through the configuration changes. It means that even after the Activity is destroyed and recreated after the phone rotation, you’ll still have the same ViewModel with the same data.

Now instead of storing all of your UI data in your Activity put in the ViewModel. One common pitfall that we all do when developing the Android application is putting a lot of variables, logic, and data into your Activity and Fragment. This creates a large unmaintainable whole mess of class and violating the Single Responsibility Principle.

The Lifecycle of ViewModel

The ViewModel is responsible for preparing and managing the data for an Activity or Fragment. It is always created in the scope of an Activity or Fragment and will be retained as long as the scope is alive. The lifecycle of a ViewModel extends from the associated UI when it’s first created until it is completely destroyed. The following shows the lifetime of a ViewModel associated with Activity lifecycle.

You see the ViewModel exists throughout the activity lifecycle. The onCreate may be called several times through during the lifecycle of an Activity, such as when the app is rotated but the model remains.

So, enough of this theory let’s how we can create a simple ViewModel class.

Creating a ViewModel

To make the view model you end up extending the ViewModel class and then put all your UI related data in the model class, that you gonna show in the Activity or Fragment. So, let’s create a ViewModel for the screen to store the current background color.

The following shows how to create a ColorChangerViewModel.

class ColorChangerViewModel : ViewModel() {
    private var colorResource: Int = 0xfff

    fun setColorResource(colorResource: Int) {
        this.colorResource = colorResource
    }

    fun getColorResource() = colorResource
}

You see our ViewModel is only responsible for holding the data that you’re gonna show in the UI. In our case, our ViewModel only needs to know about the color.

Note: ViewModel should not contain elements, that contains a reference to the UI such as Views since this will create an indirect reference to a Context. It will also cause a memory leak.

Now you guys must be thinking if I need Context inside ViewModel to get the SystemService or any other logic you wanna do with it. So, thankfully we’ve AndroidViewModel which is simply a ViewModel that includes an Application reference. Storing an Application Context inside ViewModel is ok because an application context is tied to the application lifecycle.

So, we create ViewModel let’s see how we gonna use this view model inside the activity.

MainActivity

For creating a ViewModel instance you use the utility class called ViewModelProviders.

class MainActivity : AppCompatActivity() {

    private lateinit var colorChangerViewModel: ColorChangerViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        colorChangerViewModel = ViewModelProviders.of(this).get(ColorChangerViewModel::class.java)
        mainActivityRootView.setBackgroundColor(colorChangerViewModel.getColorResource())
        changeColorButton.setOnClickListener {
            val color = generateRandomColor()
            mainActivityRootView.setBackgroundColor(color)
            colorChangerViewModel.setColorResource(color)
        }

    }

    private fun generateRandomColor(): Int {
        val rnd = Random()
        return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))
    }
}

Notice the ViewModelProviders takes an activity instance. This is the mechanism that allows you to rotate the device to get a technically new activity instance but always ensures that activity instance is associated with the same ViewModel.

You see here our activity is only responsible for knowing how to draw that data to the screen and receiving user interactions but not for processing them. Our ViewModel instance, we’re accessing the getter and setter to save and retrieve the color.

Every time the user presses a button it updates the previous color with the new color in ViewModel. So, when the user rotates the app it destroys the activity and again calls the onCreate method which sets previous background color instead of white default color.

When creating an instance of a ViewModel with ViewModelProviders.of(this).get(SomeViewModel::class.java). In this scenario, we have a default constructor, what if we need the parameterize constructor for our ViewModel. For this kind of ViewModel, we need to create the custom ViewModelProvider.Factory.

Creating ViewModelProvider.Factory

To create a custom model factory we need to implements the ViewModelProivder.Factory interface. The custom model factory is responsible to instantiates the ViewModels.

The following shows how to create ViewModelProvider.Factory.

class CustomViewModelFactory(private val user: User) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return UserViewModel(user) as T
    }
}

You see in create method we’re calling our parameterize ViewModel constructor. Let’s see the UserViewModel class.

class UserViewModel(val user: User) : ViewModel(){
    .......
    .......
}

Now we have the model factory and ViewModel class let’s see how we can use this in the Activity.

class MainActivity : AppCompatActivity(){
       ......
       ......
       override fun onCreate(savedInstanceState: Bundle?) {
             .......
             .......
             val factory = CustomViewModelFactory(someUserModel)
             val userViewModel = ViewModelProviders.of(this, factory).get(UserViewModel::class.java)
       }
}

When creating a view model we need to pass the Activity reference along with ViewModelProvider.Factory instance.

Removing ViewModel Lifecycle Forwarding

At some point, you may need to clean up the view model. The idea is that you may want to delete or remove the data in the ViewModel on configuration change. Simply override the onCleared method in the view model class. You can also cancel a long-running task in the onCleared method.

override fun onCleared() {
    super.onCleared()
    cleanUpSomeBackgroundWork()
}

The onCleared method will call when the Activity completely gets destroyed.

ProTip

The ViewModel class is also designed to work well LiveData and Data Binding. Using all of these together you can create a Reactive UI which is just a fancy way of saying a UI that automatically updates whenever the underlying data changes.

Alright, this is my demonstration about how to simply create ViewModel and work with it. I hope you guys have learned something from this post. If you have question or comments regarding this post please do comment below.

Thank for being here and keep reading…

The post ViewModel – Android Architecture Component appeared first on Coding Infinite.

]]>
https://codinginfinite.com/architecture-component-viewmodel-example/feed/ 3
Android ktx with example – Fragment | Palette | Collection | SQLite https://codinginfinite.com/android-ktx-fragment-ktx-palette-ktx-collection-ktx-sqlite-ktx/ Tue, 26 Jun 2018 16:13:20 +0000 http://codinginfinite.com/?p=562 If you’re developing an Android application with Kotlin, then I have good news for you. Recently Google released an Android ktx library, which is a set of Kotlin Extension function. Android ktx is a part of Jetpack family. The purpose of Android ktx is to write less code and more concise. Android ktx brings us...

The post Android ktx with example – Fragment | Palette | Collection | SQLite appeared first on Coding Infinite.

]]>
If you’re developing an Android application with Kotlin, then I have good news for you. Recently Google released an Android ktx library, which is a set of Kotlin Extension function. Android ktx is a part of Jetpack family. The purpose of Android ktx is to write less code and more concise. Android ktx brings us lots of extension functions, named parameters, lambdas, and parameter with the default value. It does not add any new features to existing Android Api’s.

I read all the documentation on android-ktx and thought to write some notes on it. It’s not just reading on Android developer documentation. We’re going to see the extension functions with example and explore most of them.

Note: Android ktx is currently in preview mode but it is open for the developer to give it a try and give feedback to contributors. It may be offering more extension functions when it is released.

To get started with Android ktx add the google repository in build,gradle file.

repositories { 
    google() 
}

Android ktx dependency in split into the modular approach. By modular means, you don’t have to add the core dependency, if you do not want to use all of the extension’s functions. Here is the list of dependency of Android ktx.

implementation 'androidx.core:core-ktx:$currentVersion'
implementation 'androidx.fragment:fragment-ktx:$currentVersion'
implementation 'androidx.palette:palette-ktx:$currentVersion'
implementation 'androidx.sqlite:sqlite-ktx:$currentVersion'
implementation 'androidx.collection:collection-ktx:$currentVersion'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:$currentVersion'
implementation 'androidx.lifecycle:lifecycle-reactivestreams-ktx:$currentVersion'
implementation 'android.arch.work:work-runtime-ktx:$currentVersion'

After syncing the project you’re good to go to use Android ktx. Now let’s start with the first modular dependency.

1. Fragment-ktx:

Fragment ktx dependency right now supports only one extension function. The only extension function is about triggering the fragment transaction. Without ktx performing a fragment transaction, the transaction requires starting a transaction triggering an action like replacing or adding a fragment and then the signing on one of the four commit methods. Now let’s see how we can remove the boilerplate code with fragment ktx extension.

supportFragmentManager.transaction(now = false, allowStateLoss = false) {
      replace(R.id.frag_container, myFrament,FRAGMENT_TAG)
}

Fragment ktx as the transaction extension function to the FragmentManager class removing all the begin transaction boilerplate code. As well as providing the four value for sync and stateless that you can easily override.

nowallowStateLossMethod
falsefalsecommit()
falsetruecommitAllowingStateLoss()
truefalsecommitNow()
truetruecommitNowAllowingStateLoss()

2. Palette-ktx:

Like I said the library is currently in the preview that’s why we only have two extension function for palette ktx. Now let’s take a look at what extension function we have…?

Now you can easily create Palette. Builder with the bitmap.

val paletteBuilder : Palette.Builder = bitmap.buildPalette()

You can easily get Palette. Swatch from Palette class.

val paletteSwatch = pallete[Target.DARK_VIBRANT]

Returns the selected swatch for the given Target from the palette, or if null one could not be found. With palette swatch, you can retrieve RGB colour by calling the getRgb method.

3. SQLite-ktx:

SQLite ktx dependency right now supports only one extension function. When implementing database transaction you need a lot of boilerplate code, with the SQLite ktx, you can focus on what matters the operation that you want to make in the database. Let’s see an example of handling transaction with sqlLite ktx.

sqLitedatabase.transaction(exclusive = true){
    // Insert data, delete data, update data
}

If you setting exclusive to true it called beginTransaction and when setting false it called beginTransactionNonExclusive.

4. Collection-ktx:

If you use the Kotlin top-level function of creating collection then you absolutely love this collection ktx dependency. It supports many extension functions and it also supports the top-level function of creating the collection. Let’s see them one by one.

4.1 Collection-ktx Top-level Functions:

With the .collection package of ktx, you can easily create an arrayMapOf with top-level function to create ArrayMap.

val arrayMap = arrayMapOf<String,String>()   // returns an empty new ArrayMap

You can also give a list of Pair where the first component is the key and second component is the value.

map = arrayMapOf(pairs = *arrayOf(
          Pair("Jon", "Doe"),
          Pair("Hilary", "Clinton"))
)    // returns a array map with specified content.

The ArraySet also gives some top-level function to ease the process when working with them.

val arraySet = arraySetOf<Int>()   // returns an empty new ArraySet.

You can also give a vararg to create ArraySet.

val arraySet = arraySetOf(1,2,3)  // return an array set with specified content.
4.2 Collection-ktx Extension Functions:

When working with the LongSparseArray and SparseArrayCompat we can make use of the below extension function. Both of the classes pretty much offers the same functionalities.

val longSparseArray = LongSparseArray<String>()   // create a LongSparseArray of String

//   returns true if the collection contain the key
longSparseArray.contains(key: Long)    

// You can use index operator to store value a specified index
longSparseArray.set(key : Long,value : String)   // value is String, because our sparse array is String type

// create new collcetion by adding or replacing entries from other
longSparseArray.plus(other : LongSparseArray<String>)

// returns true if the collection contains the key
longSparseArray.containsKey(key : Long)

// return true if the collection contains the value
longSparseArray.containsValue(value : String)

// return the value corresponding to the key, or default when no present.
longSparseArray.getOrDefault(key : Long, defaultValue : String)  // return defaultValue if no value found according to the key

// return true when the collection contains one or more than element in the array.
longSparseArray.isNotEmpty()

// removes the entry from the array only if it is mapped to value in the specified index.
longSparseArray.remove(key : Long, value: String)

// updates this collection by adding replacing entries from other.
longSparseArray.putAll(other: LongSparseArray<String>)

// performs foreach on every key/value entry.
longSparseArray.forEach(action : (key : Long, value : String) -> Unit)

// Example of foreach function
longSparseArray.forEach{ key,value -> 
     // Use the key and value to perform the operation
}

// return Iterator over the collection key.
val iterator : LongIterator = longSparseArray.keyIterator()

// return Iterator over the collection values.
val iterator : Iterator<String> = longSparseArray.valueIterator()

That’s it guy’s, I’m going to end this blog here for more further reading about Android ktx see the part 2. In the next part, I’m going to explain about lifecycle ktx, reactive streams ktx and runtime ktx. Finally, in the third part, we’re gonna explore the core ktx.

I hope you guy’s have learned something from this post. If you’ve any queries about this post please do comment below.

Thank you for being here and keep reading.

Next Part

The post Android ktx with example – Fragment | Palette | Collection | SQLite appeared first on Coding Infinite.

]]>
AutoSize TextView Android https://codinginfinite.com/android-autosize-textview-example-tutorial/ https://codinginfinite.com/android-autosize-textview-example-tutorial/#comments Mon, 11 Jun 2018 18:10:28 +0000 http://codinginfinite.com/?p=526 Finally, Android O support library got this feature covered. Material design recommends using a dynamic type instead of smaller type sizes or truncating larger size text. A TextView that automatically resize the text, expand and fill its layout based on the text view characteristics and boundaries. These characteristics make it easier to optimize the text size...

The post AutoSize TextView Android appeared first on Coding Infinite.

]]>
Finally, Android O support library got this feature covered. Material design recommends using a dynamic type instead of smaller type sizes or truncating larger size text. A TextView that automatically resize the text, expand and fill its layout based on the text view characteristics and boundaries. These characteristics make it easier to optimize the text size with different screen size and dynamic content.

Auto-resizing can also help you avoid empty spaces in your layout or text that gets cut off mid-sentence because you tried to add too many words into a TextView.

Dependency

For to use Autosize TextView you need to add a dependency in your build.gradle file.

implementation 'com.android.support:appcompat-v7:27.1.0'
Types of setting Autosize TextView
  • Default
  • Granularity
  • Preset Sizes
1. Default

To define the default settings of Autosizing TextView with xml set “setautoSizeTextType” to uniform. Let’s see an example how we can use it in the xml file.

<TextView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:autoSizeTextType="uniform" />

Now this setting of TextView scale uniformly on horizontally and vertically ignoring the text size attributes. If you’re not settings the minTextSize, maxTextSize, and granularity properties then the default values will be used 12sp, 112sp, and 1px respectively.

Note: If you set Autosizing in an XML file, it is not recommended to use the value “wrap_content” for the layout_width or layout_height attributes of a TextView. It may produce unexpected results.

You can also set Autosizing of a TextView programmatically.

emojiCompatTextView.setAutoSizeTextTypeWithDefaults(TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM)
2. Granularity

With Granularity, the TextView will scale uniformly in the range between minimum and maximum size in increments of step granularity. If you don’t set these properties the default values will be used.

To implement Autosizing using granularity you’ll need to add the following attributes in the xml file. Below is the example how to use granularity in xml.

<TextView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:autoSizeTextType="uniform"
    app:autoSizeMinTextSize="12sp"
    app:autoSizeMaxTextSize="100sp"
    app:autoSizeStepGranularity="2sp" />

You can also set Autosizing using granularity programmatically.

emojiCompatTextView.setAutoSizeTextTypeUniformWithConfiguration(12, 100, 2, TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM)
3. Preset Sizes

To have more control over the final size. e.g your app needs to compile with specific text size design guidelines. You can provide an array of supported text sizes and it will use the largest one that fits. All you need to do for Preset Sizes create an array in your resources and then set “autoSizePresetSizes” in xml.

<TextView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:autoSizeTextType="uniform"
    app:autoSizePresetSizes="@array/autosize_text_sizes" />

An array of resources.

<array name="autosize_text_sizes">
    <item>12sp</item>
    <item>24sp</item>
    <item>36sp</item>
    <item>48sp</item>
    <item>60sp</item>
    <item>72sp</item>
</array>

You can also set Autosizing using Preset Sizes programmatically.

emojiCompatTextView.setAutoSizeTextTypeUniformWithPresetSizes(resources.getIntArray(R.array.auto_size_array),TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM)

Alright guy’s, that’s my explanation about Autosizing TextView with programmatically and with xml. If you guys have any query about this post please do comment below.

Thank you for being here and keep reading.

The post AutoSize TextView Android appeared first on Coding Infinite.

]]>
https://codinginfinite.com/android-autosize-textview-example-tutorial/feed/ 4