warning
真机运行的时候,会有一些系统的核心进程时无法获取到的,他只有一个包名,没有manifest里的icon、activity什么的,用包名去获取时没有内容的
所以获取不到的时候会报上面的问题
在工具类的异常处理里,把包名拿到就好
} catch (NameNotFoundException e) {
e.printStackTrace();
//一些无法显示的核心经常的包名显示出来
ProcessInfo pinfo = new ProcessInfo(packagename, null, is_user, memory_usage, packagename);
processinfos.add(pinfo);
}
显示不同进程类别的框框
refreshData();
lv_procmanage_procinfolist.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
if (firstVisibleItem>user_proinfolist.size()+1) {
tv_procmanage_class.setText("系统进程("+sys_proinfolist.size()+")个");
}
else {
tv_procmanage_class.setText("用户进程("+user_proinfolist.size()+")个");
}
}
});
checkbox的勾选状态的问题,在滑动之后,划出去的若勾选了,由于convert的作用,也给了划进来的item勾上了
故而需要一个判断,在bean里需要一个ischecked,并且一开始就给他一个false的初值,工具类里也要获取这个状态
之前已经都写好了,这里不单独列出来了
然后划回来,勾选的没有了,因为是根据info获取的,而之前设置了默认为false
需要一个itemlistener
注意一些细节,滑出滑进,父控件与checkbox自己的点击问题,刷UI
lv_procmanage_procinfolist.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
ProcessInfo procInfo;
if (position< user_proinfolist.size()+1) {
procInfo = user_proinfolist.get(position-1);
}else {
procInfo = sys_proinfolist.get(position-user_proinfolist.size()-2);
}
if ("com.rjl.mobilephonemanager".equals(procInfo.getPackagename())) {
return;
}
//当前没被勾选,点击后应为true,记住了,方便滑进滑出
//layout里的checkbox要设为false,这样只能点击父控件
if (!procInfo.isIschecked()) {
procInfo.setIschecked(true);
}else {
procInfo.setIschecked(false);
}
//点击后要刷新下,负责只是改了数据而UI不变
if (adapter!=null) {
adapter.notifyDataSetChanged();
}
}
});
完成业务逻辑,清理进程
先有4个button
这里有一个属性 layout_weight 若后面直接跟一个数字,则表示渲染优先级,越大优先级越低,所以这里先显示了下面的linearlayout,他们的button都用了包裹内容
而上面的帧布局后显示。这样子不用去把权重写死,写死权重有时候未必合适
<pre name="code" class="html"><FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1000">
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/lv_procmanage_procinfolist">
</ListView>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#798091"
android:textColor="#FFFFFF"
android:textSize="15sp"
android:id="@+id/tv_procmanage_class"/>
</FrameLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="全选"
android:layout_marginBottom="2dp"
android:onClick="selectall"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="取消"
android:layout_marginBottom="2dp"
android:onClick="cancle"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="清理"
android:layout_marginBottom="2dp"
android:onClick="kill" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="设置"
android:layout_marginBottom="2dp"
android:onClick="setting"/>
</LinearLayout>
对比另一种写法
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="5">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:layout_weight="1">
上面写法,会先显示帧布局
public void selectall(View v){
}
public void cancle(View v){
}
public void kill(View v){
}
public void setting(View v){
}
全选
public void selectall(View v){
for(ProcessInfo p : user_proinfolist){
if ("com.rjl.mobilephonemanager".equals(p.getPackagename())) {
continue;
}
p.setIschecked(true);
}
for(ProcessInfo p : sys_proinfolist){
p.setIschecked(true);
}
//刷UI
if (adapter!=null) {
adapter.notifyDataSetChanged();
}
}
取消
public void cancle(View v){
for(ProcessInfo p : user_proinfolist){
p.setIschecked(false);
}
for(ProcessInfo p : sys_proinfolist){
p.setIschecked(false);
}
if (adapter!=null) {
adapter.notifyDataSetChanged();
}
}
设置
public void setting(View v){
if (show_sysproc) {
show_sysproc=false;
}
else {
show_sysproc=true;
}
if (adapter!=null) {
adapter.notifyDataSetChanged();
}
}
大头戏 清理进程 后台进程,需要权限
killBackgroundProcesses方法
public void kill(View v){
ActivityManager ams = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for(ProcessInfo p : user_proinfolist){
if (p.isIschecked()) {
ams.killBackgroundProcesses(p.getPackagename());
user_proinfolist.remove(p);
}
}
for(ProcessInfo p : sys_proinfolist){
if (p.isIschecked()) {
ams.killBackgroundProcesses(p.getPackagename());
sys_proinfolist.remove(p);
}
}
//干掉后台进程(前台 可见 服务 后台 空)
if (adapter!=null) {
adapter.notifyDataSetChanged();
}
}
但是有问题,不能一边遍历一边删除其中的元素
把删除的方法单独列出来
public void kill(View v){
ActivityManager ams = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
//遍历完了再更改,记录一下
List<ProcessInfo> deletedProc = new ArrayList<ProcessInfo>();
for(ProcessInfo p : user_proinfolist){
if (p.isIschecked()) {
ams.killBackgroundProcesses(p.getPackagename());
/*user_proinfolist.remove(p);*/ //不能一边遍历一边删除元素
}
}
for(ProcessInfo p : sys_proinfolist){
if (p.isIschecked()) {
ams.killBackgroundProcesses(p.getPackagename());
/*sys_proinfolist.remove(p);*/
}
}
//不能直接对线程的列表边遍历边删除
//删完记录下来,再去把两个数据源改掉,改完再刷UI
for(ProcessInfo proc : deletedProc){
if (proc.isIs_user()) {
user_proinfolist.remove(proc);
}
else {
sys_proinfolist.remove(proc);
}
}
//干掉后台进程(前台 可见 服务 后台 空)
if (adapter!=null) {
adapter.notifyDataSetChanged();
}
}
这时候有一个bug,全选后再删除,会挂掉
全选后会全部记录在节点里,然后全部删除,这个时候sys_proinfolist里就没东西,然后adapter要getView,他要根据sys_proinfolist里的位置来操作(position+2),现在是空的,故而有问题报错
@Override
public int getCount() {
// TODO Auto-generated method stub
if (show_sysproc) {
listcount = processinfolist.size()+2;
}else {
listcount= user_proinfolist.size()+1;
}
//显示的是总数减掉我们点击的要清除掉的线程数
<span style="color:#ff0000;">return listcount-deletecount;</span>
}
for(ProcessInfo proc : deletedProc){
if (proc.isIs_user()) {
user_proinfolist.remove(proc);
}
else {
sys_proinfolist.remove(proc);
}
}
//要删除的个数
<span style="color:#ff0000;">deletecount = deletedProc.size();</span>
//干掉后台进程(前台 可见 服务 后台 空)
if (adapter!=null) {
adapter.notifyDataSetChanged();
动态显示删除后的进程数
先要有原有的进程数
//获得原有进程数
int old_count = user_proinfolist.size()+sys_proinfolist.size();
for(ProcessInfo p : user_proinfolist){
//要删除的个数
deletecount = deletedProc.size();
//当前进程数
tv_processmanage_num.setText("当前手机进程数为\n"+(old_count-deletecount));
进程清理后,内存也要变
//初始化初始空闲空间
int free_memory = 0;
for(ProcessInfo p : user_proinfolist){
for(ProcessInfo proc : deletedProc){
if (proc.isIs_user()) {
user_proinfolist.remove(proc);
}
else {
sys_proinfolist.remove(proc);
}
<span style="color:#ff0000;">free_memory += proc.getMemory_usage();</span>
}
这里统计并不十分精确,因为系统存在共享的情况