使用带有自定义 baseadapter 的 arraylist 错误地删除列表视图项位置

Posted

技术标签:

【中文标题】使用带有自定义 baseadapter 的 arraylist 错误地删除列表视图项位置【英文标题】:Wrong remove listview item position using arraylist with custom baseadapter 【发布时间】:2020-04-08 08:51:43 【问题描述】:

当我单击项目位置时,我尝试使用 ArrayList 删除 ListView 项目。但是,它总是得到错误的删除项目位置。为什么从底部删除该项目?如果我单击ListView 中的任意位置,该位置仍会从底部的项目中删除。有人可以帮我解决这个问题吗?

这就是我从数据库中获取数据的方式

public static ArrayList<Integer> arrIdJob = new ArrayList<Integer>();

myJSON = json.getJSONArray(TAG_record);

for (int i = 0; i < myJSON.length(); i++) 
    JSONObject c = myJSON.getJSONObject(i);
    arrIdJob.add(Integer.parseInt(c.getString("id_jobpost")));

我在onCreateViewsetOnItemClickListener 中使用片段

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 
        arrIdJob.remove(i);
        adapterListHome.notifyDataSetChanged();
    
);

这是我的Adapter 扩展BaseAdapter

public class AdapterListHome extends BaseAdapter 

    private Activity activity;
    private ArrayList<CustomRowClass> listData;
    private LayoutInflater layoutInflater;
    private Context context;

    public AdapterListHome(Context context, ArrayList<CustomRowClass> listData) 
        this.listData = listData;
        layoutInflater = LayoutInflater.from(context);
        this.context = context;
    


    public AdapterListHome(Activity act) 
        this.activity = act;
    

    public int getCount() 
        return HomeFragment.arrIdJob.size();

    

    public Object getItem(int position) 
        return position;
    

    public long getItemId(int position) 
        return position;
    

    @Override
    public int getViewTypeCount() 
        return getCount();
    

    @Override
    public int getItemViewType(int position) 
        return position;
    

    @SuppressLint("SetTextI18n")
    public View getView(final int position, View convertView, ViewGroup parent) 

        ViewHolder holder;

        if(convertView == null)
            LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.desain_view, null);
            holder = new ViewHolder();

            convertView.setTag(holder);

         else 
            holder = (ViewHolder) convertView.getTag();
        

        holder.tvJobTitle = (TextView) convertView.findViewById(R.id.tv_jobtitile);
        holder.tvCompanyName = (TextView) convertView.findViewById(R.id.tv_companyname);
        holder.tvState = (TextView) convertView.findViewById(R.id.tv_state);
        holder.tvSalary = (TextView) convertView.findViewById(R.id.tv_minsal);

        //for key
        holder.keyIdUser = (TextView) convertView.findViewById(R.id.key_iduser);
        holder.keyIdJob = (TextView) convertView.findViewById(R.id.key_idjob);
        holder.keyIdCompany = (TextView) convertView.findViewById(R.id.key_idcompany);
        holder.keyQualification = (TextView) convertView.findViewById(R.id.key_qualification);
        holder.keyDesc = (TextView) convertView.findViewById(R.id.key_desc);

        //set
        holder.tvJobTitle.setText(HomeFragment.arrJobTitle.get(position));
        holder.tvCompanyName.setText(HomeFragment.arrCompanyName.get(position));
        holder.tvState.setText(HomeFragment.arrState.get(position));
        holder.tvSalary.setText(toRupiah(HomeFragment.arrMinSal.get(position))+" - "+toRupiah(HomeFragment.arrMaxSal.get(position)));
        //set for key

        holder.keyIdJob.setText(HomeFragment.arrIdJobStr.get(position));
        holder.keyIdCompany.setText(HomeFragment.arrIdCompany.get(position));
        holder.keyQualification.setText(HomeFragment.arrQualification.get(position));
        holder.keyDesc.setText(HomeFragment.arrDesc.get(position));


        //   Picasso.get().load(Config.PATH_URL_IMG_CAT+ ListMenuActivity.IMAGE.get(position)).into(holder.imgThumb);

        return convertView;
    

    static class ViewHolder 
        TextView tvJobTitle, tvCompanyName, tvState, tvSalary;
        TextView keyIdUser, keyIdJob, keyIdCompany, keyQualification, keyDesc;
        String data;
        //ImageView imgThumb;
    

    private String toRupiah(String nominal)
        String hasil = "";
        DecimalFormat toRupiah = (DecimalFormat) DecimalFormat.getCurrencyInstance();
        DecimalFormatSymbols formatAngka = new DecimalFormatSymbols();
        formatAngka.setCurrencySymbol("Rp. ");
        formatAngka.setMonetaryDecimalSeparator(',');
        toRupiah.setDecimalFormatSymbols(formatAngka);
        hasil = toRupiah.format(Double.valueOf(nominal));
        return hasil;
       
    

【问题讨论】:

【参考方案1】:

看起来您正在使用包含整数的ArrayList,并且您正试图通过项目的索引删除项目。 ArrayList.remove() 函数将 indexelement 从列表中删除。在您的情况下,由于它们都是int,这应该通过此处提供的索引 - arrIdJob.remove(i); 从您的ArrayList 中删除元素。我认为这很好。

我看到的问题是您的数据结构以及您如何保存数据以便在ListView 中显示它们。你的HomeFragment 中有很多ArrayLists,从arrIdJob 中删除数据实际上也需要其他ArrayLists 来清理自己。因为它们都被引用并因此在您的适配器中使用。

因此,仅从 arrIdJob 中删除 id 在您的情况下是不够的,因为您还必须从其他列表中删除该特定项目才能从列表中完全删除该项目。因此,您对项目单击侦听器的实现可能如下所示。

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 
        arrIdJob.remove(i);

        // Clear the other lists!
        arrJobTitle.remove(i);
        arrCompanyName.remove(i);
        arrState.remove(i);
        arrMinSal.remove(i);
        arrIdJobStr.remove(i);
        arrQualification.remove(i);
        arrIdCompany.remove(i);
        arrDesc.remove(i);

        adapterListHome.notifyDataSetChanged();
    
);

删除所有这些实际上应该从列表中完全删除该项目,并且您应该摆脱任何异常行为。

我还建议以面向对象的方式设置您的数据。话虽如此,我宁愿创建一个像下面这样的对象。

public class CompanyAndJob 
    public int jobId; 
    public int companyName; 
    public int jobStr;
    public int qualification;
    // .... Other items

然后,我将创建一个 CompanyAndJobList 对象,以通过适配器的构造函数传递给适配器。这将使整体实现更加模块化。

另外,如果您获得我建议的对象列表,您可能还需要修改适配器的其他部分。例如,您需要修改getItem,如下所示。

public CompanyAndJob getItem(int position) 
    return listOfCompanyAndJobs.get(position);

我希望你能明白。

【讨论】:

很高兴知道我可以提供帮助。如果答案正确,您可以接受。谢谢!【参考方案2】:

将适配器中的 getItem(int position) 替换为

public Object getItem(int position) 
    return listData.get(position);

另外,请确保您在适配器和ItemClickListener 中引用相同的列表。

【讨论】:

以上是关于使用带有自定义 baseadapter 的 arraylist 错误地删除列表视图项位置的主要内容,如果未能解决你的问题,请参考以下文章

Android - 带有自定义 BaseAdapter 的 Gridview,在位置获得点击视图

带有 BaseAdapter 的 ListView

ListView 不显示带有 BaseAdapter 的 ImageButton

如何使用 baseadapter 自定义列表视图

如何在android中使用baseadapter刷新自定义列表视图

使用 CardView BaseAdapter OnItemClick 自定义 ListView