Android 异步任务加载映像回收视图
我正在尝试创建一个类似的应用程序: 首先,我从数据库中加载CardView的所有信息 图像的标题、描述和图像的URL。 当我将所有信息放在RecyclerView中时,(标题和描述)显示正确,但是对于图像,我创建了一个AsyncTask类来从URL加载图像,使用户不用等待应用程序响应太久 如果用户缓慢滚动图像,则图像加载正确且一切正常,但如果我滚动到快速,则会出现一些问题,例如,项目3中显示的图像将显示在最后一个项目中,直到最后一个项目的图像加载并刷新 下面是我加载映像的适配器的一些代码:Android 异步任务加载映像回收视图,android,image,android-asynctask,android-recyclerview,android-cardview,Android,Image,Android Asynctask,Android Recyclerview,Android Cardview,我正在尝试创建一个类似的应用程序: 首先,我从数据库中加载CardView的所有信息 图像的标题、描述和图像的URL。 当我将所有信息放在RecyclerView中时,(标题和描述)显示正确,但是对于图像,我创建了一个AsyncTask类来从URL加载图像,使用户不用等待应用程序响应太久 如果用户缓慢滚动图像,则图像加载正确且一切正常,但如果我滚动到快速,则会出现一些问题,例如,项目3中显示的图像将显示在最后一个项目中,直到最后一个项目的图像加载并刷新 下面是我加载映像的适配器的一些代码: @
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
if (holder instanceof EventosViewHolder) {
......
//Load the image (getFoto() get drawable)
if (eventoInfoAux.getFoto()==null){
CargarImagen cargarImagen = new CargarImagen(((EventosViewHolder) holder).vRelativeLayout,eventoInfo,position);
cargarImagen.execute();
}else{
((EventosViewHolder) holder).vRelativeLayout.setBackground(eventoInfoAux.getFoto());
}
}
}
下面是CargarImagen类的代码:
//Clase para cargar imagenes con una tarea asíncrona desde un url de la imagen
public class CargarImagen extends AsyncTask<String, String, Boolean>{
//RelativeLayout donde se introduce la imagen de fondo
RelativeLayout relativeLayout=null;
//EventoInfo para obtener la url de la imagen
List<EventoInfo> eventoInfo=null;
//Posición de la imagen clicada
int i;
//Se cargan todos los valores de las variables necesarias desde los datos introducidos
public CargarImagen(RelativeLayout relativeLayout,List<EventoInfo> eventoInfo,int i) {
this.relativeLayout = relativeLayout;
this.eventoInfo = eventoInfo;
this.i = i;
}
//Pintamos el fondo de gris mientras se está cargando la imagen
@Override
protected void onPreExecute() {
super.onPreExecute();
relativeLayout.setBackgroundResource(R.color.fondo_card_view);
}
//Se realiza la carga de la imagen en segundo plano
@SuppressWarnings("deprecation")
@Override
protected Boolean doInBackground(String... params) {
//Necesario para hacer la llamada a la red
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
//obtenemos la imagen con el metodo getBitmapFromURL
Bitmap myImage = getBitmapFromURL(eventoInfo.get(i).url);
//Si se tiene imagen se pinta, si no no se hace nada
if (myImage !=null){
Drawable dr = new BitmapDrawable(myImage);
eventoInfo.get(i).setFoto(dr);
return true;
}
return false;
}
//Al finalizar la carga de la imagen se pinta el fondo del relative layout
protected void onPostExecute(Boolean result) {
if(result){
relativeLayout.setBackground(eventoInfo.get(i).foto);
}
}
//Metodo para obtener un bitmap desde una url
public Bitmap getBitmapFromURL(String imageUrl) {
try {
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
//在图像的url中,我们可以看到一幅图像
公共类CargarImagen扩展异步任务{
//相对地,你不需要介绍你的照片
RelativeLayout RelativeLayout=null;
//关于获取图像url的事件
List eventoInfo=null;
//克利卡达图像库
int i;
//在引入数据时,变量的必要性
公共汽车图像(RelativeLayout RelativeLayout,列表事件信息,int i){
this.relativeLayout=relativeLayout;
this.eventoInfo=eventoInfo;
这个。i=i;
}
//平塔莫斯·埃尔丰多·德格里斯·米恩特拉斯·埃斯塔卡甘多·拉伊梅根
@凌驾
受保护的void onPreExecute(){
super.onPreExecute();
relativeLayout.setBackgroundResource(R.color.fondo\u卡视图);
}
//这是一个平面上的图像
@抑制警告(“弃用”)
@凌驾
受保护的布尔doInBackground(字符串…参数){
//这是红色的
StrictMode.ThreadPolicy policy=新建StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(策略);
//从URL获取图像的方法
位图myImage=getBitmapFromURL(eventoInfo.get(i.url));
//这是一张照片,没有这张照片
if(myImage!=null){
Drawable dr=新的位图Drawable(myImage);
eventoInfo.get(i).setFoto(dr);
返回true;
}
返回false;
}
//最终确定了相关布局图中的图像
受保护的void onPostExecute(布尔结果){
如果(结果){
相对挫折(eventoInfo.get(i.foto));
}
}
//我知道你的地址
公共位图getBitmapFromURL(字符串imageUrl){
试一试{
URL URL=新URL(imageUrl);
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream输入=连接。getInputStream();
位图myBitmap=BitmapFactory.decodeStream(输入);
返回我的位图;
}捕获(IOE异常){
e、 printStackTrace();
返回null;
}
}
}
我可以给你.apk文件,你就可以看到问题了
提前谢谢。:)
这里是我的适配器的完整代码
import java.util.List;
import com.abdevelopers.navarraongoing.R;
import com.abdevelopers.navarraongoing.detalle.DetalleActivity;
import android.content.Intent;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class EventosAdapter extends RecyclerView.Adapter<ViewHolder>{
private static final int TYPE_EVENTO = 0;
private static final int TYPE_FOOTER = 1;
//lista de eventos
private List<EventoInfo> eventoInfo;
private String usuario;
private EventoInfo eventoInfoAux;
private PaginaInicioActivity paginaInicio;
//Se pasan los valores necesarios para obtener información de los eventos
public EventosAdapter(List<EventoInfo> eventoInfo, String usuario, PaginaInicioActivity paginaInicio ) {
this.eventoInfo = eventoInfo;
this.usuario = usuario;
this.paginaInicio = paginaInicio;
}
//Metodo para obtener el numero de items en la lista que introducimos
@Override
public int getItemCount() {
return eventoInfo.size();
}
@Override
public int getItemViewType(int position) {
if (position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_EVENTO;
}
}
//Se asignan los datos a cada uno de los elementos de la cardview
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
if (holder instanceof EventosViewHolder) {
//Obtenemos cada uno de los eventos
eventoInfoAux = eventoInfo.get(position);
//eventosViewHolder = holder;
//Introducimos el título del evento
((EventosViewHolder) holder).vTitle.setText(eventoInfoAux.titulo);
//Introdicumos la fecha y el lugar del evento
((EventosViewHolder) holder).vFechaLugar.setText(eventoInfoAux.fecha+", "+eventoInfoAux.lugar);
//obtenemos el numero de asistentes al evento
String asistentes = Integer.toString(eventoInfoAux.asistentes);
((EventosViewHolder) holder).vLikeButton.setText(asistentes);
//Se pinta el boton de like dependiendo de si está o no like
if(eventoInfoAux.like){
((EventosViewHolder) holder).vLikeButton.setBackgroundResource(R.drawable.button_like_liked);
}else{
((EventosViewHolder) holder).vLikeButton.setBackgroundResource(R.drawable.button_like);
}
//Se pinta la imagen del evento dependiendo de si está en la base de datos o no
if (eventoInfoAux.foto==null){
CargarImagen cargarImagen = new CargarImagen(((EventosViewHolder) holder).vRelativeLayout,eventoInfo,position);
cargarImagen.execute();
}else{
((EventosViewHolder) holder).vRelativeLayout.setBackground(eventoInfoAux.foto);
}
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_EVENTO) {
View view = LayoutInflater.
from(parent.getContext()).
inflate(R.layout.evento_card_view, parent, false);
return new EventosViewHolder(view,eventoInfo,usuario,paginaInicio);
} else if (viewType == TYPE_FOOTER) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.pie_carga_pagina_inicio, parent, false);
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
return new FooterViewHolder(view);
}
return null;
}
//Clase para crear el footerview donde se cargan más eventos
class FooterViewHolder extends ViewHolder {
public FooterViewHolder(View view) {
super(view);
}
}
//Clase para crear los eventos con su cardview
class EventosViewHolder extends ViewHolder implements View.OnClickListener{
private TextView vTitle;
private TextView vFechaLugar;
private Button vLikeButton;
private RelativeLayout vRelativeLayout;
private List<EventoInfo> eventoInfo;
private String usuario;
private LikesDDBB likesManager;
private PaginaInicioActivity paginaInicio;
private CardView vCardView;
public EventosViewHolder(View itemView,List<EventoInfo> eventoInfo,String usuario,
PaginaInicioActivity paginaInicio) {
super(itemView);
this.paginaInicio = paginaInicio;
this.usuario = usuario;
vTitle = (TextView)itemView.findViewById(R.id.titulo);
vFechaLugar = (TextView) itemView.findViewById(R.id.fecha_lugar);
vLikeButton = (Button) itemView.findViewById(R.id.like_button);
vRelativeLayout = (RelativeLayout) itemView.findViewById(R.id.layout_cardview);
vCardView = (CardView)itemView.findViewById(R.id.card_view);
//Valores por defecto de los botones y del fondo en caso de no haber like ni foto
vLikeButton.setBackgroundResource(R.drawable.button_like);
vRelativeLayout.setBackgroundResource(R.color.fondo_card_view);
vLikeButton.setOnClickListener(this);
vCardView.setOnClickListener(this);
vLikeButton.setTag("boton");
vCardView.setTag("evento");
this.eventoInfo = eventoInfo;
}
@SuppressWarnings("deprecation")
@Override
public void onClick(View v) {
if(v.getTag().equals("boton")){
likesManager = new LikesDDBB(this.eventoInfo.get(getPosition()).like, usuario,
vLikeButton, getPosition(), eventoInfo, paginaInicio);
likesManager.execute();
}else if(v.getTag().equals("evento")){
Intent inicion = new Intent(paginaInicio,DetalleActivity.class);
paginaInicio.startActivity(inicion);
}
}
}
//Para obtener la lista de eventos desde la clase PaginaInicioActivity
public List<EventoInfo> getEventoInfo() {
return eventoInfo;
}
public void setEventoInfo(List<EventoInfo> eventoInfo) {
this.eventoInfo = eventoInfo;
}
}
import java.util.List;
导入com.abdevelopers.navara.R;
导入com.abdevelopers.navarrainuousing.detalle.DetalleActivity;
导入android.content.Intent;
导入android.support.v7.widget.CardView;
导入android.support.v7.widget.RecyclerView;
导入android.support.v7.widget.RecyclerView.ViewHolder;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入android.view.ViewGroup.LayoutParams;
导入android.widget.Button;
导入android.widget.RelativeLayout;
导入android.widget.TextView;
公共类EventsAdapter扩展了RecyclerView.Adapter{
私有静态final int TYPE_EVENTO=0;
私有静态final int TYPE_FOOTER=1;
//事件列表
私有列表事件信息;
私有字符串usuario;
私人事件信息事件信息;
私人Paginicio活动Paginicio;
//在事件信息的获取过程中,必须对事件进行必要的评估
公共事件适配器(列出事件信息、字符串usuario、paginanicio活动paginanicio){
this.eventoInfo=eventoInfo;
this.usuario=usuario;
this.paginacio=paginacio;
}
//我想知道介绍清单中项目的编号
@凌驾
public int getItemCount(){
返回eventoInfo.size();
}
@凌驾
public int getItemViewType(int位置){
如果(位置+1==getItemCount()){
返回类型\页脚;
}否则{
返回类型_EVENTO;
}
}
//这是一张卡德维尤元素的卡片
@凌驾
公共无效onBindViewHolder(ViewHolder,最终int位置){
if(事件的持有者实例OSVIEWHOLDER){
//这是一个非常重要的事件
eventoinfaux=eventoInfo.get(位置);
//eventosViewHolder=holder;
//事件简介
((EventosViewHolder)holder.vTitle.setText(eventoinfaux.titulo);
//事件简介
((EventosViewHolder)holder.vFechaLugar.setText(eventoinfaux.fecha+”,“+eventoinfaux.lugar);
//事件发生次数
字符串asistentes=Integer.toString(eventoinfaux.asistentes);
((EventosViewHolder)holder.vLikeButton.setText(asistentes);
//这是一个类似的例子
if(eventoinfaux.like){
((EventosViewHolder)holder.vLikeButton.setBackgroundResource(R.drawable.button_like_like_like);
}否则{
((EventosViewHolder)holder.vLikeButton.setBackgroundResource(R.drawable.button_-like);
}
//这是一个事件的图像,它依赖于第二个日期的基础
if(eventoinfaux.foto==null){
CargarImagen CargarImagen=新的CargarImagen(((EventosViewHolder)支架)。vRelativeLa