Android ListView 向下滚动时显示不正确的内容,然后向上滚动时显示正确的内容
Android ListView show incorrect content when Scrolling Down, then correct content when Scrolling Up
作为 Android Studio 的新手,我目前对同一代码的不同行为感到困惑。如果代码相同,向上或向下滚动时结果可能有何不同?这可能是一些 Android 查看回收问题吗?
从网络上的 JSON 文件解析数据后,自定义适配器读取并设置 ListView 中每一行的相应数据。每行有四条信息:1) 标题,2) 描述,3) 图像 URL(通过 Picasso 显示)和 4) 分配给 setOnClickListener 的外部 URL一个按钮,通过浏览器意图打开。
虽然每一行的标题、描述和图像都完美无缺,但对于分配给按钮的 setOnClickListener 的 URL,恰好有一个非常奇怪、奇怪且到目前为止(对我来说)无法解释的问题行为:
1) 首次呈现 ListView 时,在浏览器中单击按钮打开 URL 时,系统打开的不是该项目的正确 URL,而是 URL 对应数组中的下一项。
2) 如果向下滚动一点,然后再次向上滚动,当点击同一个按钮时(之前导致不正确的 URL),这次它确实会打开正确的 URL.
在相同的代码上,在相同的 运行 上,按钮在向下滚动时会显示不正确的 URL,然后在向上滚动时会显示正确的 URL。
到目前为止,我的提示是考虑这可能与 Android 的回收视图功能有关,但我仍然不知道如何纠正这个问题。
我确实在 CustomAdapter.java 中包含了以下代码行,希望能防止回收:
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
然而,包含或排除上述代码并没有实际区别。
我的CustomAdapter.java的完整代码如下:
package ca.costari.apps.ge3000;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.Objects;
public class CustomAdapter extends BaseAdapter {
private Context context;
private ArrayList<PlayersModel> playersModelArrayList;
private String clickurl;
public CustomAdapter(Context context, ArrayList<PlayersModel> playersModelArrayList) {
this.context = context;
this.playersModelArrayList = playersModelArrayList;
}
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getCount() {
return playersModelArrayList.size();
}
@Override
public Object getItem(int position) {
return playersModelArrayList.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@SuppressLint("InflateParams")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
convertView = Objects.requireNonNull(inflater).inflate(R.layout.lv_item, null, true);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
holder.procesa_titulo = Objects.requireNonNull(convertView).findViewById(R.id.id_titulo);
}
holder.procesa_mensajepromo = convertView.findViewById(R.id.id_mensajepromo);
holder.procesa_imagenurl = convertView.findViewById(R.id.imageViewPromo);
convertView.setTag(holder);
}else {
// the getTag returns the viewHolder object set as a tag to the view
holder = (ViewHolder)convertView.getTag();
}
clickurl = playersModelArrayList.get(position).getClickURL();
holder.procesa_clickurl = convertView.findViewById(R.id.id_clickurl);
holder.procesa_clickurl.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
AsignaBotonUrl(v, clickurl);
}
});
holder.procesa_titulo.setText(playersModelArrayList.get(position).getTitulo());
holder.procesa_mensajepromo.setText(playersModelArrayList.get(position).getMensajePromo());
// Picasso to display image from URL
Picasso.with(holder.procesa_imagenurl.getContext())
.load(playersModelArrayList.get(position).getImageURL())
.placeholder(R.drawable.echale_un_ojo_te_interesa)
.into(holder.procesa_imagenurl);
return convertView;
}
private void AsignaBotonUrl(View view, String url) {
Intent browserIntent = new Intent(
Intent.ACTION_VIEW,
Uri.parse(url));
view.getContext().startActivity(browserIntent);
}
private class ViewHolder {
protected TextView procesa_titulo, procesa_mensajepromo;
protected ImageView procesa_imagenurl;
protected Button procesa_clickurl;
}
}
以上代码为以下ListView中包含的项目赋值xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fdfdfd"
android:orientation="vertical"
android:layout_marginBottom="30dp"
tools:ignore="UselessParent">
<TextView
android:id="@+id/id_titulo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#2f2f2f"
android:layout_marginTop="10dp"
android:layout_marginBottom="20dp"
android:gravity="center_vertical"
android:textSize="20sp"
android:paddingLeft="10dp" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/imageViewPromo"
android:layout_marginBottom="20dp"
android:contentDescription="@string/echale_un_ojo" />
<TextView
android:id="@+id/id_mensajepromo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#2f2f2f"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingLeft="10dp"
android:layout_marginBottom="10dp" />
<Button
android:id="@+id/id_clickurl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="24sp"
android:text="@string/conocer_mas"
android:drawableRight="@drawable/open_web"
android:layout_marginBottom="30dp" />
</LinearLayout>
</LinearLayout>
这是我在 Whosebug 中的第一个 post,因此请您耐心等待,因为我可能没有正确提出我的问题,如果我可能需要包含更多内容,请告诉我此处代码,或提供更多信息。
万分感谢!!!
将clickurl
更改为最终的局部变量,因此删除
private String clickurl
并在 getView
中使用它,这样每个听众都有一个独特的 URL。
final String clickurl = playersModelArrayList.get(position).getClickURL();
按原样,您的 onClickListener 使用 clickurl
的单个实例(保存在适配器 class 中的实例),因此它始终会使用上次调用 [=] 时设置的任何内容13=].
作为 Android Studio 的新手,我目前对同一代码的不同行为感到困惑。如果代码相同,向上或向下滚动时结果可能有何不同?这可能是一些 Android 查看回收问题吗?
从网络上的 JSON 文件解析数据后,自定义适配器读取并设置 ListView 中每一行的相应数据。每行有四条信息:1) 标题,2) 描述,3) 图像 URL(通过 Picasso 显示)和 4) 分配给 setOnClickListener 的外部 URL一个按钮,通过浏览器意图打开。
虽然每一行的标题、描述和图像都完美无缺,但对于分配给按钮的 setOnClickListener 的 URL,恰好有一个非常奇怪、奇怪且到目前为止(对我来说)无法解释的问题行为:
1) 首次呈现 ListView 时,在浏览器中单击按钮打开 URL 时,系统打开的不是该项目的正确 URL,而是 URL 对应数组中的下一项。
2) 如果向下滚动一点,然后再次向上滚动,当点击同一个按钮时(之前导致不正确的 URL),这次它确实会打开正确的 URL.
在相同的代码上,在相同的 运行 上,按钮在向下滚动时会显示不正确的 URL,然后在向上滚动时会显示正确的 URL。
到目前为止,我的提示是考虑这可能与 Android 的回收视图功能有关,但我仍然不知道如何纠正这个问题。
我确实在 CustomAdapter.java 中包含了以下代码行,希望能防止回收:
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
然而,包含或排除上述代码并没有实际区别。
我的CustomAdapter.java的完整代码如下:
package ca.costari.apps.ge3000;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.Objects;
public class CustomAdapter extends BaseAdapter {
private Context context;
private ArrayList<PlayersModel> playersModelArrayList;
private String clickurl;
public CustomAdapter(Context context, ArrayList<PlayersModel> playersModelArrayList) {
this.context = context;
this.playersModelArrayList = playersModelArrayList;
}
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getCount() {
return playersModelArrayList.size();
}
@Override
public Object getItem(int position) {
return playersModelArrayList.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@SuppressLint("InflateParams")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
convertView = Objects.requireNonNull(inflater).inflate(R.layout.lv_item, null, true);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
holder.procesa_titulo = Objects.requireNonNull(convertView).findViewById(R.id.id_titulo);
}
holder.procesa_mensajepromo = convertView.findViewById(R.id.id_mensajepromo);
holder.procesa_imagenurl = convertView.findViewById(R.id.imageViewPromo);
convertView.setTag(holder);
}else {
// the getTag returns the viewHolder object set as a tag to the view
holder = (ViewHolder)convertView.getTag();
}
clickurl = playersModelArrayList.get(position).getClickURL();
holder.procesa_clickurl = convertView.findViewById(R.id.id_clickurl);
holder.procesa_clickurl.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
AsignaBotonUrl(v, clickurl);
}
});
holder.procesa_titulo.setText(playersModelArrayList.get(position).getTitulo());
holder.procesa_mensajepromo.setText(playersModelArrayList.get(position).getMensajePromo());
// Picasso to display image from URL
Picasso.with(holder.procesa_imagenurl.getContext())
.load(playersModelArrayList.get(position).getImageURL())
.placeholder(R.drawable.echale_un_ojo_te_interesa)
.into(holder.procesa_imagenurl);
return convertView;
}
private void AsignaBotonUrl(View view, String url) {
Intent browserIntent = new Intent(
Intent.ACTION_VIEW,
Uri.parse(url));
view.getContext().startActivity(browserIntent);
}
private class ViewHolder {
protected TextView procesa_titulo, procesa_mensajepromo;
protected ImageView procesa_imagenurl;
protected Button procesa_clickurl;
}
}
以上代码为以下ListView中包含的项目赋值xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fdfdfd"
android:orientation="vertical"
android:layout_marginBottom="30dp"
tools:ignore="UselessParent">
<TextView
android:id="@+id/id_titulo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#2f2f2f"
android:layout_marginTop="10dp"
android:layout_marginBottom="20dp"
android:gravity="center_vertical"
android:textSize="20sp"
android:paddingLeft="10dp" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/imageViewPromo"
android:layout_marginBottom="20dp"
android:contentDescription="@string/echale_un_ojo" />
<TextView
android:id="@+id/id_mensajepromo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#2f2f2f"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingLeft="10dp"
android:layout_marginBottom="10dp" />
<Button
android:id="@+id/id_clickurl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="24sp"
android:text="@string/conocer_mas"
android:drawableRight="@drawable/open_web"
android:layout_marginBottom="30dp" />
</LinearLayout>
</LinearLayout>
这是我在 Whosebug 中的第一个 post,因此请您耐心等待,因为我可能没有正确提出我的问题,如果我可能需要包含更多内容,请告诉我此处代码,或提供更多信息。
万分感谢!!!
将clickurl
更改为最终的局部变量,因此删除
private String clickurl
并在 getView
中使用它,这样每个听众都有一个独特的 URL。
final String clickurl = playersModelArrayList.get(position).getClickURL();
按原样,您的 onClickListener 使用 clickurl
的单个实例(保存在适配器 class 中的实例),因此它始终会使用上次调用 [=] 时设置的任何内容13=].