Hossein Mobasher
Hossein Mobasher

Reputation: 4472

ListView and ReferenceHolder

I am working on Download Manager application, and my structure is as follow :

I have two package that first one is all activity and foreground about utilities. (Activities, ListAdapters and etc. ) And the second is package includes all of background active classes. ( Download Threads include FTP, HTTP, HTTPS and etc. ).

Also, to keep details of download files, I defined the class such below :

public class DownloadInfo {
    public DownloadInfo(String url, int connection, int progress, boolean status) {
        this.M_url = url;
        this.M_connection = connection;
        this.M_progress = progress;
        this.B_status = status;
    }

    String M_url;
    int M_connection;
    int M_progress;
    boolean B_status;
}

And also the ArrayList<DownloadInfo> that keeps downloaded/downloading file lists. To initialize the ListView, I've declared the class that inherits from ArrayAdapter<DownloadInfo> as following :

public class FillDownloadList extends ArrayAdapter<DownloadInfo> {
    private ArrayList<DownloadInfo> M_dlList;
    private Context M_context;
    private DownloadViewHolder holder;

    public FillDownloadList(Context context, ArrayList<DownloadInfo> dlList) {
        super(context, R.layout.download_item, dlList);
        this.M_dlList = dlList;
        this.M_context = context;
    }

    public View getView(final int position, View convertView,
            android.view.ViewGroup parent) {
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.download_item, parent,
                    false);

            holder = new DownloadViewHolder();

            holder.activityButton = ((Button) convertView
                    .findViewById(R.id.dl_button));

            holder.linkText = ((TextView) convertView
                    .findViewById(R.id.link_textview));
            holder.speedText = ((TextView) convertView
                    .findViewById(R.id.speed_textview));
            holder.percentBar = ((ProgressBar) convertView
                    .findViewById(R.id.dl_progressbar));

            convertView.setTag(holder);
        } else {
            holder = (DownloadViewHolder) convertView.getTag();
        }

        holder.linkText.setText(this.M_dlList.get(position).M_name);
        holder.percentBar.setProgress(this.M_dlList.get(position).M_progress);

    // Doing some initializing and setting the download thread based on DownloadInfo `B_status` parameter.

        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e("log", M_dlList.get(position).M_url);
                Log.e("log", System.out.println(holder.linkText.getText());
            }
        });

        return convertView;
    }

    private static class DownloadViewHolder {
        TextView linkText;
        TextView speedText;
        Button activityButton;
        ProgressBar percentBar;
    }
}

To increase the performance of Adapter, I am declaring the DownloadViewHolder classes to keeping the reference (To avoid unnecessary inflating). When I clicked on the items of ListView, the LogCat output is not understandable for me :-/ ! Because the second Log.e always print the last item that added to listView. What is wrong?

Could any one please guide me to solve ?

Thanks in advance :)

Upvotes: 1

Views: 53

Answers (1)

logcat
logcat

Reputation: 3454

There is an issue with your code, When you click happends, click listener pick up holder, but it's holder from last viewed list item, to prevent it, you have to create holder in getView() and pass it to onClickListener via constructor.

Upvotes: 1

Related Questions