【问题标题】:Use of ViewHolder is giving unusual output使用 ViewHolder 会产生异常的输出
【发布时间】:2013-05-25 14:47:47
【问题描述】:

我正在使用custom list view,其中每行包含两个图像视图和一个文本视图。我在custom adaptergetView() 方法中使用view holder。我在getview() 方法中的一个图像视图上设置了Onclicklistener(),也只在listview 的活动中设置了onSelectItemListener()。现在,当我点击imageview 时,它会影响特定的行,但是当我向下滚动时,我会得到随机行的影响。当我单击打开imageview 时会发生这种情况,但是当我不使用viewholder 时不会发生这种情况。我真的不明白为什么会这样。请帮我。

这是我的getView()方法代码:

public View getView(int position, View convertView, ViewGroup parent) {
    final int myposition = position;
    // TODO Auto-generated method stub

    if (convertView == null) {
        LayoutInflater inflater = LayoutInflater.from(context);
        convertView = inflater.inflate(R.layout.fileviewrowfrnview_layout, null);
        ViewHolder holder = new ViewHolder();
        holder.icon = (ImageView) convertView.findViewById(R.id.icon2);
        holder.text = (TextView) convertView.findViewById(R.id.file_name2);
        holder.download = (ImageView) convertView.findViewById(R.id.play_buttonOropen2);
        convertView.setTag(holder);
    }
    final ViewHolder holder = (ViewHolder) convertView.getTag();


    holder.download.setOnClickListener(new View.OnClickListener() {

        @
        Override
        public void onClick(View v) {
            // TODO Auto-generated method stub  
            if (frnshare_list.get(myposition).getFileType().trim()
                .equalsIgnoreCase("file")) {
                // it is file
                if (frnshare_list.get(myposition).getDownloadStatus().trim()
                    .equalsIgnoreCase("0")) {
                    // is is not a downloaded file do download it
                    holder.icon.setVisibility(View.GONE);
                    holder.download.setVisibility(View.GONE);
                    holder.text.setTextSize(14);

                    Log.e("file to be download", "" + frnshare_list.get(myposition).getFileName());
                    if (frnshare_list.get(myposition).getFileName().length() > 15)
                        holder.text.setText(frnshare_list.get(myposition).getFileName().subSequence(0, 15) + " will be downloaded soon.");
                    else
                        holder.text.setText(frnshare_list.get(myposition).getFileName() + " will be downloaded soon.");
                    UserService us = new UserService(context);
                    Frnshared fdto = frnshare_list.get(myposition);
                    fdto.setDownloadStatus("2"); // in queue
                    fdto.setMessageId("0");
                    us.updateDowloadStatusById(fdto);
                    us.updatemsgIdbyId(fdto);
                    if (CommonUtility.isNetworkAvailable(context)) {
                        AsyncTask < Void, Void, Void > httpconnection = new AsyncTask < Void, Void, Void > () {@
                            Override
                            protected Void doInBackground(Void...params) {
                                // TODO Auto-generated method stub
                                NetworkCommunication nc = new NetworkCommunication(
                                    context);
                                try {
                                    UserService us = new UserService(
                                        context);
                                    Frnshared fdto = frnshare_list
                                        .get(myposition);
                                    Log.i("file to be download", "" + fdto.getFileName());
                                    fdto.setDownloadStatus("2"); // in queue
                                    fdto.setMessageId("0");
                                    us.updateDowloadStatusById(fdto);
                                    us.updatemsgIdbyId(fdto);
                                    String response = nc
                                        .MyHttpPostDownload(frnshare_list
                                        .get(myposition));
                                    ParsersAndDataInsertion.DownloadRequestResponseParser(
                                        response, context,
                                        frnshare_list.get(myposition));

                                } catch (IOException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                                // http call for download
                                return null;
                            }
                        }.execute(null, null, null);
                    }
                    Apitable(adto);
                }

            } else if (frnshare_list.get(myposition)
                .getDownloadStatus().equalsIgnoreCase("1")) {

                Intent intent = new Intent();
                intent.setAction(android.content.Intent.ACTION_VIEW);
                File file = new File(frnshare_list.get(myposition)
                    .getFileLocation());
                intent.setDataAndType(Uri.fromFile(file), "audio/*");

                context.startActivity(intent);

            } else if (frnshare_list.get(myposition)
                .getDownloadStatus().equalsIgnoreCase("2")) {
                Toast.makeText(context, "already request snet", 2000)
                    .show();
            }
        } else if (frnshare_list.get(myposition).getFileType()
            .equalsIgnoreCase("folder")) {}

    }
    });

// view purpose


String file_name = frnshare_list.get(position).getFileName();
if (file_name.length() > 15)
    holder.text.setText(file_name.substring(0, 15) + "");
else
    holder.text.setText(file_name); // frn name

try {
    if (frnshare_list.get(myposition).getFileType()
        .equalsIgnoreCase("file")) { // it is file
        holder.icon.setImageResource(R.drawable.mp3_icon);
        if (frnshare_list.get(myposition).getDownloadStatus()
            .equalsIgnoreCase("0")) {
            Log.i("file is ", "" + frnshare_list.get(myposition).getFileName());
            holder.download.setImageResource(R.drawable.download_png);
        } else if (frnshare_list.get(myposition).getDownloadStatus()
            .equalsIgnoreCase("1")) {

        } else if (frnshare_list.get(myposition).getDownloadStatus()
            .equalsIgnoreCase("2")) {
            Log.i("file is in queue", "" + frnshare_list.get(myposition).getFileName());
            holder.icon.setVisibility(View.GONE);
            holder.download.setVisibility(View.GONE);
            holder.text.setTextSize(14);
            if (frnshare_list.get(myposition).getFileName().length() > 15)
                holder.text.setText(frnshare_list.get(myposition).getFileName().substring(0, 1);
            else
                holder.text.setText(frnshare_list.get(myposition).getFileName() );
        }
    } else if (frnshare_list.get(myposition).getFileType()
        .equalsIgnoreCase("folder")) {
        holder.icon.setImageResource(R.drawable.folder);

    }
} catch (Exception e) {
    // TODO: handle exception
    Intent i = new Intent(context, TabViewActivity.class);
    i.putExtra("show", "frntab");
    context.startActivity(i);

    BugSenseHandler.sendException(e);
    e.printStackTrace();
}


return convertView;
}

【问题讨论】:

标签: java android listview android-view baseadapter


【解决方案1】:

我看过你的代码,我自己也看过很多次,这是我的建议

if(position==1){

//here change color or hide view

holder.someView.setVisibility(View.Invisible);

holder.someView.setColor ==== green; //forgive me abt syntx

}else{

//Here in else part it is important that you must reverse above things
//so that when you scroll list, GREEN color do not show up in random rows

holder.someView.setVisibility(View.Visible);

holder.someView.setColor ==== red; //forgive me abt syntx

}

//same is for on click listener etc

【讨论】:

  • @Syed Zahid Ali:我已经做到了。在我的代码中,我检查了三个状态 0、1、2,据此我正在更改视图但没有效果:(
  • @Sneha 是的,你做了,但在位置 0 你有 holder.icon.setVisibility(View.GONE);并且您还没有将图标状态更改为在其任何其他部分中可见。所以,总的来说,我认为你应该检查你的代码
  • @SyedZahidAli 位置是指列出视图位置或我在代码中提到的状态,即 0,1,2。
  • if (frnshare_list.get(myposition).getDownloadStatus() .equalsIgnoreCase("0")).......这里是我的位置
【解决方案2】:

您正在执行 ListView 之外的异步任务。那是自找麻烦。事情是这样的——ListView 回收行。因此,当任务完成时,它实际上可能指向与开始时完全不同的位置。您必须非常小心,并确保异步任务对 UI 完全没有影响,它强制整个列表重绘而不是对任何一行进行更改,或者它从不假定单击的行仍然有效,而是知道单击按钮时行中的位置并确定现在需要更新的行。

基本上,如果可以,请避免使用 AsyncTasks。如果不能,则需要确保 AsyncTask 不接触 UI(调用 notifyDataSetChanged 除外),并且在任务过程中它需要的任何数据(比如保存到的文件名)都被复制到本地AsyncTask 在创建时的成员变量,而不是从行视图中读取。

【讨论】:

  • 先生在异步任务中我只更新数据库中的状态而不更改任何视图
【解决方案3】:

我认为您的代码是实现它的正常方式,但是由于在创建过程中回收了您的问题。

你能做的是 1.检查您在方法中直接获得的位置 - 它应该按照重绘的顺序 2. 不要重复使用您的持有人中已经设置的内容,一旦您从转换视图获得持有人,从其他数据源设置该内容,如List&lt;&lt;&gt;&gt; - 这样您就可以节省重新创建视图的时间,而内容将在您的其他数据持有者中。

【讨论】:

  • @rock_win 先生,因为我对 android 比较陌生,所以它对我来说很复杂。如果你能给我一个例子,这将很有帮助。:(
  • 查看您为 TextView 和 ImageView 设置的位图和字符串只是不同数据的类型。因此,您可以为每个行项目分别拥有该数据的实体模型,并可能将其存储在 List 类型的 Java 中。现在持有人给你的所有帮助是你不需要重新膨胀布局。因此,一旦您获得持有人,使用您的列表并使用您获得的position 作为参数检索数据并将其设置为持有人内的Views。因为那是您从该方法返回的最终结果。有关更多详细信息,您还可以参考...
  • Google IO 在 ListViews 上的谈话——我想那是在 2010 年。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多