我正在使用这个库来显示照片(我不想使用PhotoView
库,因为它没有我需要的)。这个库是完美的,但只有一个缺点:当改变屏幕方向时,它会使屏幕变白,并在几毫秒内重新加载图像......我玩过代码,SubsamplingScaleImageView
发现这三个中有一些方法AsyncTask
' sdoInBackground
中操作所需的方法uiThread
。
当我使用该代码时,我已经将所有内容从doInBackground
方法移动到postExecute
每个AsyncTask
类中并编译程序。令我惊讶的是一切工作正常,我决定撤消所有操作并更仔细地使用该代码进行操作,但在那之后它没有工作,即使我试图postExecute
再次将代码移动到......我不记得我是如何将该代码移入,onPostExecute
但它一直在工作,直到我决定重构它(((请任何人帮助我!
/**
* Async task used to get image details without blocking the UI thread.
*/
private static class TilesInitTask extends AsyncTask<Void, Void, int[]> {
private final WeakReference<SubsamplingScaleImageView> viewRef;
private final WeakReference<Context> contextRef;
private final WeakReference<DecoderFactory<? extends ImageRegionDecoder>> decoderFactoryRef;
private final Uri source;
private ImageRegionDecoder decoder;
private Exception exception;
public TilesInitTask(SubsamplingScaleImageView view, Context context, DecoderFactory<? extends ImageRegionDecoder> decoderFactory, Uri source) {
this.viewRef = new WeakReference<SubsamplingScaleImageView>(view);
this.contextRef = new WeakReference<Context>(context);
this.decoderFactoryRef = new WeakReference<DecoderFactory<? extends ImageRegionDecoder>>(decoderFactory);
this.source = source;
}
@Override
protected int[] doInBackground(Void... params) {
try {
String sourceUri = source.toString();
Context context = contextRef.get();
DecoderFactory<? extends ImageRegionDecoder> decoderFactory = decoderFactoryRef.get();
SubsamplingScaleImageView view = viewRef.get();
if (context != null && decoderFactory != null && view != null) {
decoder = decoderFactory.make();
Point dimensions = decoder.init(context, source);
int sWidth = dimensions.x;
int sHeight = dimensions.y;
int exifOrientation = view.getExifOrientation(sourceUri);
if (view.sRegion != null) {
sWidth = view.sRegion.width();
sHeight = view.sRegion.height();
}
return new int[] { sWidth, sHeight, exifOrientation };
}
} catch (Exception e) {
Log.e(TAG, "Failed to initialise bitmap decoder", e);
this.exception = e;
}
return null;
}
@Override
protected void onPostExecute(int[] xyo) {
final SubsamplingScaleImageView view = viewRef.get();
if (view != null) {
if (decoder != null && xyo != null && xyo.length == 3) {
view.onTilesInited(decoder, xyo[0], xyo[1], xyo[2]);
} else if (exception != null && view.onImageEventListener != null) {
view.onImageEventListener.onImageLoadError(exception);
}
}
}
}
/**
* Async task used to load images without blocking the UI thread.
*/
private static class TileLoadTask extends AsyncTask<Void, Void, Bitmap> {
private final WeakReference<SubsamplingScaleImageView> viewRef;
private final WeakReference<ImageRegionDecoder> decoderRef;
private final WeakReference<Tile> tileRef;
private Exception exception;
public TileLoadTask(SubsamplingScaleImageView view, ImageRegionDecoder decoder, Tile tile) {
this.viewRef = new WeakReference<SubsamplingScaleImageView>(view);
this.decoderRef = new WeakReference<ImageRegionDecoder>(decoder);
this.tileRef = new WeakReference<Tile>(tile);
tile.loading = true;
}
@Override
protected Bitmap doInBackground(Void... params) {
try {
SubsamplingScaleImageView view = viewRef.get();
ImageRegionDecoder decoder = decoderRef.get();
Tile tile = tileRef.get();
if (decoder != null && tile != null && view != null && decoder.isReady()) {
synchronized (view.decoderLock) {
// Update tile's file sRect according to rotation
view.fileSRect(tile.sRect, tile.fileSRect);
if (view.sRegion != null) {
tile.fileSRect.offset(view.sRegion.left, view.sRegion.top);
}
return decoder.decodeRegion(tile.fileSRect, tile.sampleSize);
}
} else if (tile != null) {
tile.loading = false;
}
} catch (Exception e) {
Log.e(TAG, "Failed to decode tile", e);
this.exception = e;
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
final SubsamplingScaleImageView subsamplingScaleImageView = viewRef.get();
final Tile tile = tileRef.get();
if (subsamplingScaleImageView != null && tile != null) {
if (bitmap != null) {
tile.bitmap = bitmap;
tile.loading = false;
subsamplingScaleImageView.onTileLoaded();
} else if (exception != null && subsamplingScaleImageView.onImageEventListener != null) {
subsamplingScaleImageView.onImageEventListener.onTileLoadError(exception);
}
}
}
}
UPD
现在我刚刚更改AsyncTasks
为Runnable
并通过run()
没有Handler(getMainLooper()).post(runnable)
. 有人可以解释一下发生了什么吗?
/**
* Async task used to get image details without blocking the UI thread.
*/
private static class TilesInitTask implements Runnable {
private final WeakReference<SubsamplingScaleImageView> viewRef;
private final WeakReference<Context> contextRef;
private final WeakReference<DecoderFactory<? extends ImageRegionDecoder>> decoderFactoryRef;
private final Uri source;
private ImageRegionDecoder decoder;
private Exception exception;
public TilesInitTask(SubsamplingScaleImageView view, Context context, DecoderFactory<? extends ImageRegionDecoder> decoderFactory, Uri source) {
this.viewRef = new WeakReference<>(view);
this.contextRef = new WeakReference<>(context);
this.decoderFactoryRef = new WeakReference<DecoderFactory<? extends ImageRegionDecoder>>(decoderFactory);
this.source = source;
}
public void run() {
SubsamplingScaleImageView view = null;
try {
String sourceUri = source.toString();
Context context = contextRef.get();
DecoderFactory<? extends ImageRegionDecoder> decoderFactory = decoderFactoryRef.get();
view = viewRef.get();
if (context != null && decoderFactory != null && view != null) {
decoder = decoderFactory.make();
Point dimensions = decoder.init(context, source);
int sWidth = dimensions.x;
int sHeight = dimensions.y;
int exifOrientation = view.getExifOrientation(sourceUri);
if (view.sRegion != null) {
sWidth = view.sRegion.width();
sHeight = view.sRegion.height();
}
view.onTilesInited(decoder, sWidth, sHeight, exifOrientation);
}
} catch (Exception e) {
Log.e(TAG, "Failed to initialise bitmap decoder", e);
this.exception = e;
if (view != null && view.onImageEventListener != null) {
view.onImageEventListener.onImageLoadError(exception);
}
}
}
}
/**
* Async task used to load images without blocking the UI thread.
*/
private static class TileLoadTask implements Runnable {
private final WeakReference<SubsamplingScaleImageView> viewRef;
private final WeakReference<ImageRegionDecoder> decoderRef;
private final WeakReference<Tile> tileRef;
private Exception exception;
public TileLoadTask(SubsamplingScaleImageView view, ImageRegionDecoder decoder, Tile tile) {
this.viewRef = new WeakReference<>(view);
this.decoderRef = new WeakReference<>(decoder);
this.tileRef = new WeakReference<>(tile);
tile.loading = true;
}
public void run() {
SubsamplingScaleImageView view = null;
try {
view = viewRef.get();
ImageRegionDecoder decoder = decoderRef.get();
Tile tile = tileRef.get();
if (decoder != null && tile != null && view != null && decoder.isReady()) {
synchronized (view.decoderLock) {
// Update tile's file sRect according to rotation
view.fileSRect(tile.sRect, tile.fileSRect);
Log.d("TAGTAG", "2");
if (view.sRegion != null) {
tile.fileSRect.offset(view.sRegion.left, view.sRegion.top);
}
tile.bitmap = decoder.decodeRegion(tile.fileSRect, tile.sampleSize);
tile.loading = false;
view.onTileLoaded();
}
} else if (tile != null) {
tile.loading = false;
}
} catch (Exception e) {
Log.e(TAG, "Failed to decode tile", e);
this.exception = e;
if (view != null && view.onImageEventListener != null) {
view.onImageEventListener.onTileLoadError(exception);
}
}
}
}