background

We are currently working on updates to kotlin and Jetpack. I was assigned to upgrade Jetpack this time, and the target version was Google’s latest release.

Originally thought is a very simple work, is to upgrade all versions to do it! I thought this could be done in a minute.

It turns out there are so many holes.

Most of the content of today’s article is in the routing project, I completed the simple code and demo, if you are interested, you can understand. portal

All pit

First we upgrade the above version according to the official documentation. We are upgrading androidx. Fragments: fragments – KTX and androidx. Activity: activity – KTX found strange questions, because they use pom lifecycle – the version of the runtime, Lifecycle will have to be upgraded at the same time.

Then I cracked, officials removed androidx. Lifecycle: lifecycle – extensions to the warehouse, the library change into androidx. Lifecycle: lifecycle – process.

At this point we found a ghosting problem, because some projects in the main project also had dependencies on this library, which would cause dependencies to be passed into the main project. But if you were to remove them one by one like whack-a-mole, it would be very embarrassing if you missed them.

Remove all dependencies

This time I will tell you three ways of writing hui!

You can actually add groovy below build.gradle in the application directory. Make sure you eliminate these dependencies when you pack.

configurations {
    all*.exclude group: 'androidx.lifecycle'.module: 'lifecycle-extensions'
}
Copy the code

Or you can consider using my alternative method of removing all submodules of a project from the root directory build.gradle.

The advantage of this approach is that all submodules remove the corresponding dependencies, so that the dependency code is not directly used later.

allprojects {
    configurations.all { Configuration c ->
        if (c.state == Configuration.State.UNRESOLVED) {
            exclude group: 'androidx.lifecycle'.module: "lifecycle-extensions"}}}Copy the code

By using allProject + Configuration, we can call exclude to uniformly remove specific dependencies for the project.

There’s another way, of course, which is to do A strategy, and then replace some of the dependencies once, and that’s what happens when YOU replace A with B.

allprojects {

    configurations.all { Configuration c ->

     	resolutionStrategy.eachDependency { DependencyResolveDetails details ->
     	           if (details.requested.group == 'androidx.lifecycle' && 	details.requested.name == 'lifecycle-extensions') {
     	               details.useTarget group: 'androidx.lifecycle'.name: 	'lifecycle-process'}}}}Copy the code

. This part of the function, in fact, there is very interesting. You can gain a deeper understanding of one of gradle’s most important configurations

ViewModelProviders have been removed

The second problem we have is that ViewModelProviders have been removed in the latest version, which, oh my God, is killing us.

This part is actually relatively simple, because we have removed the old dependency, so there is no ViewModelProviders code in our project. In the first version we tried to avoid extensive modification, so we just copied a similar ViewModelProviders class under the package name.

But we normally only need a couple of of methods.

package androidx.lifecycle

@Deprecated("ViewModelProviders adapter not support any more")
object ViewModelProviders {

    @MainThread
    @JvmStatic
    fun of(activity: FragmentActivity): ViewModelProvider {
        return ViewModelProvider(activity)
    }

    @MainThread
    @JvmStatic
    fun of(activity: FragmentActivity, factory: ViewModelProvider.Factory?).: ViewModelProvider {
        return if (factory == null) {
            ViewModelProvider(activity)
        } else {
            ViewModelProvider(activity, factory)
        }
    }


    @MainThread
    @JvmStatic
    fun of(fragment: Fragment): ViewModelProvider {
        return ViewModelProvider(fragment)
    }

    @MainThread
    @JvmStatic
    fun of(fragment: Fragment, factory: ViewModelProvider.Factory?).: ViewModelProvider {
        return if (factory == null) {
            ViewModelProvider(fragment)
        } else {
            ViewModelProvider(fragment, factory)
        }
    }

}
Copy the code

So we’ll probably just generate this class, and we’ll solve our first substitution problem. But outdated classes don’t need to last forever, so we’re going to phase out static checking for business changes.

JVM 1.8 also failed?

The upgrade in our process, we found some warehouse directly with the androidx. Activity: activity – KTX and androidx. Fragments: fragments – KTX. They retrieve viewModels in the form of a fragment or an extension of the activity, the viewModels delegate.

However, due to the upgrade of the SDK, the noinline method needs to be compiled by kotlin JVM 1.8, so it cannot compile. The solution is relatively simple, which is to set the following code in the Module build.gradle.

KotlinOptions {jvmTarget = "1.8"}Copy the code

But is there a general way to directly set all modules in a project to jvmTarget?

allprojects { tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach { kotlinOptions { JvmTarget = "1.8"}}Copy the code

This way, we can adjust all the kotlinOptions versions in the project to the version we want.

The Binding delicious

Finally, as I was ready to start using ViewBinding, I stole the Hi-DHL Binding and emasculated a ViewBinding only version.

[Binding project address](

Github.com/hi-dhl/Bind…).

But it’s still a nice way to write a commission.

This part has been introduced by several big guys before, so I won’t expand the explanation here.

conclusion

Of course, I won’t give examples of other tweaks, such as the main process registration, and some of the other weird crash issues, we’ll just have to deal with them.

All right, I’m done with the pussy, so next time we’ll see if we can get a better one.

I’ll do it next time.