Author of this issue:

Video: Throwing the line (Zhu Kai)

Article: Walker zhang Lei

Hi, I’m Junkey the sling. This is the second installment of the basics of Kotlin: “It doesn’t Write that way” in Kotlin. No more words, video service.

Since I never learned how to post a video on the Nuggets, click here to bilibili, or click here to YouTube.

The following is from the author Walker.

Last time we talked about the basics of Kotlin: variables, functions, and types. You’ve heard that Kotlin is fully compatible with Java, which means that code written in Java and Kotlin interact perfectly, not that you can write Kotlin in Java, which is not. In this video, we’re going to talk about the non-Java ways of writing Kotlin.

Constructor

The Kotlin constructor was introduced briefly in the last article. This section takes a look at how Kotlin’s constructor is different from Java’s:

  • Java

    ☕ ️public class User {
        int id;
        String name;
          👇   👇
        public User(int id, String name) {
            this.id = id;
            this.name = name; }}Copy the code
  • Kotlin

    🏝 ️class User {
        val id: Int
        valName: String 👇constructor(id: Int, name: String) {
     / / 👆 not public
            this.id = id
            this.name = name
        }
    }
    Copy the code

Two differences can be found:

  • In Java, the constructor has the same name as the class, which is used in KotlinconstructorSaid.
  • The constructor in Kotlin does not have the public modifier, because by default visibility is public. (I won’t expand the visibility modifier here, but I’ll get to that later.)

init

In addition to the constructor, the init block, which is often used together in Java, is written a little differently in Kotlin: you need to prefix it with init.

  • Java

    ☕ ️public class User {👇 {// Initialize the code block before executing the following constructor
        }
        public User(a) {}}Copy the code
  • Kotlin

    🏝 ️class User {👇 init {// Initialize the code block before executing the following constructor
        }
        constructor() {}}Copy the code

As noted above, Kotlin’s init block is executed at instantiation time, just like Java, and it is executed before the constructor.

As mentioned in the last article, Java classes without the final keyword can be inherited by default, while Kotlin’s classes are final by default. In Java, final can also be used to modify variables. Let’s take a look at how Kotlin does this.

final

Val in Kotlin, like final in Java, represents a read-only variable and cannot be modified. Here’s a comparison of Java’s member variables, parameters, and local variables:

  • Java

    ☕ ️ 👇final int final1 = 1;
                 👇  
    void method(final String final2) {👇final String final3 = "The parameter is " + final2;
    }
    Copy the code
  • Kotlin

    🏝 ️ 👇val fina1 = 1
           // the 👇 parameter has no val
    fun method(final2: String){👇val final3 = "The parameter is " + final2
    }
    Copy the code

We can see the main differences are:

  • Final becomes val.
  • Kotlin’s arguments are of type val by default, so you don’t need to write the val keyword before the arguments. The reason for this design in Kotlin is to ensure that the arguments can’t be modified, whereas Java’s arguments can be modified (not final by default), which increases the probability of an error.

As we said in the last video, var is short for variable, and val is short for value.

In fact, when we’re writing Java code, very few people use final, but final is useful for modifying variables, but nobody uses it; But if you look at Kotlin code written by people, both domestic and foreign, you’ll find a lot of people have a bunch of Val’s in their code. Why is that? Because final is a bit more difficult to write than val: I need to write one more word. It’s just a little bit of trouble, but it causes a lot of people not to write.

That’s the interesting thing: going from final to val, which is just a little bit more convenient, makes a huge difference in how often it’s used. This change affects the quality of the code: by adding restrictions where appropriate, you reduce the probability of code errors.

valCustom getter

There is a difference between val and final. Although val can’t be assigned twice, you can use a custom getter function to return a dynamically obtained value each time the variable is accessed:

🏝 ️ 👇val size: Int
    get() { // 👈 Executes kitems.size every time the size value is fetched
        return items.size
    }
Copy the code

But this is another way of using val, which in most cases corresponds to final use in Java.

static property / function

So we said that nobody likes to write final, right? But there’s one scenario where people like to use final the most: constants.

☕ ️public static final String CONST_STRING = "A String";
Copy the code

When we write constants in Java, we use static + final. And in Kotlin, in addition to final, static is written differently, and it’s even more different. To be exact: in Kotlin, the concepts of static variables and static methods are eliminated.

What if you want to use a direct reference in Kotlin through a class like in Java? Kotlin’s answer is Companion Object:

🏝 ️class Sample {... 👇companion object {
        val anotherString = "Another String"}}Copy the code

Why does Kotlin get more complicated? Let’s see what “object” is.

object

Object in Kotlin — lowercase, not uppercase, object in Java is no longer used in Kotlin.

Object in Java becomes Any in Kotlin, and acts just like Object: as the base class for all classes.

While object is not a class, it is a keyword in Kotlin like class:

🏝 ️object Sample {
    val name = "A name"
}
Copy the code

The idea is straightforward: create a class, and create an object of that class. This is what object means.

To use this object in your code, you can access it directly by its class name:

🏝 ️ Sample. The nameCopy the code

That’s what singletons are, so creating singletons in Kotlin doesn’t have to be as complicated as creating singletons in Java. You just replace class with object.

  • Singleton class

    Let’s look at an example of a singleton, implemented in Java and Kotlin:

    • Implementations of singletons in Java (non-thread-safe) :

      ☕ ️public class A {
          private static A sInstance;
          
          public static A getInstance(a) {
              if (sInstance == null) {
                  sInstance = new A();
              }
              return sInstance;
          }
      
          // 👇 has a lot of template code. }Copy the code

      You can see that Java has written a lot of template code to implement the singleton class, which is a little tedious.

    • Implement singletons in Kotlin:

      🏝 ️// 👇 Class is replaced with object
      object A {
          val number: Int = 1
          fun method(a) {
              println("A.method()")}}Copy the code

      The differences between Java and Java are:

      • Similar to the class definition, but putclassReplaced with aobject
      • There is no need to maintain an additional instance variablesInstance.
      • There is no need to “ensure that the instance is created only once”getInstance()Methods.

      It’s much simpler than the Java implementation.

      This singleton implemented by Object is a hunger-like singleton and is thread safe.

  • Inheriting classes and implementing interfaces

    In Kotlin, not only can a class inherit from another class, but also an object can implement an interface:

    🏝 ️open class A {
        open fun method(a){... }}interface B {
        fun interfaceMethod(a)
    }
      👇      👇   👇
    object C : A(), B {
    
        override fun method(a){... }override fun interfaceMethod(a){... }}Copy the code

    Why do objects implement interfaces? Object is a combination of two steps into one step. It has the class keyword function and implements the singleton, so it is easy to understand.

  • An anonymous class

    In addition, Kotlin can also create anonymous classes in Java, but the writing is a little different:

    • Java:

      ☕ ️ 👇 ViewPager. SimpleOnPageChangeListener listener =new ViewPager.SimpleOnPageChangeListener() {
          @Override / / 👈
          public void onPageSelected(int position) {
              // override}};Copy the code
    • Kotlin:

      🏝 ️val listener = object: ViewPager.SimpleOnPageChangeListener() {
          override fun onPageSelected(position: Int) {
              // override}}Copy the code

      This is similar to how Java creates anonymous classes, except that new is replaced by object: :

      • In JavanewAn object used to create an anonymous class
      • In the Kotlinobject:It can also be used to create objects of anonymous classes

      Both new and object: refer to interfaces or abstract classes.

companion object

Variables and functions in an object decorated with object are static, but sometimes we just want some of the functions and variables in the class to be static.

🏝 ️class A {👇object B {
        var c: Int = 0}}Copy the code

As mentioned above, we can create an object in the class and place the variable or function that needs to be static in the internal object B. The external static variable can be called as follows:

🏝 ️ A.B.C 👆Copy the code

Objects nested in a class can be modified with companion:

🏝 ️class A {👇companion object B {
        var c: Int = 0}}Copy the code

Companion can be understood as companion, companion, and represents a decorated object and external class binding.

But there is a small limitation: you can have at most one companion object in a class, but you can have multiple nested objects. There are three thousand beauties in the emperor’s harem, but only one empress.

The advantage of this is that the name of the object can be omitted:

🏝 ️ A.c// 👈 B is gone
Copy the code

So, when the companion modifier is used, the name of the object can also be omitted:

🏝 ️class A {
                // 👇 B is gone
    companion object {
        var c: Int = 0}}Copy the code

That’s the equivalent of Java static variables and methods that we talked about at the beginning of this section: Companion Object variables and functions.

  • Static initialization

    Static variables and methods in Java are placed in Companion Objects in Kotlin. So static initializations in Java are naturally placed in Companion Objects in Kotlin, just like class initialization code, represented by init and a pair of curly braces:

    🏝 ️class Sample {👇companion object{👇 init {... }}}Copy the code

Top-level property/function declaration

Instead of just calling static functions, Kotlin has something even more convenient: “top-level declaration.” Is actually the attributes and functions of statement don’t write in the class, this is allowed in the Kotlin:

🏝 ️package com.hencoder.plus

// 👇 belongs to package, not in class/object
fun topLevelFuncion(a){}Copy the code

Properties and functions written in this way do not belong to any class, but directly belong to the package. They are as global as static variables and functions, but are easier to use: You don’t even need to write the class name when you use them elsewhere:

🏝 ️import com.hencoder.plus.topLevelFunction // 👈 Import function directly

topLevelFunction()
Copy the code

Writing a function or variable at the top level has an advantage: When you write code in Android Studio, it’s easy for the IDE to automatically think of the function you’re writing based on the first few letters. This improves the efficiency of writing code and reduces duplication of code in your project.

  • Name the same top-level function

    One possible problem with not writing top-level functions in a class is that if you declare functions with the same name in different files, will they get confused? Here’s an example:

    • In the org.kotlinmaster.library package there is a function method:

      🏝 ️packageOrg. Kotlinmaster. Library1 👆fun method(a) {
          println("library1 method()")}Copy the code
    • In the org. Kotlinmaster. Library2 package under a same function:

      🏝 ️packageOrg. Kotlinmaster. Library2 👆fun method(a) {
          println("library2 method()")}Copy the code

    What happens if you call both of these functions at the same time:

    🏝 ️importOrg. Kotlinmaster. Library1. Method 👆fun test(a){method () 👇 org. Kotlinmaster. Library2. Method ()}Copy the code

    As you can see, when there are two top-level functions with the same name, the IDE automatically prefixes them with a package, which confirms the “top-level functions are packages” feature.

contrast

In practice, which one should I choose between Object, Companion Object, and top-level? To make a simple judgment, follow these two principles:

  • If you want to write the functionality of the utility class, create the file directly and write the top-level function.
  • If you need to inherit from another class or implement an interface, useobjectcompanion object.

constant

So in Java, in addition to the static variables and methods that we talked about above, we use static when we declare constants, so what happens when we declare constants in Kotlin?

  • Declare constants in Java:

    ☕ ️public class Sample {👇 👇public static final int CONST_NUMBER = 1;
    }
    Copy the code
  • Declare constants in Kotlin:

    🏝 ️class Sample {
        companion object{👇/ / 👇
            const val CONST_NUMBER = 1
        }
    }
    
    const val CONST_SECOND_NUMBER = 2
    Copy the code

Found differences include:

  • Kotlin’s constants must be declared in an object (including companion objects) or “top-level” because constants are static.
  • Kotlin added modifiers for constantsconstThe keyword.

And there’s another difference:

  • Only basic and String types can be declared constants in Kotlin.

The reason for this is that constant in Kotlin refers to “compile-time constant,” which means that “the compiler knows at compile time what the actual value of this thing is at each call,” so it can be hard-coded directly into the code where it is used at compile time.

Instead of basic and String variables, you can change the value inside an object by calling its methods or variables, so that the variable is not constant. Let’s take a look at a Java example, such as a User class:

☕ ️public class User {
    int id; // 👈 Can be modified
    String name; // 👈 Can be modified
    public User(int id, String name) {
        this.id = id;
        this.name = name; }}Copy the code

Declare a static final User instance where it is used, which cannot be assigned twice:

☕ ️static final User user = new User(123."Zhangsan");
  👆    👆
Copy the code

However, you can change the value of the user instance by accessing its member variables:

☕ ️ user name ="Lisi";
      👆
Copy the code

So a constant in Java can be considered “pseudo-constant” because its internal value can be changed in this way. Kotlin’s constants don’t have this problem because they have to be basic types, so they fit the definition of constants.

The val “read-only” and static variables mentioned above are both for individual variables. Now let’s look at another common topic in programming: arrays and collections.

Arrays and collections

An array of

Declare an array of strings:

  • How to write in Java

    ☕️
    String[] strs = {"a"."b"."c"};
          👆        👆
    Copy the code
  • Kotlin:

    🏝 ️val strs: Array<String> = arrayOf("a"."b"."c")
                👆              👆
    Copy the code

You can see that the array in Kotlin is a class that has a generic type, and the creation function is a generic function, as is the collection data type.

We’ll talk about generics later in this article, but let’s start with Java generics.

What are the benefits of generalizing arrays? Arrays can be more powerful as collections, and Kotlin can add a number of useful utility functions to arrays due to generalization:

  • get() / set()
  • contains()
  • first()
  • find()

This greatly increases the utility of arrays.

  • Value and Modification

    Getting or setting array elements in Kotlin, as in Java, can be indexed using square brackets and subscripts:

    🏝 ️ println (STRS [0]) 👇 👆 STRS [1] = "B"
    Copy the code
  • Covariant is not supported

    Kotlin’s arrays are still compiled to bytecode using Java arrays, but are generic implementations at the language level. This loses covariance, which means that subclass array objects cannot be assigned to subclass array variables:

    • Kotlin

      🏝 ️val strs: Array<String> = arrayOf("a"."b"."c")
                        👆
      val anys: Array<Any> = strs // compile-error: Type mismatch
                      👆
      Copy the code
    • This is possible in Java:

      ☕️
      String[] strs = {"a"."b"."c"};
        👆
      Object[] objs = strs; // success
        👆
      Copy the code

    I’m not going to expand on covariant here, but I’ll talk about it later when I talk about generics.

A collection of

Kotlin, like Java, has three collection types: List, Set, and Map, which mean the following:

  • ListStores a set of elements in a fixed order that can be repeated.
  • SetStores a set of unequal elements, usually in no fixed order.
  • MapA data set that stores key-value pairs where the keys are not equal, but different keys can correspond to the same value.

How has the use of these three collection types changed from Java to Kotlin? Let’s take a look.

  • List

    • Create a list in Java:

      ☕ ️ a List < String > strList =new ArrayList<>();
      strList.add("a");
      strList.add("b");
      strList.add("c"); // 👈 Adding elements is cumbersome
      Copy the code
    • Create a list in Kotlin:

      🏝 ️val strList = listOf("a"."b"."c")
      Copy the code

    The first thing you can see is that creating a List in Kotlin is extraordinarily simple, kind of like creating an array. And the List in Kotlin has one more feature: support covariant (covariant). In other words, we can assign the List of a subclass to the List variable of a superclass:

    • Kotlin:

      🏝 ️val strs: List<String> = listOf("a"."b"."c")
                      👆
      val anys: List<Any> = strs // success
                     👆
      Copy the code
    • In Java, this would cause an error:

      ☕ ️ a List < String > strList =new ArrayList<>();
             👆
      List<Object> objList = strList; // 👈 compile error: incompatible types
            👆  
      Copy the code

    For covariant support or not, lists and arrays are reversed. As for covariation, we need to take a brief look at it with examples, which will be discussed in later articles.

    • And array

      The API for Kotlin arrays and MutableList are very similar. The main difference is that the number of elements in an array cannot be changed. So when do we use arrays?

      • This problem exists in Java. Arrays and lists have similar functions, but lists have more functions, so the intuition is to use List. Arrays are not without their advantages, however. Arrays of basic types (int[], float[]) perform better without autoboxing.

      • The same is true in Kotlin, where arrays are preferable in situations where performance requirements are more demanding and the element type is a basic type. One thing to note here, however, is that Kotlin needs to use a specialized primitive array class (IntArray FloatArray LongArray) to avoid packing. In other words, when the elements are not of a basic type, it’s easier to use List than Array.

  • Set

    • Create a Set in Java:

      ☕ ️ Set < String > strSet =new HashSet<>();
      strSet.add("a");
      strSet.add("b");
      strSet.add("c");
      Copy the code
    • Create the same Set in Kotlin:

      🏝 ️val strSet = setOf("a"."b"."c")
      Copy the code

    Similar to the List, the Set is also covariant.

  • Map

    • Create a Map in Java:

      ☕️
      Map<String, Integer> map = new HashMap<>();
      map.put("key1".1);
      map.put("key2".2);
      map.put("key3".3);
      map.put("key4".3);
      Copy the code
    • Create a Map in Kotlin:

      🏝 ️val map = mapOf("key1" to 1."key2" to 2."key3" to 3."key4" to 3)
      Copy the code

    Similar to the two collection types above, the creation code is simple. Each parameter of mapOf represents a key-value pair, and to represents the association of “key” with “value.” This is called an “infix expression,” which I will not expand here until later in this article.

    • Value and Modification

      • In addition to getting a value based on the key using get(), as in Java, Kotlin maps can also be obtained using square brackets:

        🏝 ️ 👇val value1 = map.get("key1")
                       👇
        val value2 = map["key2"]
        Copy the code
      • Similarly, Kotlin can use square brackets to change the value of a Map key:

        🏝 ️ 👇val map = mutableMapOf("key1" to 1."key2" to 2) 👇 map. Put ("key1".2) 👇 map ["key1"] = 2    
        Copy the code

      This uses the knowledge of operator overloading and implements the same Positional Access Operations as arrays, a concept I won’t expand on here until later.

  • Mutable sets/immutable sets

    In the previous example of modifying the Map value, the function was created using mutableMapOf() instead of mapOf(), because only maps created by mutableMapOf() can be modified. There are two types of collections in Kotlin: read-only and mutable. Read only here has two meanings:

    • The size of the set is immutable
    • The values of the elements in the collection are immutable

    Here are three examples of creating immutable and mutable instances of the three collection types:

    • listOf()Create immutableList.mutableListOf()Create mutableList.
    • setOf()Create immutableSet.mutableSetOf()Create mutableSet.
    • mapOf()Create immutableMap.mutableMapOf()Create mutableMap.

    We can see that functions that are mutable create collections that are mutable. Functions that are not mutbale create collections that are mutable, but that are mutable can be converted toMutable by using the toMutable*() function:

    🏝 ️val strList = listOf("a"."b"."c") 👇 strList. ToMutableList ()val strSet = setOf("a"."b"."c") 👇 strSet. ToMutableSet ()val map = mapOf("key1" to 1."key2" to 2."key3" to 3."key4" to 3) 👇 map. ToMutableMap ()Copy the code

    Then you can make changes to the collection. Here’s a caveat:

    • toMutable*()Returns a new set. The original set is still immutable, so only the set returned by the function can be modified.

Sequence

In addition to collections, Kotlin also introduced a new container type, Sequence, which, like Iterable, can be used to traverse a set of data and do specific processing for each element. Let’s first look at creating a Sequence.

  • create
    • Like listOf(), created with a set of elements:

      🏝 ️ sequenceOf ("a"."b"."c")
      Copy the code
    • Use Iterable to create:

      🏝 ️val list = listOf("a"."b"."c")
      list.asSequence()
      Copy the code

      List implements the Iterable interface.

    • Use a lambda expression to create:

      🏝 ️// 👇 The first element
      val sequence = generateSequence(0) { it + 1 }
                                        // 👆 Lambda expression, responsible for generating the second and subsequent elements, with it representing the previous element
      Copy the code

This looks the same as Iterable, so why bother using Sequence? Examples will be used in the next article.

Visibility modifier

Now that we’re done with data sets, let’s look at visibility modifiers in Kotlin. There are four kinds of visibility modifiers in Kotlin:

  • public: Public, maximum visibility, can be referenced anywhere.
  • private: private, minimal visibility, according to the declaration location can be classified as visible in the class and file visible.
  • protectedProtect, protect, protect, protectprivate+ subclass visible.
  • internal: Internal, visible only to modules.

Java has an internal “module visible” modifier instead of a default “package visible” modifier. This section discusses the four visibility modifiers in Kotlin and the differences between Kotlin and Java, using examples. Let’s start with public:

public

If you do not write a visibility modifier in Java, you can refer to it only within the same package:

☕ ️ 👇package org.kotlinmaster.library; 
// There is no visibility modifier
class User {}Copy the code
☕ ️// 👇 is the same package as above
package org.kotlinmaster.library;

public class Example {
    void method(a) {
        new User(); // success}}Copy the code
☕ ️package org.kotlinmaster;
                    // 👆 is not a package
import org.kotlinmaster.library.User;
                          👆
public class OtherPackageExample {
    void method(a) {
        new User(); // compile-error: 'org.kotlinmaster.library.User' is not public in 'org.kotlinmaster.library'. Cannot be accessed from outside package}}Copy the code

If you want a reference outside of package, you need to add the visibility modifier public before class to indicate exposure.

If you don’t write the visibility modifier in Kotlin, it means public, which has the same effect as the public modifier in Java. In Kotlin the public modifier “can be added, but not necessary”.

@hide

In the official Android SDK, there are some methods that are only visible to the SDK and not open to users (because these methods are not stable and will most likely be changed or removed in a later version). To implement this feature, a Javadoc method @hide is added to the method annotation to restrict client access:

☕ ️/ * * *@hide👈 * /
public void hideMethod(a) {... }Copy the code

However, this restriction is not strict, and the restricted method can be accessed through reflection. For this, Kotlin introduced a more stringent visibility modifier: internal.

internal

Internal means that decorated classes and functions are visible only within a module. A module is a set of kotlin files that are compiled together.

  • Module in Android Studio
  • Maven project

This is often the case with Modules in Android Studio, but the Maven project is just a matter of understanding.

Internal is useful when writing a Library Module. When you want to create a function that is only open to use within the Module and not visible to users of the library, you should use the internal visibility modifier.

What happened to Java’s “visible inside the package”?

Java’s default “visible within the package” is deprecated in Kotlin, where the closest visibility modifier to it is the internal “visible within the module.” Why would it be deprecated to switch inside the visible? I think there are several reasons:

  • Kotlin encourages the creation of top-level functions and attributes, and a single source file can contain multiple classes, making Kotlin’s source code structure more flat and making the package structure less important than in Java.
  • For the sake of decoupling and maintainability of the code, more and more modules become smaller and smaller, so thatinternal“Visible within the Module” already satisfies the need for code encapsulation.

protected

  • In JavaprotectedPackage visible + subclass visible.
  • In the Kotlinprotectedsaidprivate+ subclass visible.

Kotlin has a narrower scope of visibility than Java protected because Kotlin no longer has the concept of “visibility inside packages” and is more concerned with Modules than Java’s focus on packages.

private

  • In JavaprivateRepresents visible in a class, and is “visible” to external classes when it is an inner class.
  • In the KotlinprivateIndicates that the class is visible in or in the file in which it is located, and is “invisible” to external classes when it is an inner class.

Private modified variables “visible in class” and “visible in file” :

🏝 ️class Sample {
    private val propertyInClass = 1 // 👈 Is available only in the Sample class
}

private val propertyInFile = "A string." // 👈 range is larger and the entire file is visible
Copy the code

The difference between Java and Kotlin when decorating variables of inner classes:

  • In Java, an external class can access the private variables of an inner class:

    ☕ ️public class Outter {
        public void method(a) {
            Inner inner = new Inner();
                                👇
            int result = inner.number * 2; // success
        }
        
        private class Inner {
            private int number = 0; }}Copy the code
  • In Kotlin, an outer class cannot access a private variable of an inner class:

    🏝 ️class Outter {
        fun method(a) {
            val👇 inner = inner ()val result = inner.number * 2 // compile-error: Cannot access 'number': it is private in 'Inner'
        }
        
        class Inner {
            private val number = 1}}Copy the code
  • You can decorate classes and interfaces

    • In Java, only one external class is allowed per file, so classes and interfaces are not allowed to be set to private, because declaring private cannot be used externally, which makes no sense.

    • Kotlin allows multiple class and top-level functions and properties to be declared in the same file, so Kotlin allows classes and interfaces to be declared private because other members of the same file can access them:

      🏝 ️private class Sample {
          val number = 1
          fun method(a) {
              println("Sample method()")}}// 👇 is in the same file, so it is accessible
      val sample = Sample()
      Copy the code

exercises

  1. Create a Kotlin class that disallows outsiders from creating instances through the constructor and provides at least one way to instantiate them.
  2. Use Array, IntArray, List to achieve “save 1-100_000 numbers, and calculate the average of these numbers”, and print out the execution time of these three data structures.

The authors introduce

Video author

Throw line (Zhu Kai)
  • Code on the school founder, project manager, content module planner and video content author.
  • Android GDE (Google Certified Android Development Specialist), former Flipboard Android Engineer.
  • GitHub is ranked 92nd in the world for Java and has 6.6 K followers and 9.9 K stars on GitHub.
  • The personal Android open source library, MaterialEditText, is referenced by several projects around the world, including Flipboard, a news-reading software with 500 million users worldwide.
  • Served as the lecturer of Android in Google Developer Group Beijing offline sharing sessions for many times.
  • After the personal technical article “RxJava Details for Android Developers” was released, it was forwarded and shared within many companies and teams in China and served as the main source of information for technical meetings of teams. It was also backtransmitted to some Chinese teams in some Companies such as Google and Uber in the United States.
  • HenCoder, an advanced Android teaching website founded, enjoys considerable influence in the Global Chinese Android development community.
  • After that, he founded The Android advanced development teaching course HenCoder Plus, with students from all over the world, including senior software engineers from Taiwan, Japan, the United States and other regions, including Ali, Tiaotiao, Huawei, Tencent and other famous first-tier Internet companies.

The authors

Walker Zhang Lei

Walker zhang Lei is a senior engineer at Jike Android. In 2015, I joined Jike and participated in the architecture design and product iteration of Jike 2.0 to 6.0. Years of Experience in Android development, worked for OPPO, focusing on client user experience, audio and video development and performance optimization.