本页内容仅为高级使用作参考

大部分的应用,直接使用Drawees就好了,不用考虑关闭的事情了。

Java带有垃圾收集功能,许多开发者习惯于不自觉地创建一大堆乱七八糟的对象,并且想当然地认为他们会从内存中想当然地消失。

在5.0系统之前,这样的做法对于操作Bitmap是极其糟糕的。Bitmap占用了大量的内存,大量的内存申请和释放引发频繁的GC,使得界面卡顿不已。

Bitmap 是Java中为数不多的能让Java开发者想念或者羡慕C++以及C++众多的指针库,比如Boost 的东西。

Fresco的解决方案是: 可关闭的引用(CloseableReference)

为了正确地使用它,请按以下步骤进行操作:

1. 调用者拥有这个引用

我们创建一个引用,但我们传递给了一个调用者,调用者将持有这个引用。

1
2
3
4
CloseableReference<Val> foo() {
  Val val;
  return CloseableReference.of(val);
}

2. 持有者在离开作用域之前,需要关闭引用

创建了一个引用,但是没有传递给其他调用者,在结束时,需要关闭:

1
2
3
4
5
6
7
8
void gee() {
  CloseableReference<Val> ref = foo();
  try {
    haa(ref);
  } finally {
    ref.close();
  }
}

finally 中最适合做此类事情了。

3. 不要自己释放资源!

CloseableReference 会在没有活跃引用时释放资源,它通过一个内部的计数器来追踪活跃引用数。当它降为0时,CloseableReference就会释放持有的资源。你使用CloseableReference时的职责就是使用它来释放资源,而不是自己去手动释放资源!如果你这么做了,所有指向对应资源的CloseableReference在刷新时都会抛出异常。

1
2
3
4
5
6
7
8
9
10
  CloseableReference<Val> ref = foo();

  Val val = ref.get();
  // 处理val
  
  // 绝对不要close val
  //// val.close();

  // 使用CloseableReference来释放val
  ref.close();

4. 除了引用的持有者,闲杂人等不得关闭引用

作为一个参数传递,调用者持有这个引用,在下面的函数体中,不能关闭引用。

1
2
3
void haa(CloseableReference<?> ref) {
  Log.println("Haa: " + ref.get());
}

如果调用了 .close(), 调用者尝试调用 .get()时,会抛出IllegalStateException

5. 在赋值给变量前,先进行clone

在类中使用:

1
2
3
4
5
6
7
8
9
10
11
12
class MyClass {
  CloseableReference<Val> myValRef;

  void mmm(CloseableReference<Val> ref) {
    myValRef = ref.clone();
  };

  void close() {
    // MyClass的调用者需要关闭myValRef
    CloseableReference.closeSafely(myValRef);
  }
}

在内部中使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
void haa(CloseableReference<?> ref) {
  final CloseableReference<?> refClone = ref.clone();
  executor.submit(new Runnable() {
    public void run() {
      try {
        Log.println("Haa Async: " + refClone.get());
      } finally {
        refClone.close();
      }
    }
  });
  // 当前函数域内可安全关闭,闭包内为已经clone过的引用。
}

编辑和纠错