Fresco源碼解析,fresco源碼

來源:互聯網
上載者:User

Fresco源碼解析,fresco源碼

datasource是一個獨立的 package,與FB匯入的guava包都在同一個工程內 - fbcore

datasource的類別關係比較簡單,一張類圖基本就可以描述清楚它們間的關係。

DataSource 是一個 interface, 功能與JDK中的Future類似,但是相比於Future,它的先進之處則在於 不僅僅只生產一個單一的結果,而是能夠提供系列結果

Unlike Futures, DataSource can issue a series of results, rather than just one.

最典型的用途就是漸進式載入圖片時可以提供載入中的中間資料。

DataSubscriberDataSource 構成了一個觀察者模式

Datasource 提供了註冊方法。

void subscribe(DataSubscriber<T> dataSubscriber, Executor executor);

通過 subscribe 方法我們可以把 DataSubscriber 註冊成為 DataSource 的觀察者,然後當 DataSource 的資料發生變化時,在 Executor 中通知所有的觀察者 - DataSubscriber

DataSubscriber 會響應資料的四種變化。

使用Executor來通知觀察者是比較高明的,這樣做可以讓回調方法的執行線程交由 DataSubscriber 來處理,增加了靈活性。

DataSource 只是一個介面,沒有提供任何實現,AbstractDataSource 實現了 DataSource 後封裝了一些基礎的操作,例如 通知觀察者記錄資料狀態

Datasource 的狀態記錄使用了一個枚舉類型。

private enum DataSourceStatus {  // data source has not finished yet  IN_PROGRESS,  // data source has finished with success  SUCCESS,  // data source has finished with failure  FAILURE,}

這三種狀態儲存在一個成員變數(mDataSourceStatus)中。

@GuardedBy("this")private DataSourceStatus mDataSourceStatus;

AbstractDataSource 構造時,會把 mDataSourceStatus 設定為 IN_PROGRESS

protected AbstractDataSource() {  mIsClosed = false;  mDataSourceStatus = DataSourceStatus.IN_PROGRESS;  mSubscribers = new ConcurrentLinkedQueue<>();}

所有的觀察者(訂閱者)會被放在一個列表中 - mSubscribers

private final ConcurrentLinkedQueue<Pair<DataSubscriber<T>, Executor>> mSubscribers;

如果當前的資料請求沒有關閉並且滿足mDataSourceStatus == DataSourceStatus.IN_PROGRESS時才能註冊成功觀察者,因為只有當資料發生變化的時候,觀察者才有存在的意義。

  @Overridepublic void subscribe(final DataSubscriber<T> dataSubscriber, final Executor executor) {  Preconditions.checkNotNull(dataSubscriber);  Preconditions.checkNotNull(executor);  boolean shouldNotify;  synchronized(this) {    if (mIsClosed) {      return;    }    if (mDataSourceStatus == DataSourceStatus.IN_PROGRESS) {      mSubscribers.add(Pair.create(dataSubscriber, executor));    }    shouldNotify = hasResult() || isFinished() || wasCancelled();  }  if (shouldNotify) {    notifyDataSubscriber(dataSubscriber, executor, hasFailed(), wasCancelled());  }}

如果 DataSource 有了新的資料或者請求已經結束掉或被取消掉,會通知觀察者。

private void notifyDataSubscribers() {  final boolean isFailure = hasFailed();  final boolean isCancellation = wasCancelled();  for (Pair<DataSubscriber<T>, Executor> pair : mSubscribers) {    notifyDataSubscriber(pair.first, pair.second, isFailure, isCancellation);  }}private void notifyDataSubscriber(    final DataSubscriber<T> dataSubscriber,    final Executor executor,    final boolean isFailure,    final boolean isCancellation) {  executor.execute(      new Runnable() {        @Override        public void run() {          if (isFailure) {            dataSubscriber.onFailure(AbstractDataSource.this);          } else if (isCancellation) {            dataSubscriber.onCancellation(AbstractDataSource.this);          } else {            dataSubscriber.onNewResult(AbstractDataSource.this);          }        }      });}

使用 DataSource 很重要的一點:不要產生記憶體泄露,也就是說,用過的資源一定要釋放掉。
使用 DataSubscriber 註冊成為了觀察者後,回調方法都會帶回一個 DataSource 的執行個體,如果請求已經結束後者失敗了,拿到資料後一定要把 DataSourceclose 掉,否則很容易造成 OOM。

BaseDataSubscriber 就是為了防止OOM,它本身的設計也很巧妙。

在毀掉方法 onNewResultonFailure 中加了一個 try - catch, 在 try 的 block 中調用子類必須重載的 onNewResultImpl 方法,然後在 finally 的 block 中 close DataSource

DataSourceSubscriber.java

public abstract class BaseDataSubscriber<T> implements DataSubscriber<T> {  @Override  public void onNewResult(DataSource<T> dataSource) {    try {      onNewResultImpl(dataSource);    } finally {      if (dataSource.isFinished()) {        dataSource.close();      }    }  }  @Override  public void onFailure(DataSource<T> dataSource) {    try {      onFailureImpl(dataSource);    } finally {      dataSource.close();    }  }  @Override  public void onCancellation(DataSource<T> dataSource) {  }  @Override  public void onProgressUpdate(DataSource<T> dataSource) {  }  protected abstract void onNewResultImpl(DataSource<T> dataSource);  protected abstract void onFailureImpl(DataSource<T> dataSource);}

IncreasingQualityDataSourceSupplierFirstAvailableDataSourceSupplierDataSource 的兩種不同的資料存放區形式,等後面用到了再做分析。

Supplier 是一個設計比較巧妙的借口,用途非常廣泛。

A class that can supply objects of a single type. Semantically, this could be a factory, generator, builder, closure, or something else entirely. No guarantees are implied by this interface.

SettableDataSourceset 方法中使用 GuavaPreconditions 來做資料合法性檢驗,它與 DataSource 的區別也是僅此而已。

Preconditions

  • checkArgument
  • checkState
  • checkNotNull
  • checkElementIndex
  • checkPositionIndex
  • checkPositionIndexes

如果 check 結果為 false, 則拋出異常。Fresco 的錯誤處理基本上是用異常做的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.