需求:当你在复用listView的子项带有checkbox控件的view对象时,由于复用的原理是直接复用前面失去焦点的view对象(不懂得具体可看前面的一篇关于listView优化的记录http://my.oschina.net/zaizaiangels/blog/529308)
那么checkbox的记录也会被复用,这就会产生数据错乱
处理方法:
步骤:1、给listView添加监听点击事件的方法,在监听到listView的子项被点击时,认为的去记录该子项下checkbox的状态
2、我们将在一个业务bean中保存每个listView子项的状态,在复用的时候,检查并设置相应的状态即可
代码如下
子项的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="65dip">
<ImageView
android:id="@+id/iv_task_icon"
android:layout_width="55dip"
android:layout_height="55dip"
android:layout_marginBottom="5dip"
android:layout_marginLeft="5dip"
android:layout_marginTop="5dip"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/tv_task_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginTop="3dip"
android:layout_toRightOf="@id/iv_task_icon"
android:text="程序名称:"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_task_memory_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_task_name"
android:layout_marginLeft="5dip"
android:layout_marginTop="1dip"
android:layout_toRightOf="@id/iv_task_icon"
android:text="内存占用:"
android:textColor="#88000000"
android:textSize="16sp" />
<CheckBox
android:id="@+id/cb_task_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dip"
android:clickable="false"
android:focusable="false" />
</RelativeLayout>
listView的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:clickable="true"
android:focusable="false">
<TextView
android:id="@+id/textView1"
android:layout_width="fill_parent"
android:layout_height="55dip"
android:background="@android:color/holo_green_dark"
android:gravity="center"
android:text="任务管理器"
android:textColor="@android:color/black"
android:textSize="22sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_process_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运行中的进程"
android:textColor="#000000" />
<TextView
android:id="@+id/tv_remains_memory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="剩余/总内存"
android:textColor="#000000" />
</RelativeLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/ll_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="invisible">
<ProgressBar
android:layout_width="match_parent"
android:layout_height="60dip" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加载程序信息" />
</LinearLayout>
<ListView
android:id="@+id/lv_task_manager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:fastScrollEnabled="true" />
<TextView
android:id="@+id/tv_task_prompt_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:text="用户进程"
android:textColor="@android:color/white" />
</FrameLayout>
</LinearLayout>
业务bean代码:
package com.zaizai.safty.domain;
import android.graphics.drawable.Drawable;
/**
* 进程信息业务bean
* Created by zaizai on 2015/11/15.
*/
public class TaskInfo {
private Drawable icon;
private String name; //应用程序名字
private String packname; //应用程序包名
private long memorysize;//内存占用大小
private boolean userTask;//true用户进程 false系统进程
private boolean checaked;
public boolean isChecaked() {
return checaked;
}
public void setChecaked(boolean checaked) {
this.checaked = checaked;
}
@Override
public String toString() {
return "TaskInfo{" +
"icon=" + icon +
", name='" + name + '\'' +
", packname='" + packname + '\'' +
", memorysize=" + memorysize +
", userTask=" + userTask +
", checaked=" + checaked +
'}';
}
public Drawable getIcon() {
return icon;
}
public void setIcon(Drawable icon) {
this.icon = icon;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPackname() {
return packname;
}
public void setPackname(String packname) {
this.packname = packname;
}
public long getMemorysize() {
return memorysize;
}
public void setMemorysize(long memorysize) {
this.memorysize = memorysize;
}
public boolean isUserTask() {
return userTask;
}
public void setUserTask(boolean userTask) {
this.userTask = userTask;
}
}
activity代码
package com.zaizai.safty;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.zaizai.safty.domain.TaskInfo;
import com.zaizai.safty.engine.TaskInfoProvider;
import com.zaizai.safty.utils.SystemInfoUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by zaizai on 2015/11/15.
*/
public class TaskManagerActivity extends AppCompatActivity {
private static final String TAG = "zaizai";
private TextView tvProcessCount;
private TextView tvRemainsMemory;
private LinearLayout llLoading;
private ListView lvTaskManager;
private List<TaskInfo> allTaskInfos;
private List<TaskInfo> userTaskInfos;
private List<TaskInfo> systemTaskInfos;
private TaskManagerAdapter taskManagerAdapter;
private TextView tvTaskPromptInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task_manager);
tvProcessCount = (TextView) findViewById(R.id.tv_process_count);
tvRemainsMemory = (TextView) findViewById(R.id.tv_remains_memory);
llLoading = (LinearLayout) findViewById(R.id.ll_loading);
lvTaskManager = (ListView) findViewById(R.id.lv_task_manager);
tvTaskPromptInfo = (TextView) findViewById(R.id.tv_task_prompt_info);
int processCount = SystemInfoUtils.getRunningProcessCount(this);
tvProcessCount.setText("运行中的进程有:" + processCount + "个");
long availableRemainsMemory = SystemInfoUtils.getAvailableRemainsMemoryCount(this);
long totalRemainsMemory = SystemInfoUtils.getTotalRemainsMemoryCount(this);
tvRemainsMemory.setText("剩余/总内存:" + Formatter.formatFileSize(this, availableRemainsMemory) + "/" + Formatter.formatFileSize(this, totalRemainsMemory));
/*加载数据到listView*/
fillData();
/*监听listView的点击事件,自己保存checkBox的状态*/
lvTaskManager.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.i(TAG, "TaskManagerListView被点击");
int userTaskCount = 0;
if (userTaskInfos != null) {
userTaskCount = userTaskInfos.size();
}
int systemtaskCount = 0;
if (systemTaskInfos != null) {
systemtaskCount = systemTaskInfos.size();
}
TaskInfo taskInfo = null;
if (position == 0) {
/*用户进程的标签*/
return;
} else if (position == userTaskCount + 1) {
/*系统进程的标签*/
return;
} else if (position <= userTaskCount && userTaskInfos != null) {
/*用户进程*/
int newPosition = position - 1;
taskInfo = userTaskInfos.get(newPosition);
} else if (position >= userTaskCount + 2 && position <= (userTaskCount + systemtaskCount + 2) && systemTaskInfos != null) {
/*position > userTaskCount + 2 加一因为增加一个系统进程标签*/
int newPostion = position - userTaskCount - 2;
taskInfo = systemTaskInfos.get(newPostion);
}
if (view instanceof RelativeLayout) {
ViewHolder holder = (ViewHolder) view.getTag();
if (taskInfo != null && taskInfo.isChecaked()) {
Log.i(TAG, "checkBox被选中");
taskInfo.setChecaked(false);
holder.cbTaskStatus.setChecked(false);
} else {
Log.i(TAG, "checkBox被选中");
taskInfo.setChecaked(true);
holder.cbTaskStatus.setChecked(true);
}
}
}
});
/*监听滚动事件,改变提示文本控件的信息*/
lvTaskManager.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (userTaskInfos != null && systemTaskInfos != null) {
if (firstVisibleItem >= userTaskInfos.size()) {
tvTaskPromptInfo.setText("系统进程:" + systemTaskInfos.size() + "个");
} else {
tvTaskPromptInfo.setText("用户进程:" + userTaskInfos.size() + "个");
}
}
}
});
}
/**
* 填充数据
*/
private void fillData() {
llLoading.setVisibility(View.VISIBLE);
new Thread(new Runnable() {
@Override
public void run() {
allTaskInfos = TaskInfoProvider.getTaskInfos(TaskManagerActivity.this);
userTaskInfos = new ArrayList<TaskInfo>();
systemTaskInfos = new ArrayList<TaskInfo>();
/*将allTaskInfos中的infos进行分类*/
for (TaskInfo info : allTaskInfos) {
if (info.isUserTask()) {
userTaskInfos.add(info);
} else {
systemTaskInfos.add(info);
}
}
/*更新界面*/
runOnUiThread(new Runnable() {
@Override
public void run() {
llLoading.setVisibility(View.INVISIBLE);
if (taskManagerAdapter == null) {
taskManagerAdapter = new TaskManagerAdapter();
lvTaskManager.setAdapter(taskManagerAdapter);
} else {
taskManagerAdapter.notifyDataSetChanged();
}
}
});
}
}).start();
}
private class TaskManagerAdapter extends BaseAdapter {
@Override
public int getCount() {
int size = 0;
if (userTaskInfos != null) {
size = size + userTaskInfos.size();
}
if (systemTaskInfos != null) {
size = size + systemTaskInfos.size();
}
size = size + 2;
return size;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TaskInfo taskInfo = null;
int userTaskCount = 0;
if (userTaskInfos != null) {
userTaskCount = userTaskInfos.size();
}
int systemtaskCount = 0;
if (systemTaskInfos != null) {
systemtaskCount = systemTaskInfos.size();
}
if (position == 0) {
/*用户进程的标签*/
TextView tv = new TextView(getApplicationContext());
tv.setBackgroundColor(Color.GRAY);
tv.setTextColor(Color.WHITE);
tv.setText("用户进程:" + userTaskCount + "个");
return tv;
} else if (position == userTaskCount + 1) {
/*系统进程的标签*/
TextView tv = new TextView(getApplicationContext());
tv.setBackgroundColor(Color.GRAY);
tv.setTextColor(Color.WHITE);
tv.setText("系统进程:" + systemtaskCount + "个");
return tv;
} else if (position <= userTaskCount && userTaskInfos != null) {
/*用户进程*/
int newPosition = position - 1;
taskInfo = userTaskInfos.get(newPosition);
} else if (position >= userTaskCount + 2 && position <= (userTaskCount + systemtaskCount + 2) && systemTaskInfos != null) {
/*position > userTaskCount + 2 加一因为增加一个系统进程标签*/
int newPostion = position - userTaskCount - 2;
taskInfo = systemTaskInfos.get(newPostion);
}
View view;
ViewHolder viewHolder;
if (convertView != null && convertView instanceof RelativeLayout) {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
} else {
view = View.inflate(getApplicationContext(), R.layout.list_item_taskinfo, null);
viewHolder = new ViewHolder();
viewHolder.ivTaskIcon = (ImageView) view.findViewById(R.id.iv_task_icon);
viewHolder.tvTaskName = (TextView) view.findViewById(R.id.tv_task_name);
viewHolder.tvTaskMemorySize = (TextView) view.findViewById(R.id.tv_task_memory_size);
viewHolder.cbTaskStatus = (CheckBox) view.findViewById(R.id.cb_task_status);
view.setTag(viewHolder);
}
if (taskInfo != null) {
viewHolder.ivTaskIcon.setImageDrawable(taskInfo.getIcon());
viewHolder.tvTaskName.setText(taskInfo.getName());
viewHolder.tvTaskMemorySize.setText("内存占用:" + Formatter.formatFileSize(getApplicationContext(), taskInfo.getMemorysize()));
viewHolder.cbTaskStatus.setChecked(taskInfo.isChecaked());
}
return view;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
static class ViewHolder {
ImageView ivTaskIcon;
TextView tvTaskName;
TextView tvTaskMemorySize;
CheckBox cbTaskStatus;
}
}
数据提供类
package com.zaizai.safty.engine;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Debug;
import com.zaizai.safty.R;
import com.zaizai.safty.domain.TaskInfo;
import java.util.ArrayList;
import java.util.List;
/**
* 提供手机里面的进程信息
* Created by zaizai on 2015/11/15.
*/
public class TaskInfoProvider {
public static List<TaskInfo> getTaskInfos(Context context) {
//得到任务管理器
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
/*包管理器,用来获得程序的基本信息*/
PackageManager packageManager = context.getPackageManager();
List<ActivityManager.RunningAppProcessInfo> appProcessInfos = activityManager.getRunningAppProcesses();
List<TaskInfo> taskInfos = new ArrayList<TaskInfo>();
for (ActivityManager.RunningAppProcessInfo appProcessInfo : appProcessInfos) {
TaskInfo taskInfo = new TaskInfo();
/*appProcessInfo.pid;进程id 没有为0
* appProcessInfo.processName;应用程序包名
* */
String packname = appProcessInfo.processName;
taskInfo.setPackname(packname);
Debug.MemoryInfo[] memoryInfos = activityManager.getProcessMemoryInfo(new int[]{appProcessInfo.pid});
long memorysize = memoryInfos[0].getTotalPrivateDirty() * 1024;
taskInfo.setMemorysize(memorysize);
/*通过包管理器获得程序的基本信息*/
try {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packname, 0);
Drawable icon = applicationInfo.loadIcon(packageManager);
taskInfo.setIcon(icon);
String name = applicationInfo.loadLabel(packageManager).toString();
taskInfo.setName(name);
if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
/*用户进程*/
taskInfo.setUserTask(true);
} else {
/*系统进程*/
taskInfo.setUserTask(false);
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
taskInfo.setIcon(context.getResources().getDrawable(R.drawable.ic_default));
taskInfo.setName(packname);
}
taskInfos.add(taskInfo);
}
return taskInfos;
}
}