Using Kotlin to efficiently develop Android App (I)

Using Kotlin to efficiently develop Android App (I)

[[227035]]
Star Wars Soldiers.jpg

background

Recently we are working on a blockchain-related wallet project. The new App uses a brand new technology stack. In Android, we use Kotlin+RxJava+Android Architecture Components, and in iOS, we use Swift+RxSwift. This article does not discuss the architecture of the App, but only discusses the features of Kotlin used in the project.

In Android App, it is no exaggeration to say that more than 95% of our code is developed using Kotlin. Therefore, it is necessary to make a brief summary of the use of Kotlin in this stage.

Kotlin features used:

1. Extension Function

Kotlin allows developers to add new functions to a class without changing the existing class. This feature is called extension function.

Let's take a simple example: if you want to close an I/O stream, you might write a utility method in Java.

  1. /**  
  2. * Safely close the io stream  
  3. * @param closeable  
  4. */  
  5. public   static void closeQuietly(Closeable closeable) {  
  6. if (closeable != null ) {  
  7. try {
  8.   closeable.close ();  
  9. } catch (IOException e) {  
  10. e.printStackTrace();  
  11. }  
  12. }  
  13. }

For Kotlin, you can extend Closeable with a function closeQuietly().

  1. fun Closeable?.closeQuietly() {  
  2. try {  
  3. this? .close ()  
  4. } catch (e: Throwable) {  
  5. }  
  6. }

After that, any class that implements the Closeable interface can use its own closeQuietly() method to close the stream. We no longer need that utility method.

In the project, we use extension functions to encapsulate Glide, which greatly simplifies the use of Glide.

  1. /**  
  2. * Placeholder rectangle  
  3. */  
  4. fun ImageView. load (url: String) {  
  5. get(url).placeholder(R.drawable.shape_default_rec_bg)  
  6. .error(R.drawable.shape_default_rec_bg)
  7.   . into (this)  
  8. }  
  9. /**  
  10. * Placeholder rounded rectangle  
  11. */  
  12. fun ImageView.loadRound(url: String) {  
  13. get(url).placeholder(R.drawable.shape_default_round_bg)  
  14. .error(R.drawable.shape_default_round_bg)  
  15. // .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(DisplayUtil.dp2px(context, 6f), 0)))
  16.   .transform(RoundedCornersTransformation(DisplayUtil.dp2px(context, 6f), 0))  
  17. . into (this)  
  18. }
  19.   /**  
  20. * Placeholder circle  
  21. */  
  22. fun ImageView.loadCircle(url: Drawable) {  
  23. get(url).placeholder(R.drawable.shape_default_circle_bg)  
  24. .error(R.drawable.shape_default_circle_bg)  
  25. . into (this)  
  26. }
  27.   fun ImageView.loadCircle(url: String) {  
  28. get(url).placeholder(R.drawable.shape_default_circle_bg)  
  29. .error(R.drawable.shape_default_circle_bg)  
  30. . into (this)  
  31. }  
  32. fun ImageView.get(url: String): GlideRequest = GlideApp. with (context). load (url)  
  33. fun ImageView.get(url: Drawable): GlideRequest = GlideApp. with (context). load (url)

In addition, we use extension functions in many places.

I also updated my Kolin tool library, which includes various utils and extensions.

https://github.com/fengzhizi715/SAF-Kotlin-Utils

2. Trailing Closure

I didn't understand this concept at first. By chance, I saw our friends write the following code when using RxBus:

  1. RxBus.get().register(LogoutEvent::class.java) { refresh() }

I was confused at the time because I wrote RxBus and I remember that it didn't provide such a method. After clicking on the register() method, I found that register is like this:

  1. public Disposable register(Class eventType, Consumer onNext) {  
  2. return toObservable(eventType).observeOn(AndroidSchedulers.mainThread()).subscribe(onNext);  
  3. }

Since Kotlin is used, the use of the register method can be simplified as follows:

  1. RxBus.get().register(LogoutEvent::class.java,{  
  2. refresh()  
  3. })

Since the first parameter of register() is a method or a closure, you can move the method or closure to the outermost part. It will become what you see in the project:

  1. RxBus.get().register(LogoutEvent::class.java) { refresh() }

This is the trailing closure, which makes the code look more concise.

3. Usage of with

With is to use an object as a parameter of a function. In the function block, this can refer to the object. In the function block, you can directly call the method or property of the object.

  1. /**  
  2. * Calls the specified function [block] with the given [receiver] as its receiver and   returns its result.  
  3. */  
  4. @kotlin.internal.InlineOnly  
  5. public inline fun with (receiver: T, block: T.() -> R): R {  
  6. contract  
  7. callsInPlace(block, InvocationKind.EXACTLY_ONCE)  
  8. }  
  9. return receiver.block()  
  10. }

An Adapter before using with

  1. class AppPublisherAdapter : BaseAdapter() {  
  2. override fun getLayoutId(viewType: Int ): Int = R.layout.cell_app_publisher  
  3. override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int ,content: BoundAppInfoResponse.AppInfo) {  
  4. holder.itemView.tv_game_name.text = content.name  
  5.   if (content.is_bound) {  
  6. holder.itemView.tv_bound_user_name.text = content.bound_user_name  
  7. holder.itemView.tv_bound_user_name.setTextColor(context.resources.getColor(R.color.color_bound_user_name))  
  8. } else {  
  9. holder.itemView.tv_bound_user_name.text = context.getString(R.string.bind_on_account)  
  10. holder.itemView.tv_bound_user_name.setTextColor(context.resources.getColor(R.color.color_bind_on_account))  
  11. }  
  12. holder.itemView.iv_game_icon. load (content.logo_url)  
  13. }  
  14. }

After using with, the function block can omit "content."

  1. class AppPublisherAdapter : BaseAdapter() {  
  2. override fun getLayoutId(viewType: Int ): Int = R.layout.cell_app_publisher  
  3. override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int , content: BoundAppInfoResponse.AppInfo) {  
  4. with (content) {  
  5. holder.itemView.tv_game_name.text = name    
  6. if (is_bound) {  
  7. holder.itemView.tv_bound_user_name.text = bound_user_name  
  8. holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bound_user_name))  
  9. } else {  
  10. holder.itemView.tv_bound_user_name.text = context.string(R.string.bind_on_account)  
  11. holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bind_on_account))  
  12. }  
  13. holder.itemView.iv_game_icon. load (logo_url)  
  14. }  
  15. }
  16.   }

IV. Others

This part is not a feature of Kotlin, but a tool I developed using Kotlin, such as the logging framework L and Retrofit's logging interceptor. These libraries were actually developed a long time ago, and their functions have been slightly upgraded recently.

L's github address:

  • https://github.com/fengzhizi715/SAF-Kotlin-log

The github address of Retrofit log interceptor:

  • https://github.com/fengzhizi715/saf-logginginterceptor

The effect diagram of the log interceptor:


Request effect diagram.jpeg


response effect diagram.jpeg

Summarize

Kotlin absorbs the advantages of many languages ​​and has many exciting features compared to Java, which greatly improves development efficiency. The features introduced in this article are just a drop in the ocean. Next, I will sort out more Kotlin features used in projects.

BTW, when I was writing this article, the first version of the domestic wallet had just been completed and the first round of testing began.

<<:  In addition to paying, receiving money and adding friends, the QR codes you use every day also have these practical functions

>>:  Make iPhone fingerprint unlocking more sensitive | Qinggong

Recommend

The next stage of self-driving cars: You can take a nap in the car

According to foreign media reports, the problem w...

Banmeng Portrait Photography Online Class 4th Session 2020

Banmeng Portrait Photography Online Class 4th Ses...

Tangyuan or Yuanxiao? Note that these 4 types of people are advised to eat less!

Today is the Lantern Festival. Are you ready to e...

How do iPhone and Android phones receive push notifications?

How do we receive push notifications on our phone...

New media operation marketing strategy skills!

Through new media operations, we can complete bra...

Solution | 7 industry promotion tips under the influence of the epidemic

The sudden outbreak of the new coronavirus epidem...

Lard residue is not really that bad.

When it comes to mouth-watering childhood memorie...

How did the mercenary shout happy birthday?

The mercenary's happy birthday video was shot...

Wang Rui's 10-day advanced yoga course Baidu Cloud download

Wang Rui's 10-day advanced yoga course Baidu ...

After several major WeChat updates, you may not know these 8 useful tips

WeChat may be the most frequently used app in eve...