Android 使用URL的逐帧动画返回null Drawable
我想创建一帧一帧的动画,并从URL下载可绘制的内容 问题: 是否可以从onPostExecute或imageButton检索bitmapDrawable? 我想再简单不过了 下面的代码不完整,我不知道如何从Android 使用URL的逐帧动画返回null Drawable,android,url,bitmap,android-asynctask,android-animation,Android,Url,Bitmap,Android Asynctask,Android Animation,我想创建一帧一帧的动画,并从URL下载可绘制的内容 问题: 是否可以从onPostExecute或imageButton检索bitmapDrawable? 我想再简单不过了 下面的代码不完整,我不知道如何从onPostExecute检索bitmapDrawable,因此我从现在的代码中得到了一个空的Drawable 主碎片 public class PrincipalFragment extends Fragment { private int mNum; private
onPostExecute
检索bitmapDrawable
,因此我从现在的代码中得到了一个空的Drawable
主碎片
public class PrincipalFragment extends Fragment {
private int mNum;
private AnimationDrawable mframeAnimation = null;
private static final int DELAY = 500;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
}
/**
* The Fragment's UI is just a simple text view showing its
* instance number.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.scrollview, container, false);
ImageButton i = (ImageButton)v.findViewById(R.id.imageButton1);
i.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
ImageButton button = (ImageButton)v;
String principal = "principal";
if (event.getAction() == MotionEvent.ACTION_DOWN) {
button.setColorFilter(0x8066bbdd);
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
button.setColorFilter(null);
Intent i = new Intent(getActivity(), SubView.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("query", principal);
startActivity(i);
return true;
}
return false;
}
});
ImageButton i2 = (ImageButton)v.findViewById(R.id.imageButton2);
i2.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
ImageButton button = (ImageButton)v;
String principal2 = "principal2";
if (event.getAction() == MotionEvent.ACTION_DOWN) {
button.setColorFilter(0x8066bbdd);
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
button.setColorFilter(null);
Intent i = new Intent(getActivity(), SubView.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("query", principal2);
startActivity(i);
return true;
}
return false;
}
});
ImageDownloader.Mode mode = ImageDownloader.Mode.CORRECT;
ImageDownloader imageDownloader = new ImageDownloader();
imageDownloader.setMode(mode);
BitmapDrawable frame1 = imageDownloader.download(URLnames.URLS[0], i, getResources());
BitmapDrawable frame2 = imageDownloader.download(URLnames.URLS[1], i2, getResources());
int reasonableDuration = 2500;
mframeAnimation = new AnimationDrawable();
mframeAnimation.setOneShot(false);
mframeAnimation.addFrame(frame1, reasonableDuration);
mframeAnimation.addFrame(frame2, reasonableDuration);
ImageView img = (ImageView) v.findViewById(R.id.img_animated);
img.setImageDrawable(mframeAnimation);
mframeAnimation.setVisible(true, true);
img.post(new Starter());
return v;
}
class Starter implements Runnable {
public void run() {
mframeAnimation.start();
}
}
}
ImageDownloader.class
public class ImageDownloader {
private static final String LOG_TAG = "ImageDownloader";
public enum Mode { NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT }
private Mode mode = Mode.NO_ASYNC_TASK;
private Resources r = null;
/**
* Download the specified image from the Internet and binds it to the provided ImageView. The
* binding is immediate if the image is found in the cache and will be done asynchronously
* otherwise. A null bitmap will be associated to the ImageView if an error occurs.
*
* @param url The URL of the image to download.
* @param imageView The ImageView to bind the downloaded image to.
* @param resources
*/
public BitmapDrawable download(String url, ImageView imageView, Resources resources) {
resetPurgeTimer();
Bitmap bitmap = getBitmapFromCache(url);
BitmapDrawable bitmapDrawable = new BitmapDrawable(r, bitmap);
this.r = resources;
if (bitmap == null) {
bitmapDrawable = forceDownload(url, imageView);
} else {
cancelPotentialDownload(url, imageView);
imageView.setImageBitmap(bitmap);
}
return bitmapDrawable;
}
/*
* Same as download but the image is always downloaded and the cache is not used.
* Kept private at the moment as its interest is not clear.
private void forceDownload(String url, ImageView view) {
forceDownload(url, view, null);
}
*/
/**
* Same as download but the image is always downloaded and the cache is not used.
* Kept private at the moment as its interest is not clear.
* @param resources
* @return
*/
private BitmapDrawable forceDownload(String url, ImageView imageView) {
// State sanity: url is guaranteed to never be null in DownloadedDrawable and cache keys.
BitmapDrawable bitmapDrawable;
if (url == null) {
imageView.setImageDrawable(null);
return null;
}
if (cancelPotentialDownload(url, imageView)) {
switch (mode) {
case NO_ASYNC_TASK:
Bitmap bitmap = downloadBitmap(url);
addBitmapToCache(url, bitmap);
imageView.setImageBitmap(bitmap);
break;
case NO_DOWNLOADED_DRAWABLE:
imageView.setMinimumHeight(156);
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
task.execute(url);
break;
case CORRECT:
task = new BitmapDownloaderTask(imageView);
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
imageView.setMinimumHeight(156);
task.execute(url);
break;
}
}
return null;
}
/**
* Returns true if the current download has been canceled or if there was no download in
* progress on this image view.
* Returns false if the download in progress deals with the same url. The download is not
* stopped in that case.
*/
private static boolean cancelPotentialDownload(String url, ImageView imageView) {
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
if (bitmapDownloaderTask != null) {
String bitmapUrl = bitmapDownloaderTask.url;
if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
bitmapDownloaderTask.cancel(true);
} else {
// The same URL is already being downloaded.
return false;
}
}
return true;
}
/**
* @param imageView Any imageView
* @return Retrieve the currently active download task (if any) associated with this imageView.
* null if there is no such task.
*/
private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
if (imageView != null) {
Drawable drawable = imageView.getDrawable();
if (drawable instanceof DownloadedDrawable) {
DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
return downloadedDrawable.getBitmapDownloaderTask();
}
}
return null;
}
Bitmap downloadBitmap(String url) {
final int IO_BUFFER_SIZE = 4 * 1024;
// AndroidHttpClient is not allowed to be used from the main thread
final HttpClient client = (mode == Mode.NO_ASYNC_TASK) ? new DefaultHttpClient() :
AndroidHttpClient.newInstance("Android");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
// return BitmapFactory.decodeStream(inputStream);
// Bug on slow connections, fixed in future release.
return BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (IOException e) {
getRequest.abort();
Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
} catch (IllegalStateException e) {
getRequest.abort();
Log.w(LOG_TAG, "Incorrect URL: " + url);
} catch (Exception e) {
getRequest.abort();
Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
} finally {
if ((client instanceof AndroidHttpClient)) {
((AndroidHttpClient) client).close();
}
}
return null;
}
/*
* An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
*/
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
/**
* The actual AsyncTask that will asynchronously download the image.
*/
class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
private final WeakReference<ImageView> imageViewReference;
public BitmapDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
/**
* Actual download method.
*/
@Override
protected Bitmap doInBackground(String... params) {
url = params[0];
return downloadBitmap(url);
}
/**
* Once the image is downloaded, associates it to the imageView
*/
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
addBitmapToCache(url, bitmap);
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
// Change bitmap only if this process is still associated with it
// Or if we don't use any bitmap to task association (NO_DOWNLOADED_DRAWABLE mode)
if ((this == bitmapDownloaderTask) || (mode != Mode.CORRECT)) {
// imageView.setImageBitmap(bitmap);
BitmapDrawable bitmapDrawable = new BitmapDrawable(r, bitmap);
imageView.setImageDrawable(bitmapDrawable);
}
}
}
}
/**
* A fake Drawable that will be attached to the imageView while the download is in progress.
*
* <p>Contains a reference to the actual download task, so that a download task can be stopped
* if a new binding is required, and makes sure that only the last started download process can
* bind its result, independently of the download finish order.</p>
*/
static class DownloadedDrawable extends ColorDrawable {
private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
super(Color.BLACK);
bitmapDownloaderTaskReference =
new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
}
public BitmapDownloaderTask getBitmapDownloaderTask() {
return bitmapDownloaderTaskReference.get();
}
}
public void setMode(Mode mode) {
this.mode = mode;
clearCache();
}
/*
* Cache-related fields and methods.
*
* We use a hard and a soft cache. A soft reference cache is too aggressively cleared by the
* Garbage Collector.
*/
private static final int HARD_CACHE_CAPACITY = 10;
private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds
// Hard cache, with a fixed maximum capacity and a life duration
private final HashMap<String, Bitmap> sHardBitmapCache =
new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {
@Override
protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
if (size() > HARD_CACHE_CAPACITY) {
// Entries push-out of hard reference cache are transferred to soft reference cache
sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
return true;
} else
return false;
}
};
// Soft cache for bitmaps kicked out of hard cache
private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =
new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);
private final Handler purgeHandler = new Handler();
private final Runnable purger = new Runnable() {
public void run() {
clearCache();
}
};
/**
* Adds this bitmap to the cache.
* @param bitmap The newly downloaded bitmap.
*/
private void addBitmapToCache(String url, Bitmap bitmap) {
if (bitmap != null) {
synchronized (sHardBitmapCache) {
sHardBitmapCache.put(url, bitmap);
}
}
}
/**
* @param url The URL of the image that will be retrieved from the cache.
* @return The cached bitmap or null if it was not found.
*/
private Bitmap getBitmapFromCache(String url) {
// First try the hard reference cache
synchronized (sHardBitmapCache) {
final Bitmap bitmap = sHardBitmapCache.get(url);
if (bitmap != null) {
// Bitmap found in hard cache
// Move element to first position, so that it is removed last
sHardBitmapCache.remove(url);
sHardBitmapCache.put(url, bitmap);
return bitmap;
}
}
// Then try the soft reference cache
SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(url);
if (bitmapReference != null) {
final Bitmap bitmap = bitmapReference.get();
if (bitmap != null) {
// Bitmap found in soft cache
return bitmap;
} else {
// Soft reference has been Garbage Collected
sSoftBitmapCache.remove(url);
}
}
return null;
}
/**
* Clears the image cache used internally to improve performance. Note that for memory
* efficiency reasons, the cache will automatically be cleared after a certain inactivity delay.
*/
public void clearCache() {
sHardBitmapCache.clear();
sSoftBitmapCache.clear();
}
/**
* Allow a new delay before the automatic cache clear is done.
*/
private void resetPurgeTimer() {
purgeHandler.removeCallbacks(purger);
purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);
}
}
公共类ImageDownloader{
私有静态最终字符串日志\u TAG=“ImageDownloader”;
公共枚举模式{NO_ASYNC_TASK,NO_download_DRAWABLE,CORRECT}
私有模式=模式。无异步任务;
私有资源r=null;
/**
*从Internet下载指定的图像并将其绑定到提供的ImageView
*如果在缓存中找到映像,则绑定是立即的,并且将异步完成
*否则。如果发生错误,则会将空位图关联到ImageView。
*
*@param url要下载的图像的url。
*@param imageView将下载的图像绑定到的imageView。
*@param资源
*/
公共BitmapDrawable下载(字符串url、ImageView、资源){
重置PurgeTimer();
位图位图=getBitmapFromCache(url);
BitmapDrawable BitmapDrawable=新的BitmapDrawable(r,位图);
这.r=资源;
如果(位图==null){
bitmapDrawable=forceDownload(url,imageView);
}否则{
取消潜在下载(url、imageView);
设置图像位图(位图);
}
返回位图可绘制;
}
/*
*与下载相同,但始终下载映像,不使用缓存。
*由于利益不明,目前保密。
私有void forceDownload(字符串url、图像视图){
强制下载(url、视图、空);
}
*/
/**
*与下载相同,但始终下载映像,不使用缓存。
*由于利益不明,目前保密。
*@param资源
*@返回
*/
私有位图可强制下载(字符串url,ImageView){
//状态健全性:url在下载的可绘制和缓存密钥中保证永远不为空。
位图可绘制位图可绘制;
如果(url==null){
imageView.setImageDrawable(空);
返回null;
}
if(取消潜在下载(url,图像视图)){
开关(模式){
案例编号异步任务:
位图位图=下载位图(url);
addBitmapToCache(url、位图);
设置图像位图(位图);
打破
案例编号\u下载\u可提取:
imageView.setMinimumHeight(156);
BitmapDownloaderTask任务=新建BitmapDownloaderTask(图像视图);
task.execute(url);
打破
大小写正确:
任务=新位图下载任务(imageView);
DownloadedDrawable DownloadedDrawable=新的DownloadedDrawable(任务);
imageView.setImageDrawable(可下载Drawable);
imageView.setMinimumHeight(156);
task.execute(url);
打破
}
}
返回null;
}
/**
*如果当前下载已取消或中没有下载,则返回true
*此图像视图的进度。
*如果正在进行的下载处理相同的url,则返回false。下载不正确
*在那种情况下停止。
*/
私有静态布尔cancelPotentialDownload(字符串url,ImageView ImageView){
BitmapDownloaderTask BitmapDownloaderTask=getBitmapDownloaderTask(图像视图);
if(bitmapDownloaderTask!=null){
字符串bitmapUrl=bitmapDownloaderTask.url;
如果((bitmapUrl==null)| |(!bitmapUrl.equals(url))){
bitmapDownloaderTask.cancel(true);
}否则{
//已下载相同的URL。
返回false;
}
}
返回true;
}
/**
*@param imageView任意imageView
*@return检索与此imageView关联的当前活动下载任务(如果有)。
*如果没有此类任务,则为null。
*/
私有静态位图下载任务getBitmapDownloaderTask(ImageView ImageView){
如果(imageView!=null){
Drawable Drawable=imageView.getDrawable();
if(可下载的可绘制实例可绘制){
DownloadedDrawable DownloadedDrawable=(DownloadedDrawable)可绘制;
返回downloadedDrawable.getBitmapDownloaderTask();
}
}
返回null;
}
位图下载位图(字符串url){
最终输入输出缓冲区大小=4*1024;
//不允许从主线程使用AndroidHttpClient
最终HttpClient客户端=(模式==模式。无异步任务)?新建DefaultHttpClient():
AndroidHttpClient.newInstance(“Android”);
最终HttpGet getRequest=新HttpGet(url);
试一试{
HttpResponse response=client.execute(getRequest);
final int statusCode=response.getStatusLine().getStatusCode();
if(statusCode!=HttpStatus.SC\u OK){
Log.w(“ImageDownloader”,“Error”+状态码+
从“+url”检索位图时);
返回null;
}
最终HttpEntity=response.getEntity();
如果(实体!=null){
InputStream InputStream=null;
试一试{
inputStream=entity.getContent();
public Bitmap download(String url, ImageView imageView, Resources resources) throws InterruptedException, ExecutionException {
resetPurgeTimer();
Bitmap bitmap = getBitmapFromCache(url);
this.r = resources;
if (bitmap == null) {
bitmapDrawable = forceDownload(url, imageView);
} else {
cancelPotentialDownload(url, imageView);
imageView.setImageBitmap(bitmap);
}
return bitmapDrawable;
}
/*
* Same as download but the image is always downloaded and the cache is not used.
* Kept private at the moment as its interest is not clear.
private void forceDownload(String url, ImageView view) {
forceDownload(url, view, null);
}
*/
/**
* Same as download but the image is always downloaded and the cache is not used.
* Kept private at the moment as its interest is not clear.
* @param resources
* @return
* @throws ExecutionException
* @throws InterruptedException
*/
private Bitmap forceDownload(String url, ImageView imageView) throws InterruptedException, ExecutionException {
// State sanity: url is guaranteed to never be null in DownloadedDrawable and cache keys.
Bitmap bitmap = null;
if (url == null) {
imageView.setImageDrawable(null);
return null;
}
if (cancelPotentialDownload(url, imageView)) {
switch (mode) {
case NO_ASYNC_TASK:
Bitmap bitmap2 = downloadBitmap(url);
addBitmapToCache(url, bitmap2);
imageView.setImageBitmap(bitmap2);
break;
case NO_DOWNLOADED_DRAWABLE:
imageView.setMinimumHeight(156);
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView, this);
task.execute(url);
break;
case CORRECT:
task = new BitmapDownloaderTask(imageView, this);
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
imageView.setMinimumHeight(156);
task.execute(url);
bitmap = task.get();
break;
}
}
return bitmap;