onItemClick 变量的 ClassCastException

ClassCastException for onItemClick variable

我正在尝试在屏幕上显示的 pid 变量出现 ClassCastException。我知道 onclick 位置的项目是一个字符串,它正在转换为导致异常的 RunningAppProcessInfo,但我无法弄清楚如何在不使用它的情况下获取 pid。

这是我的代码

  ActivityManager activityManager = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
  List<RunningAppProcessInfo> list = activityManager.getRunningAppProcesses();

  ArrayList<String> info = new ArrayList<>();
  for (ActivityManager.RunningAppProcessInfo p : list) {
      info.add(p.processName);
  }

  ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, info);
  ListView listView = (ListView) findViewById(R.id.list);
  listView.setAdapter(adapter);

  listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
          int  uid = ((RunningAppProcessInfo)parent.getItemAtPosition(position)).pid;
          Toast.makeText(getApplicationContext(),uid,Toast.LENGTH_LONG).show();
        }
  });

嗯,不。按照您初始化适配器的方式,该项目将是进程名称,而不是进程 ID。它肯定不会是 RunningAppProcessInfo 的实例。如果您希望您的项目是进程 ID,请按如下方式重新定义您的适配器:

ArrayList<Integer> info = new ArrayList<>();
for (ActivityManager.RunningAppProcessInfo p : list) {
    info.add(p.pid); // not p.processName
}

ArrayAdapter<Integer> adapter = new ArrayAdapter<>(this,
   android.R.layout.simple_list_item_1, info);

然后通过以下方式检索它:

int uid = (Integer) parent.getItemAtPosition(position);

如果两者都需要,则必须定义自己的 class 以包含进程名称和 ID:

class Info {
    final String processName;
    final int pid;
    Info(String processName, int pid) {
        this.processName = processName;
        this.pid = pid;
    }
    @Override
    public String toString() {
        return processName;
    }
}
ArrayList<Info> info = new ArrayList<>();
for (ActivityManager.RunningAppProcessInfo p : list) {
    info.add(new Info(p.processName, p.pid));
}

ArrayAdapter<Info> adapter = new ArrayAdapter<>(this,
   android.R.layout.simple_list_item_1, info);

并通过以下方式检索:

int uid = ((Info)parent.getItemAtPosition(position)).pid;

您可能会想写:

ArrayList<RunningAppProcessInfo> info = new ArrayList<>();
for (ActivityManager.RunningAppProcessInfo p : list) {
    info.add(p);
}

ArrayAdapter<RunningAppProcessInfo> adapter = new ArrayAdapter<>(this,
   android.R.layout.simple_list_item_1, info);

并保留您的原始检索代码,但不幸的是,RunningAppProcessInfo 没有可供适配器使用的可用 toString() 方法,因此您将不得不编写一个容器 class 一种或另一种方式。

parent.getItemAtPosition(position) 实际上 return 您在 ArrayAdapter 构造函数中提供的列表项,因此它是一个字符串,然后当您尝试时当然会得到一个 classCastException将此字符串转换为 RunningAppProcessInfo。

我的建议是直接使用自定义适配器而不是 ArrayAdapter。这是我写的示例代码供您参考:

public class ProcessSampleAdapter extends BaseAdapter {

private Context mContext;
private List<ActivityManager.RunningAppProcessInfo> mAppProcInfos;

public ProcessSampleAdapter(Context context, List<ActivityManager.RunningAppProcessInfo> list) {
    mContext = context;
    mAppProcInfos = list;
}

@Override
public int getCount() {
    return mAppProcInfos.size();
}

@Override
public Object getItem(int position) {
    return mAppProcInfos.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup root) {
    convertView = LayoutInflater.from(mContext).inflate(android.R.layout.simple_list_item_1, null);

    TextView textV = (TextView)convertView;
    textV.setText(mAppProcInfos.get(position).processName);

    return convertView;
}

}

顺便说一句,因为uid是一个int,所以不要直接将它提供给makeToast方法,否则它不会显示uid,而是会尝试寻找id为uid的String资源。