Kotlin 语言高级安卓开发入门(5)

除了同步阻塞代码块,我们可以用一个表达式来实现同步阻塞。 “Any” 是 Kotlin 的对象版本。所有的类型都是 “Any” 的子类型。我们可以对它增加一个方法,该方法输入是一个函数,然后执行这个函数的代码,这段代码会同步该实例。如果我们需要同样的锁,或者一些对象需要被锁住,我们可以把这段代码放在函数内部的锁起来。然后我们把它传给每个实例的这个方法中。这个方法简化了调用者的代码,而且清晰很多。

 

简单清晰的锁

 

另一个十分酷的应用存在于我们常用的锁的情景中,我们常常忘记在一些操作之前完成锁的操作。我们可以写这样的类,这个类只允许你访问你需要用锁才能操作的资源。

[代码]csharp代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

 

data class Lock<t>(private val obj: T) {

  public fun acquire(func: (T) -> Unit) {

    synchronized (obj) {

      func(obj)

    }

  }

}

 

val readerLock = Lock(JsonReader(stream))

 

// Later

readerLock.acquire {

  println(it.readString())

}</t>

 

在这个例子里面,我们创建了依赖流的 JsonReader。设想不论什么原因我们需要多线程同时访问它,这样我们就必须使用锁,锁会帮助我们管理同步的问题。

 

然后在后面的代码中,我们调用了这个 acquire 的方法,它会在这个 JsonReader 的实例上实现同步,然后把它传给我们提供的函数。所以在这种情况下,我们会在这个 JsonReader 里面再次析构,于是我们需要使用锁。但现在我们的代码根本没有处理锁的问题。我们也没有显式的同步,也没有为 JsonReader 创建锁。可是访问 JsonReader 不使用锁是不可能的。

 

避免 Kotlin 带来的泄露

 

前面,我提到过关于 data 的代码,定义了一个这样的值:

 

[代码]csharp代码:

?

1

 

val notEmpty: (String) -> Boolean { !it.isEmpty() }

 

Kotlin 实现函数表达式的方法和在 Java 里面使用类的方法是一样的。好处是 Kotlin 并没有创建对于外部范围的引用,因为没有这样的类。这样避免了可能的上下文泄漏。

 

我们需要关心的就是传入的数据。它会导致创建一个静态的单例实例而且没有引用。用这些函数表达式根本不可能产生上下文泄漏。但是在最上层,我们两个是一模一样的。

 

扩展函数表达式的例子

 

扩展函数 – 给一个类型加入函数但是不修改原来的类型。

 

函数表达式 – 未定义的函数体被用作表达式(i.e.,date)

 

Higher-Order 函数 – 一个参数是函数或者返回是函数的函数。

 

扩展函数表达式是上述三个概念的综合体,这是个强大的而且可以创建清晰的 API 的方法。为了说明这点,我将使用一个 databases 的 API 做为例子,把它改造成一个更加整洁的、没有无效代码的 API。

 

[代码]csharp代码:

?

1

2

3

4

5

6

7

 

db.beginTransaction();

try {

  db.delete("users", "first_name = ?", new String[] { "Jake" });

  db.setTransactionSuccessful();

} finally {

  db.endTransaction();

}

 

如果你想在一个 transaction 里面执行一个 statement 的话,这是你必须写的六行代码。我们开始一个 transaction,我们把它放在 “try finally” 里面,然后我们标记这个 transaction 为成功。如果它抛出或者不在 “finally” 里面抛出异常,我们需要结束 transaction.

这是一个容易带来 bug 的代码,容易健忘的代码和应该重构的代码。任何事情都有可能出现错误,在这里你不小心交换了两个事情,然后突然,你就会有一个很难找到原因的 bug。 或者它会在运行时 crash。

扩展函数表达式允许我们解决这个问题。我们现在能给 database 自己增加一个方法, 这将给现有的代码构建一个防护墙。

 

[代码]csharp代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

 

fun SQLiteDatabase.inTransaction(func: (SQLiteDatabase) -> Unit) {

  beginTransaction()

  try {

    func(this)

    setTransactionSuccessful()

  } finally {

    endTransaction()

  }

}

 

db.inTransaction {

  it.db.delete("users", "first_name = ?", arrayOf("Jake"))

}

 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/565fb5401a5bd42fef5d2913560b4f9f.html