安卓:java.util.concurrent.ThreadPoolExecutor

标签 android multithreading

在我的应用程序中有一个 RecyclerView,其中包含大量图像。当用户使用以下代码滚动 RecyclerView 时,图像被加载:

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        loader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,url);
    else
        loader.execute(url);

不幸的是,有时当用户快速滚动时会发生此错误:

Task android.os.AsyncTask$3@73f1d84 rejected from 
java.util.concurrent.ThreadPoolExecutor@8f5f96d[Running, pool size = 9, 
active threads = 9, queued tasks = 128, completed tasks = 279]

有没有办法检测 poolExecutor 是否已满并跳过图像加载?

整个图像类:

public class Image extends ImageView {
private AsyncTask<String,Integer,Bitmap> loader;

public Image(Context context) {
    super(context);
    this.setScaleType(ScaleType.FIT_XY);
}

public Image(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.setScaleType(ScaleType.FIT_XY);
}

public void loadURL(String url) {
    if(loader!=null)
        loader.cancel(true);
    loader=new AsyncTask<String, Integer, Bitmap>() {
        @Override
        protected Bitmap doInBackground(String... params) {
            URL url = null;
            byte[] bytes = null;
            HttpURLConnection connection=null;
            try {
                url = new URL(params[0]);
                connection=(HttpURLConnection) url.openConnection();
                connection.setRequestProperty("Connection", "close");
                connection.setRequestMethod("GET");
                connection.setUseCaches(true);
                InputStream is = null;
                is=connection.getInputStream();
                bytes = IOUtils.toByteArray(is);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (connection!=null)
                connection.disconnect();
            Bitmap res=null;
            if(!isCancelled() && bytes!=null)
                res=BitmapFactory.decodeByteArray(bytes,0,bytes.length);
            return res;
        }
        @Override
        protected void onPostExecute(Bitmap res) {
            if(res!=null) {
                setImageBitmap(res);
                _animate();
            }
        }
    };
    if (this.getDrawable()!=null) {
        Bitmap bmp=((BitmapDrawable) this.getDrawable()).getBitmap();
        this.setAnimation(null);
        if (bmp!=null) {
            bmp.recycle();
            //Log.d("image","recycled");
        }
        this.setImageBitmap(null);
    }
    /*
    ThreadPoolExecutor e =(ThreadPoolExecutor) Executors.newFixedThreadPool(9);
    Log.d("pool size",e.getActiveCount()+"/"+e.getMaximumPoolSize());
    if (e.getActiveCount() == e.getMaximumPoolSize()) {
    }
    */
    //start loading
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        loader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
    else
        loader.execute(url);
}
private void _animate() {
    ValueAnimator bgAnim= ValueAnimator.ofObject(new IntEvaluator(),0,255);
    bgAnim.setDuration(500);
    bgAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Image.this.getDrawable().setAlpha((int) (animation.getAnimatedValue()));
        }
    });
    bgAnim.start();
}

最佳答案

我之前回答过这个问题(herehereherehere 可能还有其他),我再次为你回答:不要试图重新发明轮子!

图像加载/缓存在 Android 中是一项非常复杂的任务,许多优秀的开发人员已经做到了这一点。线程只是问题之一,但我可以从您的代码中看到您有内存泄漏,没有缓存,因此如果回滚到它,您将再次重新下载图像,HttpURLConnection 很糟糕网络层。

所以,解决这个问题的方法(恕我直言)就是重复使用其他开发人员完成的工作。您应该考虑的图书馆的好例子是:

Picasso 是我的最爱,所以要使用它你只需调用:

Picasso.with(context).load(url).into(imgView);

这一切都为您处理。

关于安卓:java.util.concurrent.ThreadPoolExecutor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44365214/

相关文章:

c++ - 在每个主机线程(多线程 CPU)上创建一个 cuda 流

python - threading.current_thread() 中的 Dummy 是什么?

java - 在 Java 中使变量同步且可见

c - 是否有一种机制可以尝试锁定多个互斥量之一?

android - Firebase 函数抛出错误 com.google.firebase.functions.FirebaseFunctionsException : Response is not valid JSON object

java - 如何在 Android 中水平滚动 ImageView?

android - 使用 Retrofit2 的补丁请求无法在 Android 上运行

android,从网络服务中检索到的文本

android - DDMS 插件不加载 GPX 文件

java - 处理在单独线程中抛出的异常的最佳方法是什么?