转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47282031
在上一篇博文《Android之——杀死用户选中的进程优化》一文中,我向大家介绍了如何优化用户的体验,那么这篇博文中,我将向大家介绍如何进行系统进程与用户进程的分离操作。同样,这篇博文是基于上一篇博文改进的。如果大家还没有阅读上一篇博文,请大家先阅读上一篇博文《Android之——杀死用户选中的进程优化》一文。好了,咱们直接进入主题吧。
老规矩,我们还是先谈谈原理级别的东西吧。
首先,我们根据当前应用是用户安装的还是系统自带的,把应用分为用户应用和系统应用,用户应用对应的进程就是用户进程,系统应用对应的进程就是系统进程。大家不禁会说,这不废话吗?是的,这就是最基础的原理。下面我们来继续说UI显示的问题,首先,给大家献上一张图来说明一下,看图:
如图,我们要实现的效果如左面的图示所示,首先,在ListView的最上方显示用户进程(用户进程数量),然后下面是用户进程的列表信息,然后下面显示系统进程(系统进程数量),然后下面紧接着显示的是系统进程列表信息。当然,这样的设计会使得自定义适配器类改动稍大。这里,我们不妨假定,用户进程集合为userTaskInfos,系统进程集合为systemTaskInfos,首先,自定义适配器中返回的数据集合大小应该是用户进程集合大小加上系统进程集合大小再加上2,也就是userTaskInfo.size()+systemTaskInfos.size()+2,不明白的童鞋请看图仔细分析下。在这个ListView的第一个位置上,也就是position为0的位置,是一个TextView提示用户进程(用户进程数量),下面从position为1的位置一直到用户进程大小的位置上,一直显示的是用户进程的信息,这些位置返回的具体进程信息是,userTaskInfo.get(position-1);当position为userTaskInfo.size()+1的时候,又是一个TextView,提示的是系统进程(系统进程数量),下面列出的都是系统进程的信息,这些位置返回的具体进程信息是,systemTaskInfos.get(position - userTaskInfo.size() - 2)。这就是我们界面上要显示的原理。请没有看明白的童鞋,仔细阅读几遍,若还是不明白,请在下面留言。我看到后会及时回复大家。
在这个类中新增一个boolean类型的字段isUserTask,标识当前进程是否是用户进程
具体代码实现如下:
//是否是用户进程
private boolean isUserTask = false;
public boolean isUserTask() {
return isUserTask;
}
public void setUserTask(boolean isUserTask) {
this.isUserTask = isUserTask;
}
在这个类中新增一个方法判断当前进程是否是用户进程,是返回true,不是返回false
具体代码实现如下:
//判断应用程序是否是用户程序
public static boolean filterApp(ApplicationInfo info) {
//原来是系统应用,用户手动升级
if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
return true;
//用户自己安装的应用程序
} else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
return true;
}
return false;
}
在这个方法的循环中,我们调用新增的判断是否是用户进程的方法,来判断当前进程是不是用户进程,并把判断结果设置到实体类的isUserTask属性中。
具体代码如下:
/**
* 获取系统所有的进程信息列表
* @param context
* @return
*/
public static List getTaskInfos(Context context){
List taskInfos = new ArrayList();
PackageManager pm = context.getPackageManager();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List runningAppProcesses = am.getRunningAppProcesses();
for(RunningAppProcessInfo info : runningAppProcesses){
TaskInfo taskInfo = new TaskInfo();
//进程名称
String packageName = info.processName;
taskInfo.setPackageName(packageName);
try {
ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName, 0);
//图标
Drawable task_icon = applicationInfo.loadIcon(pm);
if(task_icon == null){
taskInfo.setTask_icon(context.getResources().getDrawable(R.drawable.ic_launcher));
}else{
taskInfo.setTask_icon(task_icon);
}
//名称
String task_name = applicationInfo.loadLabel(pm).toString();
taskInfo.setTask_name(task_name);
//判断是否是用户程序
boolean isUserTask = filterApp(applicationInfo);
//设置是否是用户程序
taskInfo.setUserTask(isUserTask);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
taskInfo.setTask_icon(context.getResources().getDrawable(R.drawable.ic_launcher));
taskInfo.setTask_name(packageName);
}
//进程id
int pid = info.pid;
taskInfo.setPid(pid);
//获取进程占用的内存
android.os.Debug.MemoryInfo[] processMemoryInfo = am.getProcessMemoryInfo(new int[]{pid});
android.os.Debug.MemoryInfo memoryInfo = processMemoryInfo[0];
long totalPrivateDirty = memoryInfo.getTotalPrivateDirty(); //KB
taskInfo.setTask_memory(totalPrivateDirty);
taskInfos.add(taskInfo);
}
return taskInfos;
}
在这个类中,首先,我们新增两个属性字段,来封装所有的用户进程和所有的系统进程。
具体代码如下:
private List userTaskInfos;
private List systemTaskInfos;
在onCreate的子线程中,我们获取到所有的进程集合,同时我在这里实例化userTaskInfos和systemTaskInfos集合,遍历获取到的集合信息,根据进程信息中的isUserTask属性来区分是否是用户进程,来给userTaskInfos和systemTaskInfos集合添加数据,如果是用户进程,则添加到userTaskInfos集合,如果不是用户进程,则添加到systemTaskInfos集合。
具体代码如下:
new Thread(new Runnable() {
@Override
public void run() {
taskInfos = TaskUtils.getTaskInfos(getApplicationContext());
//分离用户程序和系统程序
userTaskInfos = new ArrayList();
systemTaskInfos = new ArrayList();
for(TaskInfo taskInfo : taskInfos){
if(taskInfo.isUserTask()){
userTaskInfos.add(taskInfo);
}else{
systemTaskInfos.add(taskInfo);
}
}
//发送消息机制
Message msg = new Message();
msg.what = SUCCESS_GETTASKINFO;
mHandler.sendMessage(msg);
}
}).start();
用户进程集合为userTaskInfos,系统进程集合为systemTaskInfos,首先,自定义适配器中返回的数据集合大小应该是用户进程集合大小加上系统进程集合大小再加上2,也就是userTaskInfo.size()+systemTaskInfos.size()+2,不明白的童鞋请看图仔细分析下。在这个ListView的第一个位置上,也就是position为0的位置,是一个TextView提示用户进程(用户进程数量),下面从position为1的位置一直到用户进程大小的位置上,一直显示的是用户进程的信息,这些位置返回的具体进程信息是,userTaskInfo.get(position-1);当position为userTaskInfo.size()+1的时候,又是一个TextView,提示的是系统进程(系统进程数量),下面列出的都是系统进程的信息,这些位置返回的具体进程信息是,systemTaskInfos.get(position - userTaskInfo.size() - 2)。同时为了屏蔽掉列表中的两个TextView的点击事件,我们复写了BaseAdapter中的isEnabled方法,这个方法要传递一个position参数,它的作用就是判定当前位置是否可以点击,当返回true时,可以点击,当返回false时,不可以点击。同时,为了不缓存textView我在这里作了判断,过滤掉缓存TextView的操作。
具体代码实现如下:
/**
* 自定义适配器
* @author liuyazhuang
*
*/
private class TaskManagerAdapter extends BaseAdapter{
private LayoutInflater mInflater;
private List infos;
public void setInfos(List infos) {
this.infos = infos;
}
public TaskManagerAdapter(){
mInflater = getLayoutInflater();
}
@Override
public boolean isEnabled(int position) {
// TODO Auto-generated method stub
if(position == 0){
return false;
}else if(position == userTaskInfos.size() + 1){
return false;
}
return super.isEnabled(position);
}
@Override
public int getCount() {
// return infos.size();
return userTaskInfos.size() + systemTaskInfos.size() + 2;
}
@Override
public Object getItem(int position) {
if(position == 0){
return null;
}else if(position <= userTaskInfos.size()){
return userTaskInfos.get(position - 1);
}else if(position == userTaskInfos.size() +1){
return null;
}else{
return systemTaskInfos.get(position - userTaskInfos.size() -2);
}
// return infos.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
ViewHolder holder = null;
if(position == 0){ //显示用户进行提示
TextView tv = new TextView(TaskManagerActivity.this);
tv.setText("用户进程"+"(" + userTaskInfos.size() + ")");
tv.setTextSize(20);
tv.setBackgroundColor(Color.GRAY);
return tv;
}else if(position <= userTaskInfos.size()){ //显示用户进程的列表
if(convertView != null && !(convertView instanceof TextView)){
view = convertView;
holder = (ViewHolder) view.getTag();
}else{
view = mInflater.inflate(R.layout.task_manager_item, null);
holder = new ViewHolder();
holder.iv_task_manager_icon = (ImageView) view.findViewById(R.id.iv_task_manager_icon);
holder.iv_task_manager_name = (TextView) view.findViewById(R.id.tv_task_manager_name);
holder.iv_task_manager_memory = (TextView) view.findViewById(R.id.tv_task_manager_memory);
//获取到UI上的CheckBox控件
holder.cb_task_manager_selected = (CheckBox) view.findViewById(R.id.cb_task_manager_selected);
view.setTag(holder);
}
TaskInfo taskInfo = userTaskInfos.get(position - 1);
holder.iv_task_manager_icon.setImageDrawable(taskInfo.getTask_icon());
holder.iv_task_manager_memory.setText("占用的内存:"+TextFormat.formatByte(taskInfo.getTask_memory()*1024));
holder.iv_task_manager_name.setText(taskInfo.getTask_name());
String packageName = taskInfo.getPackageName();
//应用程序是当前运行的程序
if(packageName.equals(getPackageName())){
holder.cb_task_manager_selected.setVisibility(View.GONE);
}else{
holder.cb_task_manager_selected.setVisibility(View.VISIBLE);
}
//获取条目的选中状态
boolean isChecked = taskInfo.isChecked();
if(isChecked){
holder.cb_task_manager_selected.setChecked(true);
}else{
holder.cb_task_manager_selected.setChecked(false);
}
return view;
}else if(position == userTaskInfos.size() + 1){ //显示系统进程提示
TextView tv = new TextView(TaskManagerActivity.this);
tv.setText("系统进程"+"(" + systemTaskInfos.size() + ")");
tv.setTextSize(20);
tv.setBackgroundColor(Color.GRAY);
return tv;
}else{ //显示系统进程列表
if(convertView != null && !(convertView instanceof TextView)){
view = convertView;
holder = (ViewHolder) view.getTag();
}else{
view = mInflater.inflate(R.layout.task_manager_item, null);
holder = new ViewHolder();
holder.iv_task_manager_icon = (ImageView) view.findViewById(R.id.iv_task_manager_icon);
holder.iv_task_manager_name = (TextView) view.findViewById(R.id.tv_task_manager_name);
holder.iv_task_manager_memory = (TextView) view.findViewById(R.id.tv_task_manager_memory);
//获取到UI上的CheckBox控件
holder.cb_task_manager_selected = (CheckBox) view.findViewById(R.id.cb_task_manager_selected);
view.setTag(holder);
}
TaskInfo taskInfo = systemTaskInfos.get(position - userTaskInfos.size() - 2);
holder.iv_task_manager_icon.setImageDrawable(taskInfo.getTask_icon());
holder.iv_task_manager_memory.setText("占用的内存:"+TextFormat.formatByte(taskInfo.getTask_memory()*1024));
holder.iv_task_manager_name.setText(taskInfo.getTask_name());
String packageName = taskInfo.getPackageName();
//应用程序是当前运行的程序
if(packageName.equals(getPackageName())){
holder.cb_task_manager_selected.setVisibility(View.GONE);
}else{
holder.cb_task_manager_selected.setVisibility(View.VISIBLE);
}
//获取条目的选中状态
boolean isChecked = taskInfo.isChecked();
if(isChecked){
holder.cb_task_manager_selected.setChecked(true);
}else{
holder.cb_task_manager_selected.setChecked(false);
}
return view;
}
}
}
代码有点长,请大家耐心看完,其实很多代码是相同的,我在这里没有做代码的重构操作,有兴趣的童鞋可以自己尝试下哦,加油!!
这个方法中现在要对userTaskInfos和systemTaskInfos两个集合进行操作,我在这里的逻辑主要是,创建一个集合killTaskInfos表示要杀死的进程集合,分别遍历两个集合,判断集合里面的进程是否被选中,如果被选中,则调用ActivityManager的killBackgroundProcesses方法杀掉进程,同时将杀掉的进程添加到killTaskInfos集合中。最后再写一个循环遍历killTaskInfos,分别判断进程信息的isUserTask属性,若为true则将其从userTaskInfos中移出,若为false,则从systemTaskInfos中移出,调用ListVIew的notifyDataSetChanged()方法更新UI。
具体代码实现如下:
/**
* 杀死进程
* @param v
*/
public void kill_process(View v){
//存放杀死的进程信息
List killTaskInfos = new ArrayList();
for(TaskInfo taskInfo : userTaskInfos){
if(taskInfo.isChecked()){
//杀死选中的进程
am.killBackgroundProcesses(taskInfo.getPackageName());
killTaskInfos.add(taskInfo);
}
}
for(TaskInfo taskInfo : systemTaskInfos){
if(taskInfo.isChecked()){
//杀死选中的进程
am.killBackgroundProcesses(taskInfo.getPackageName());
killTaskInfos.add(taskInfo);
}
}
//移出杀死的进程
for(TaskInfo taskInfo : killTaskInfos){
if(taskInfo.isUserTask()){
userTaskInfos.remove(taskInfo);
}else{
systemTaskInfos.remove(taskInfo);
}
}
mAdapter.notifyDataSetChanged();
}
本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在string.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。