需求:当你在复用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; } }