简体   繁体   中英

listview is repeating items in customadapter

I am learning android and my code is working fine. It fetches data from website and displays it in list. but when subcat==1 it has 9 items to fetch. It displays 7 distinct item and repeats two items. first it was showing only four that was NullPointerException 5th image didn't had name so it repeated 4 image till 9 times, but now everything is fine still it shows only 7 and repeates 2 after that. Here is my code:

public class JSONAsyncTask extends AsyncTask<String, Void, Void> {
    ProgressDialog pd;
    Context context;


    JSONAsyncTask(Context context) {
        this.context = context;
    }

    @Override
    protected void onPreExecute() {

        super.onPreExecute();
        pd = new ProgressDialog(context);
        pd.setIndeterminate(true);
        pd.setCancelable(false);
        pd.setCanceledOnTouchOutside(false);
        pd.setMessage("Please wait..\nLoading data");
        pd.show();
    }

    @Override
    protected Void doInBackground(String... strings) {
        ArrayList<item> jsonArrayList = new ArrayList<item>();
        try {
            HttpClient client = new DefaultHttpClient();
            HttpGet httpget = new HttpGet("http://avdeal.in/get_all_products.php");
            HttpResponse response = client.execute(httpget);
            HttpEntity entity = response.getEntity();
            String data = EntityUtils.toString(entity);
            JSONObject jsonObject = new JSONObject(data);
            if (jsonObject != null) {
                String posts = jsonObject.getString("products");
                JSONArray postsArray = new JSONArray(posts);
                if (postsArray != null) {
                    if (postsArray.length() > 0) {
                        for (int i = 0; i < postsArray.length(); i++) {
                            JSONObject postsObject = postsArray
                                    .getJSONObject(i);
                            int subcat = postsObject.getInt("subcat_id");

                            if (subcats == subcat) {
                                int id=postsObject.getInt("id");
                                String title = postsObject.getString("product_title");
                                String price = postsObject.getString("product_price");
                                String url = "http://avdeal.in/seller/upload_images/" + postsObject.getString("product_url");


                                list1.add(new item(id, title, price, url));
                            }

                        }
                    }


                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {

        super.onPostExecute(result);
        if (list1 != null) {
            pd.dismiss();
            adp = new actorAdapter(context, R.layout.listview, list1);
            lv.setAdapter(adp);
            adp.notifyDataSetChanged();
        }
        else {
            pd.setMessage("No internet access");
        }
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(itemView.this, "Please Wait " + i + 1, Toast.LENGTH_SHORT).show();
                int id1 = list1.get(i).getId();
                String name = list1.get(i).getName();
                String price = list1.get(i).getPrice();
                Bitmap bitmap = list1.get(i).getImage();

                if (bitmap == null) {
                    Intent intent = new Intent(context, productDetail.class);
                    intent.putExtra("name", name);
                    intent.putExtra("price", price);
                    intent.putExtra("id", id1);
                    intent.putExtra("imagena", 1);
                    startActivity(intent);
                } else {
                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
                    byte[] byteArray = stream.toByteArray();
                    Intent intent = new Intent(context, productDetail.class);
                    intent.putExtra("name", name);
                    intent.putExtra("price", price);
                    intent.putExtra("image", byteArray);
                    intent.putExtra("id", id1);
                    startActivity(intent);
                }
            }
        });
    }
}

private class ImageLoadTask extends AsyncTask<String, String, Bitmap>{
            Context context;
        ImageLoadTask(Context context) {
            this.context = context;
        }
        @Override
        protected Bitmap doInBackground(String... strings) {
            for(int i = 0 ; i < list1.size() ; i++)
            {
                if (list1.get(i).getImage()==null);
                {
                    String url=list1.get(i).getUrl();
                    InputStream is = null;
                    try {
                        is = (InputStream) new URL(url).getContent();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    Bitmap b = BitmapFactory.decodeStream(is);
                    list1.set(i, new item(list1.get(i).getId(), list1.get(i).getName(), list1.get(i).getPrice(), list1.get(i).getUrl() ,b));
                }
            }
                return null;

    }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);

        }
        protected void onPostExecute(Bitmap result){
                super.onPostExecute(result);
                adp = new actorAdapter(context, R.layout.listview, list1);
                lv.setAdapter(adp);
                adp.notifyDataSetChanged();
        }
    }

Can I do anything to lazy load image? I tried creating another AsyncTask , but it shows image when all the images are loaded.

Can I update my ListView as soon as one image is downloaded?

Please help. Can't figure out on my own. These two problems are stopping me from learning more.

public View getView(int position, View convertView, ViewGroup parent){
    inflater= (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
    View v =convertView;
    if (v == null) {

        holder=new ViewHolder();
        v=inflater.inflate(Resource,null);
        holder.name= (TextView) v.findViewById(R.id.titles);
        holder.price= (TextView) v.findViewById(R.id.price);
        holder.img= (ImageView) v.findViewById(R.id.itemimage);
        v.setTag(holder);
        holder.name.setText(list1.get(position).getName());
        holder.price.setText((CharSequence) list1.get(position).getPrice());
        holder.img.setImageBitmap(list1.get(position).getImage());



    }
    else {
        holder = (ViewHolder) v.getTag();
    }


    return v;
}

For the lazy image load, you need to create an AsyncTask for each image not an AsyncTask for all the images (dwonload them one by one in separated AsyncTasks ).

I suggest you to use one of those libraries:

This is an opinon based comparison table between 4 libs (from here ), it might help you to choose:

EDIT:

For your repeated items, change your getView method like that:

public View getView(int position, View convertView, ViewGroup parent){
    inflater= (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
    View v =convertView;
    if (v == null) {

        holder=new ViewHolder();
        v=inflater.inflate(Resource,null);
        holder.name= (TextView) v.findViewById(R.id.titles);
        holder.price= (TextView) v.findViewById(R.id.price);
        holder.img= (ImageView) v.findViewById(R.id.itemimage);
        v.setTag(holder);
    }
    else {
        holder = (ViewHolder) v.getTag();
    }

        holder.name.setText(list1.get(position).getName());
        holder.price.setText((CharSequence) list1.get(position).getPrice());
        holder.img.setImageBitmap(list1.get(position).getImage());    

    return v;
}

You forgot to update the item data when you use a recycled view (v != null).

Yes, it waits because your image loader async task loops over all bitmaps and downloads them then notify the list view to draw, you may make the async task loads only one image at a time. But I suggest you use an imageloader like Picasso or Glide.

Also in your adapter use the viewholder design pattern if you are not using it.

Even though loading images in background after creating the list and refreshing it when loading it is better in terms of user experience that is not the problem you are facing.

I think the problem is with your getView method in your custom adapter, and if you provide it we would be able to know for sure. The problem is that you probably check if an image for an object at a position has a picture, and if so - set it. probably something like so:

public View getView (int position, View convertView, ViewGroup parent)
{
    //some code to create the views and view holder..

    YourItem currentItem = mItems.get(position);
    if (currentItem.getBitmap() != null)
    {

       imageView.setImageBitmap(currentItem.getBitmap());
    }

    //rest of code
}

What you should do is also add an else clause since the picture from the last created view is still populating that ImageView.Either change the ImageView's visibility or it's bitmap.

EDIT:
It should look something like this:

public View getView (int position, View convertView, ViewGroup parent)
{
    //some code to create the views and view holder..

    YourItem currentItem = mItems.get(position);
    if (currentItem.getBitmap() != null)
    {
       imageView.setVisibility(View.VISIBLE);
       imageView.setImageBitmap(currentItem.getBitmap());
    }
    else
    {
       imageView.setVisibility(View.INVISIBLE);
    }

    //rest of code
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM