【问题标题】:RecyclerView load images non-linearlyRecyclerView 非线性加载图像
【发布时间】:2015-12-13 19:17:24
【问题描述】:

我的问题是,我有一个 RecyclerView,在此我加载音乐专辑的专辑封面,图像加载完美,但加载是线性的,所以,当缓慢拖动 RecyclerView 时,工作正常,但是当我快速拖动 RecyclerView,加载图像需要很长时间。 我使用 AsyncTask,但我不明白为什么线程一个接一个地线性运行。

这是创建和绑定我的 ViewHolder

@Override
public AdaptadorAlbumes.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_album, parent, false);
    ViewHolder vh = new ViewHolder(v, actividad);
    return vh;
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    cursor.moveToPosition(position);
    holder.imgVwPortada.setImageBitmap(Datos.getPortadaDefault());
    holder.imgVwPortada.setTag(position);
    holder.txtNombre.setText(cursor.getString(cursor.getColumnIndex(Constantes.ALB_NOMBRE)));
    holder.txtArtista.setText(cursor.getString(cursor.getColumnIndex(Constantes.ALB_ARTISTA)));
    ObtenerPortada oP = new ObtenerPortada(cursor.getInt(cursor.getColumnIndex(Constantes.ALB_ID)), holder.imgVwPortada);
    oP.execute(Datos.getActividadActual());
}

这是我的 ViewHolder

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private Activity actividad;
    public TextView txtNombre;
    public TextView txtArtista;
    public ImageView imgVwPortada;
    public RelativeLayout container;

    public ViewHolder(View v, Activity actividad) {
        super(v);
        this.actividad = actividad;
        container = (RelativeLayout) itemView.findViewById(R.id.artista);
        txtNombre = (TextView)v.findViewById(R.id.txtNombre);
        txtArtista = (TextView)v.findViewById(R.id.txtArtista);
        imgVwPortada = (ImageView)v.findViewById(R.id.imgVwPortada);
        v.setOnClickListener(this);
    }
}

这是我的 AsyncTask 类

private class ObtenerPortada extends AsyncTask<Activity, Void, Bitmap> {

    long ID;
    private ImageView imv;
    private String path;

    public ObtenerPortada(long ID, ImageView imv) {
        this.ID = ID;
        this.imv = imv;
        this.path = imv.getTag().toString();
    }

    @Override
    protected Bitmap doInBackground(Activity... params) {
        WeakReference<Bitmap> bitmap = null;
        try {
            Uri trackUri = ContentUris.withAppendedId(Constantes.uriAlbumesArt, ID);
            Bitmap bit = MediaStore.Images.Media.getBitmap(params[0].getContentResolver(), trackUri);
            bitmap = new WeakReference<>(ReducirImagenes.reducirBitmap(200, 200, bit));
        } catch (Exception e) {
            bitmap = new WeakReference<>(Datos.getPortadaDefault());
            return null;
        }
        return bitmap.get();
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        super.onPostExecute(result);
        if (!imv.getTag().toString().equals(path)) {
            return;
        }
        if(result != null && imv != null){
            imv.setImageBitmap(result);
            imv.setAlpha(0f);
            imv.setVisibility(View.VISIBLE);
            imv.animate().alpha(1f).setDuration(200).setListener(null);
        }
    }
}

这是我的问题的一个例子:https://www.youtube.com/watch?v=x_1yXh6J2Ks

【问题讨论】:

    标签: android android-asynctask android-recyclerview


    【解决方案1】:

    AsyncTask 默认在单个后台线程上串行执行。您可以改用executeOnExecutor() 并提供您自己的Executor 实例(例如ThreadPoolExecutor)来覆盖此行为。

    此外,跟踪 ViewHolder 中的任务可能会有所帮助,这样当它被回收时,如果该任务尚未开始,您可以取消上一个任务。

    【讨论】:

    • +1 用于检查图像加载仍然是必要的。您可以在 onPostExecute 中重复使用现有的检查,并在 doInBackground 中执行此操作以避免加载不再可见的内容。
    【解决方案2】:

    Android 对默认情况下可以运行的 AsyncTask 数量有限制,并且默认情况下 AsyncTask 以线性方式运行。 LinearExucutions 通过执行 onExecutor 被绕过,同时为了避免限制你必须创建自己的线程池。

     BlockingQueue<Runnable> workQueue;
     Executor threadPoolExecutor;
    
    workQueue = new LinkedBlockingQueue<Runnable>(maximumPoolSize);
    threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,    maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue);
    

    现在用 executor 执行 AsyncTask

     new AsyncTaskTest().executeOnExecutor(threadPoolExecutor,null, null, null);
    

    这是PhotoManager 的示例,您还可以使用一些在JavaHeap 之外存储图像的高级图像加载库-来自Facebook 的Fresco Library。 Fresco 还处理不加载不可见的图像。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多