つまり、私のプロジェクトの解決策は、サポートthread
付きの画像をダウンロードすることです。さらに、再利用のためにデキューされていないことqueue
をターゲット コントロールでチェックします。UI
長いバージョン:
queue
メソッドStart
/で実装しますStop
。が呼び出しているとき、ビジー ループ ( ) でキューから要求をデキューしようとするStart
バックグラウンド スレッドを開始します。while true { DoSomething(); }
デキューされていない場合は、少しスリープします。デキューされた場合は、それを実行します (イメージのダウンロード)。Stop
メソッドは、ループを終了するスレッドを指定する必要があります。
public void Start()
{
if (started) {
return;
}
started = true;
new Thread (new ThreadStart (() => {
while (started) {
var request = GetRequest();
if (request != null) {
request.State = RequestState.Executing;
Download (request);
} else {
Thread.Sleep (QueueSleepTime);
}
}
})).Start ();
}
public void Stop()
{
started = false;
}
queue
次に、そのようなロジックでイメージをダウンロードするためのプライベート メソッドを作成します。ファイル キャッシュ内のイメージをチェックします。ファイルが利用可能な場合は、それを読み取って返します。そうでない場合は、ダウンロードしてファイルに保存し、それを返す ( を呼び出すAction<UIImage> onDownload
) か、エラーを返す ( を呼び出すAction<Exception> onError
)。queue
のビジー ループでこのメソッドを呼び出します。名前を付けますDownload
:
public Download(Request request)
{
try {
var image = GetImageFromCache(request.Url);
if (image == null) {
image = DownloadImageFromServer(request.Url); // Could be synchronous
}
request.OnDownload(image);
} catch (Exception e) {
request.OnError(e);
}
}
- 次に、リクエストをキューに追加する public メソッドを作成します。パターン
Command
は、キューのリクエストをラップするのに役立ちます: storage Actions
、 current State
。名前を付けますDownloadImageAsync
:
public DownloadImageAsync(string imageUrl, Action<UIImage> onDownload, Action<Exception> onError)
{
var request = MakeRequestCommand(imageUrl, onDownload, onError);
queue.Enqueue(request);
}
- 画像の表示と
UITableViewCell
ダウンロードのリクエストの準備中:
// Custom UITableViewCell method, which is called in `UITableViewSource`'s `GetCell`
public void PrepareToShow()
{
var imageURLClosure = imageURL;
queue.DownloadImageAsync(imageURL, (UIImage image) => {
if (imageURLClosure == imageURL) {
// Cell was not dequeued. URL from request and from cell are equals.
imageView.Image = image;
} else {
// Do nothing. Cell was dequeued, imageURL was changed.
}
}, (Exception e) => {
// Set default image. Log.
});
}
(imageURLClosure == imageURL) をチェックすることはUIImageView
、スクロールが速いときに複数の画像を 1 つに表示することを避けるために重要です。1 つのセルで複数の要求を初期化できますが、最後の 1 つの結果のみを使用する必要があります。
さらなる改善:
- LIFO実行。リクエストがまだ実行されていない場合は、新しいリクエストを追加して開始します。
- クロスプラットフォーム コードの互換性
Action<byte[]> onDownload
のために代わりに使用します。Action<UIImage> onDownload
download image
セルが見えなくなったときにリクエストをキャンセルできるようになりました ( WillMoveToSuperview
)。まあ、それはあまり必要ではありません。最初のダウンロード後、イメージはキャッシュに保存されるため、それ以降のイメージのリクエストは高速に処理されます。キャッシュのおかげです。
- メモリ内キャッシュ。したがって、最悪の場合、チェーンは次のようになります。
Find image in in-memory cache
-> Find image in file cache
-> Downloading from server
.