Android - 异步加载错误的RecyclerView项目数据

时间:2015-10-30 17:12:15

标签: java android android-listview android-asynctask android-recyclerview

我正在创建一个显示商品列表的简单应用。一些项目数据被加载到另一个线程中,但是当我快速滚动时,它会显示错误的数据。

以下是适配器的代码:

package com.lorenzorapetti.pokedex.adapter;

import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.lorenzorapetti.pokedex.R;
import com.lorenzorapetti.pokedex.Utils;
import com.lorenzorapetti.pokedex.model.PokemonSpecies;
import com.lorenzorapetti.pokedex.model.PokemonType;
import com.squareup.picasso.Picasso;

import org.apache.commons.lang3.StringUtils;

import java.lang.ref.WeakReference;
import java.util.List;

import butterknife.Bind;
import butterknife.ButterKnife;

public class PokemonSpeciesAdapter extends RecyclerView.Adapter<PokemonSpeciesAdapter.ViewHolder> {

    private List<PokemonSpecies> mData;
    private Context context;

    public PokemonSpeciesAdapter(Context context, List<PokemonSpecies> data) {
        this.context = context;
        mData = data;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View itemView =((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
                .inflate(R.layout.pokemon_species_item, parent, false);

        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {

        PokemonSpecies item = mData.get(position);
        holder.position = position;

        Picasso.with(context)
                .load(Utils.getSugimoriThumbUrl(item.getIdentifier()))
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher)
                .into(holder.image);

        String identifier = "pokemon_species_" + Utils.convertIdentifier(item.getIdentifier())
                + "_name";
        holder.textPrimary.setText(context.getResources().getString(
                context.getResources().getIdentifier(identifier, "string", context.getPackageName())
        ));
        holder.textSecondary.setText("#" + StringUtils.leftPad(item.getId().toString(), 3, "0"));

        new AsyncLoad(item, holder, position).execute();
    }

    @Override
    public int getItemCount() {
        return mData != null ? mData.size() : 0;
    }

    @Override
    public long getItemId(int position) {
        return mData.get(position).getId();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        @Bind(R.id.pokemon_species_image) ImageView image;
        @Bind(R.id.pokemon_species_name) TextView textPrimary;
        @Bind(R.id.pokemon_species_number) TextView textSecondary;
        @Bind(R.id.pokemon_species_primary_type)
        TextView typePrimary;
        @Bind(R.id.pokemon_species_secondary_type)
        TextView typeSecondary;
        int position;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    private class AsyncLoad extends AsyncTask<Void, Void, AsyncLoad.AsyncItem> {

        private WeakReference<PokemonSpecies> itemData;
        private WeakReference<ViewHolder> viewHolder;
        private int mPosition;

        public AsyncLoad(PokemonSpecies item, ViewHolder viewHolder, int position) {
            this.itemData = new WeakReference<>(item);
            this.viewHolder = new WeakReference<>(viewHolder);
            mPosition = position;
        }

        @Override
        protected AsyncLoad.AsyncItem doInBackground(Void... params) {

            List<PokemonType> pokemonTypes = itemData.get().getDefaultPokemon().getPokemonTypes();
            Log.d("App", "position: " + mPosition + ", holderPosition: " + viewHolder.get().position
                            + ", pokemon: " + itemData.get().getIdentifier() + ", size: " + pokemonTypes.size());
            String primaryIdentifier = "type_" +
                    Utils.convertIdentifier(pokemonTypes.get(0).getType().getIdentifier());
            AsyncLoad.AsyncItem asyncItem = new AsyncLoad.AsyncItem();

            asyncItem.primaryText = context.getResources().getString(
                    context.getResources().getIdentifier(primaryIdentifier + "_name", "string",
                            context.getPackageName()));

            asyncItem.primaryColor = context.getResources().getColor(
                    context.getResources().getIdentifier(primaryIdentifier, "color",
                            context.getPackageName()));

            if (pokemonTypes.size() == 2) {
                String secondaryIdentifier = "type_" +
                        Utils.convertIdentifier(pokemonTypes.get(1).getType().getIdentifier());
                asyncItem.secondaryText = context.getResources().getString(
                        context.getResources().getIdentifier(secondaryIdentifier + "_name", "string",
                                context.getPackageName()));
                asyncItem.secondaryColor = context.getResources().getColor(
                        context.getResources().getIdentifier(secondaryIdentifier, "color",
                                context.getPackageName()));
            }

            return asyncItem;
        }

        @Override
        protected void onPostExecute(AsyncLoad.AsyncItem asyncItem) {
            ViewHolder holder = viewHolder.get();
            if (mPosition == holder.position) {
                holder.typePrimary.setText(asyncItem.primaryText);
                holder.typePrimary.setBackgroundColor(asyncItem.primaryColor);
                if (asyncItem.secondaryText != null) {
                    holder.typeSecondary.setText(asyncItem.secondaryText);
                    holder.typeSecondary.setBackgroundColor(asyncItem.secondaryColor);
                }
            }
        }

        protected class AsyncItem {
            String primaryText;
            int primaryColor;
            String secondaryText;
            int secondaryColor;
        }
    }

}

如何加载确切的数据?

0 个答案:

没有答案