简体   繁体   English

listview在customadapter中重复项目

[英]listview is repeating items in customadapter

I am learning android and my code is working fine. 我正在学习android,我的代码运行正常。 It fetches data from website and displays it in list. 它从网站获取数据并将其显示在列表中。 but when subcat==1 it has 9 items to fetch. 但是当subcat==1它有9个要提取的项目。 It displays 7 distinct item and repeats two items. 它显示7个不同的项目并重复两个项目。 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. 首先,它只显示四个,即NullPointerException,第5张图像没有名称,因此它重复了4张图像,直到9次,但现在一切都很好,它只显示了7张,然后重复了2张。 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. 我尝试创建另一个AsyncTask ,但是当所有图像都加载后它会显示图像。

Can I update my ListView as soon as one image is downloaded? 下载一张图像后,我是否可以更新ListView

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 ). 对于懒惰的图像加载,你需要创建AsyncTask为每个图像不是AsyncTask对所有图像(dwonload逐一分离状态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: 这是4个库之间的基于opinon的比较表(从此处开始 ),它可以帮助您选择:

EDIT: 编辑:

For your repeated items, change your getView method like that: 对于重复的项目,请按以下方式更改getView方法:

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). 使用回收视图时,您忘记更新项目数据(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. 但我建议您使用像Picasso或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. 我认为问题出在自定义适配器中的getView方法,如果您提供它,我们将可以肯定地知道。 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. 您还应该添加else子句,因为最后创建的视图中的图片仍在填充ImageView。要么更改ImageView的可见性,要么更改其位图。

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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