Android:我的 listView onClick 事件没有按预期工作(顺序混乱)
Android: My listView onClick events are not working as intended (order messes up)
我的程序应该显示应用列表及其数据使用情况。如果您单击该应用程序,它会启动一个新的 activity 页面并提供有关该应用程序的更多信息。在初始页面上一切正常,所有应用程序都显示准确的信息,但在我向下滚动后它搞砸了 - "more info" 页面显示的应用程序与我单击的应用程序不同。
我很确定问题出在没有绑定到 holder 的 onclick 事件上?但是我不知道该怎么做。应该注意的是,如果我摆脱 if(convertView == null)/else 条件,问题就解决了,但我知道这是不好的做法,因为我们不想继续重新生成以前的项目
这是我的 customAdapter 中的 getView 代码:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
final DataUsageModel model;
model = getItem(position);
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.customlayout, null);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intentMoreInfo = new Intent(view.getContext(),MoreInfoActivity.class);
intentMoreInfo.putExtra("wifiUsage",model.getWifiUsage());
intentMoreInfo.putExtra("mobileUsage",model.getMobileUsage());
intentMoreInfo.putExtra("appName",model.getName());
intentMoreInfo.putExtra("pname",model.getPname());
context.startActivity(intentMoreInfo);
}
});
holder.nameText = (TextView) convertView.findViewById(R.id.textViewWord);
holder.totalUsageText = (TextView) convertView.findViewById(R.id.textViewDescription);
holder.imageView = (ImageView) convertView.findViewById(R.id.iconImageView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.nameText.setText(model.getName());
long usageInMB = (model.getWifiUsage() + model.getMobileUsage())/(1024*1024);
holder.totalUsageText.setText(String.valueOf(usageInMB) + " MB");
holder.imageView.setImageDrawable(model.getImageRes());
return convertView;
}
public class ViewHolder {
TextView nameText;
TextView totalUsageText;
ImageView imageView;
}
这是我的新 activity 启动代码:
public class MoreInfoActivity extends AppCompatActivity {
TextView wifiUsage;
TextView mobileUsage;
ImageView icon;
TextView appName;
Button backButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.more_info_layout);
wifiUsage = findViewById(R.id.moreInfoWifi);
mobileUsage = findViewById(R.id.moreInfoMobile);
appName = findViewById(R.id.moreInfoAppName);
icon = findViewById(R.id.moreInfoIcon);
backButton = (Button)findViewById(R.id.moreInfoBack);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
appName.setText(getIntent().getStringExtra("appName"));
wifiUsage.setText("Wifi Usage: " + String.valueOf(getIntent().getLongExtra("wifiUsage",0)/(1024*1024)) + " MB");
mobileUsage.setText("Mobile Usage: " + String.valueOf(getIntent().getLongExtra("mobileUsage",0)/(1024*1024)) + " MB");
try {
icon.setImageDrawable(getPackageManager().getApplicationIcon(getIntent().getStringExtra("pname")));
}catch(PackageManager.NameNotFoundException e){
e.printStackTrace();
}
您应该为 getView 方法的每次迭代设置 OnClickListener,而不仅仅是在 convertView == null.
时
在您的情况下,当前数据位置未与每次 getView 迭代的当前视图(持有者)位置同步
此外,从适配器本身启动 activity 是一种非常糟糕的做法。
adapter的作用就是把view绑定到data上,仅此而已
我的程序应该显示应用列表及其数据使用情况。如果您单击该应用程序,它会启动一个新的 activity 页面并提供有关该应用程序的更多信息。在初始页面上一切正常,所有应用程序都显示准确的信息,但在我向下滚动后它搞砸了 - "more info" 页面显示的应用程序与我单击的应用程序不同。
我很确定问题出在没有绑定到 holder 的 onclick 事件上?但是我不知道该怎么做。应该注意的是,如果我摆脱 if(convertView == null)/else 条件,问题就解决了,但我知道这是不好的做法,因为我们不想继续重新生成以前的项目
这是我的 customAdapter 中的 getView 代码:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
final DataUsageModel model;
model = getItem(position);
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.customlayout, null);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intentMoreInfo = new Intent(view.getContext(),MoreInfoActivity.class);
intentMoreInfo.putExtra("wifiUsage",model.getWifiUsage());
intentMoreInfo.putExtra("mobileUsage",model.getMobileUsage());
intentMoreInfo.putExtra("appName",model.getName());
intentMoreInfo.putExtra("pname",model.getPname());
context.startActivity(intentMoreInfo);
}
});
holder.nameText = (TextView) convertView.findViewById(R.id.textViewWord);
holder.totalUsageText = (TextView) convertView.findViewById(R.id.textViewDescription);
holder.imageView = (ImageView) convertView.findViewById(R.id.iconImageView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.nameText.setText(model.getName());
long usageInMB = (model.getWifiUsage() + model.getMobileUsage())/(1024*1024);
holder.totalUsageText.setText(String.valueOf(usageInMB) + " MB");
holder.imageView.setImageDrawable(model.getImageRes());
return convertView;
}
public class ViewHolder {
TextView nameText;
TextView totalUsageText;
ImageView imageView;
}
这是我的新 activity 启动代码:
public class MoreInfoActivity extends AppCompatActivity {
TextView wifiUsage;
TextView mobileUsage;
ImageView icon;
TextView appName;
Button backButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.more_info_layout);
wifiUsage = findViewById(R.id.moreInfoWifi);
mobileUsage = findViewById(R.id.moreInfoMobile);
appName = findViewById(R.id.moreInfoAppName);
icon = findViewById(R.id.moreInfoIcon);
backButton = (Button)findViewById(R.id.moreInfoBack);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
appName.setText(getIntent().getStringExtra("appName"));
wifiUsage.setText("Wifi Usage: " + String.valueOf(getIntent().getLongExtra("wifiUsage",0)/(1024*1024)) + " MB");
mobileUsage.setText("Mobile Usage: " + String.valueOf(getIntent().getLongExtra("mobileUsage",0)/(1024*1024)) + " MB");
try {
icon.setImageDrawable(getPackageManager().getApplicationIcon(getIntent().getStringExtra("pname")));
}catch(PackageManager.NameNotFoundException e){
e.printStackTrace();
}
您应该为 getView 方法的每次迭代设置 OnClickListener,而不仅仅是在 convertView == null.
时在您的情况下,当前数据位置未与每次 getView 迭代的当前视图(持有者)位置同步
此外,从适配器本身启动 activity 是一种非常糟糕的做法。 adapter的作用就是把view绑定到data上,仅此而已