【问题标题】:listview is repeating items in customadapterlistview 在 customadapter 中重复项目
【发布时间】:2015-08-20 22:42:39
【问题描述】:

我正在学习 android,我的代码运行良好。它从网站获取数据并将其显示在列表中。但是当subcat==1 它有 9 个项目要获取。它显示 7 个不同的项目并重复两个项目。首先它只显示了 4 个 NullPointerException 第 5 个图像没有名称,所以它重复了 4 个图像直到 9 次,但现在一切都很好,它只显示 7 个,然后重复 2 个。这是我的代码:

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();
        }
    }

我可以做些什么来延迟加载图像吗?我尝试创建另一个AsyncTask,但它会在加载所有图像时显示图像。

我可以在下载一张图片后立即更新我的ListView 吗?

请帮忙。我自己想不通。这两个问题阻碍了我学习更多。

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;
}

【问题讨论】:

    标签: java android json listview android-asynctask


    【解决方案1】:

    对于延迟图像加载,您需要为每个图像创建一个AsyncTask,而不是为所有图像创建一个AsyncTask(在分隔的AsyncTasks 中逐一加载它们)。

    我建议您使用其中一个库:

    这是一个基于意见的 4 个库之间的比较表(来自here),它可能会帮助您选择:

    编辑:

    对于您重复的项目,请像这样更改您的 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;
    }
    

    您在使用回收视图时忘记更新商品数据(v != null)。

    【讨论】:

    • 重复列表怎么样??
    • 是的,现在可以了。异步任务怎么样,你能告诉我如何为每个图像调用异步。当我从主线程调用它时。它强制停止,我试图在主线程中保持第一个异步并为另一个图像中的每个图像调用异步它不加载任何内容并捕获异常。告诉我如何在不使用第三方库的情况下实现
    • 你不应该在主线程中下载图像,这会导致 ANR 并且你的应用程序会崩溃。使用库更好更容易,因为背后有很多优化......否则在 getView() 方法中,您需要为每个项目启动一个 AsyncTask 并将 ImageView 和图像 URL 作为参数传递。当 AsyncTask 完成下载后,您将获得当前项目的图像和 ImageView。
    • 不,我想在主线程中加载其余数据,然后在 asynctask 中加载图像,但我现在明白这是由于严格模式。我想我将不得不使用该库,因为优化也是一个问题。在所有这些中你会推荐哪个库?
    • 这取决于你需要什么,它们几乎相等......但我个人更熟悉 Universal-Image-Loader。
    【解决方案2】:

    是的,它会等待,因为您的图像加载器异步任务循环遍历所有位图并下载它们,然后通知列表视图进行绘制,您可以使异步任务一次仅加载一个图像。 但我建议你使用像 Picasso 或 Glide 这样的图像加载器。

    如果你不使用它,也可以在你的适配器中使用 viewholder 设计模式。

    【讨论】:

    • 我正在使用查看器,它正在工作。我已经从布局中设置了一个默认图像,如果图像 == null 则设置。首先我需要处理重复的图像,然后我将专注于效率和延迟加载
    【解决方案3】:

    即使在创建列表后在后台加载图像并在加载时刷新它在用户体验方面会更好,但这不是您面临的问题。

    我认为问题在于您的自定义适配器中的 getView 方法,如果您提供它,我们将能够确定。问题是您可能会检查某个位置的对象的图像是否有图片,如果有,请设置它。大概是这样的:

    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
    }
    

    您还应该添加一个 else 子句,因为上次创建的视图中的图片仍在填充该 ImageView。要么更改 ImageView 的可见性,要么更改它的位图。

    编辑:
    它应该看起来像这样:

    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
    }
    

    【讨论】:

    • 这就是困扰我的地方。代码是正确的,logcat 只显示无用的日志。没有例外没有错误。
    • 我不认为你明白我在说什么。您需要添加一个 else 子句并设置 imageView 可见性。查看我编辑的消息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    相关资源
    最近更新 更多