近期列表Recents源码流程简单解析以及ActivityManager的简单使用:

来源:互联网 发布:邢台学院网络教学平台 编辑:程序博客网 时间:2024/06/05 08:46

android近期列表RecentsActivity的目录在/frameworks/base/packages/SystemUI/

frameworks的修改需要在fastboot模式下烧system.img文件。


首先,接受开机广播

 

处理它的Receiver类是BootReceiver。下面是Receiver的内容:


随后,在广播中开启了LoadAveragService服务。

SystemUiServier 服务也开启了

 

紧接着就是显示界面,主界面是RecentsActivity,首先onCreate(),onStart()

onCreate方法中发现布局文件是


接下来看一下布局文件


发现,基本都是自定义控件。

最下面的id = recents_no_apps,是列表中没有条目的时候才会显示。

查找会发现,这个id只有在RcentsPanelView中使用,接下来先看下:

定义一个View 


如果有apps的时候,就VISIBLE,否则就是INVISIABLE

上面noApps的值得来是根据mRecentTaskDescriptions,这是一个List


每一个app都保存成了一个TaskDescription。接下来看一下TaskDescription


它主要的字段有intent:用于跳转到应用,

    taskId,用于标识的id,比如删除,点击,跳转等使用。

  以及描述,包名等,icon等。。。

接着来查看一下当有信息的时候显示的布局,RecentsAcitvity的大布局是自定义的,实现类是RecentsPanelView


整个列表的大布局又放在了一个FrameLayout布局中,然后列表显示在一个自定义的布局中,实现类是RecentsVerticalScrollView

这个布局之后还有一个LinearLayout


简单解释几个参数

android:fitsSystemWindows="true"  字面意思就是使用系统窗口。总之是对布局的一种处理。

clipToPadding就是说控件的绘制区域是否在padding里面的,true的情况下如果你设置了padding那么绘制的区域就往里 缩,

clipChildren是指子控件是否超过padding区域,这两个属性默认是true的,所以在设置了padding情况下,默认滚动是在 padding内部的,要达到上面的效果主要把这两个属性设置了false那么这样子控件就能画到padding的区域了。

初始化列表,应该是在RecentsPanelView中完成的,

初始化简单到这里,接下来看看操作过程中的的流程。

首先,开机的时候,启动SystemUIServices,然后在onCreate中实例化了Recents

执行start(),然后执行closeRecents()方法。

开机后点击home键,会执行Recents类的preloadRecentTaskList方法。在里面启动了RecentsPreloadReceiver类。


销毁过程,首先是从内到外,SwipeHelper类中的onTouch方法对

MotionEvent.ACTION_CACEL进行匹配,方法实现如下:


前面绝大部分都是在得到能不能销毁的判断值dismissChild。如果可以销毁,就会执行

dismissChild(方法),如果滑动没有超过一定距离,就执行else中的内容。在上述方法中,基本实现的就是对动画的处理,如果显示动画效果,消除相应的view

紧接着就是RecentsVerticalScrollView类中的onChildDismissed()方法。


首先先看addToRecycledViews(v);从字面意思就是将需要消除的view添加到recycleview中。


一个简单的方法实现

然后就是mLinearLayout.removeView(v);在布局上移除相应的视图。

然后就是mCallback.handleSwipe(v);实际的实现在RecentsPanelView中。



首先获得TaskDescription,也就得到了某个条目的包括iddescription,等等信息。

然后每一个item是一个RecentTaskDescription对象,然后将这个对象移除了。

紧接着调用RecentTaskLoaderremove方法。


然后就是将存放的list集合的相应indexremove掉。


其实真正滑动销毁应用生效的一句话就是am.removeTask(ad.presistentTaskId,ActivityManager.REMOVE_TASK_KILL_PROCESS);

上面的内容是关键,根据存储的taskidkill掉相应的process


当长按home键直到显示RecentsActivity的过程中,流程log如下:


首先走的是Recetns类中的preloadRecentTaskList()方法。


在这个方法中,发送了广播RecentsPreloadReceiver

而且还调用了preloadFirstTask()方法来加载第一个Task

下图是RecentsPreloadReceiver的内容


当我们短按home键的时候,会先走if再走,再走else if,当长按home的时候,只走if,只有在home关闭的时候,才会走else if

说明,短按home键,也走了一遍查询的流程,然后瞬间又关闭掉了。

receiver中获得了RecentTaskLoader的实例后,调用了preloadRecentTaskList()方法,


在其中,用handler操纵了一个线程,线程中调用了loadTaskInBackground()方法,加载背景


下面就是loadTasksInBackground()方法


中间有个AsyncTask,用于加载初始化每个TaskdoInbackground中用for循环来遍历Task

For循环中有如下代码


每次加载一个task,都要调用createTaskDescription()方法


上面就是方法的内容。

接着会在BaseStatus类的toogleRecentActivity中调用Recents类的toogleRecents()方法。

 

然后就开始绘制界面,执行RecentsActivity类的oncreate方法

然后执行RecentVerticalScrollView类的setadapter,初始化列表。

然后执行onstart(),update(),.

当关闭这个界面的时候,会调用RecentPreloadReceiver中的RecentsActivity.CANCEL_PRELOAD_INTENT

然后RecentTasksLoader.getInstance(context).cancelPreloadingRecentTasksList();Cancel掉这个tasklist




然后调用RecentActivityonDestroy()


在方法体中进行了receiver的解绑

下面是onReceive中的操作,设置其show(false)


大致就是这样



ActivityManager

参考连接:http://androidbin.iteye.com/blog/1594908             http://www.apihome.cn/api/android/android.app

MainActivity

package com.example.activitymanagerdemo;import java.util.List;import android.app.Activity;import android.app.ActivityManager;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.view.KeyEvent;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MainActivity extends Activity implements OnClickListener {private Button button1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button1 = (Button) findViewById(R.id.btn1);button1.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn1:Intent intent = new Intent(this, TestActivity.class);startActivity(intent);// finish();break;default:break;}}}

TestActivity

package com.example.activitymanagerdemo;import java.util.Arrays;import java.util.List;import android.R.integer;import android.annotation.SuppressLint;import android.app.Activity;import android.app.ActivityManager;import android.app.ActivityManager.RecentTaskInfo;import android.app.ActivityManager.RunningAppProcessInfo;import android.app.ActivityManager.RunningServiceInfo;import android.content.ComponentName;import android.content.Context;import android.content.pm.ActivityInfo;import android.os.Bundle;import android.os.UserHandle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class TestActivity extends Activity {public ActivityManager am;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_main);am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);Button button = (Button) findViewById(R.id.btn1);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {getOrigRunningList();}});}/** * 需要添加权限android.permission.GET_TASKS * 界面是从MainActivity跳转到当前的TestAtivity的。 * 如果,没有finish掉MainAcitity,获得的getClassName()和cn.getShortClassName();获得的是关于MainActivity的 * 如果跳转的时候finish()掉,说明TestActtivity底部就没有其他的Activity了,得到的就是关于TestActivity的结果 */private void getRunningTaskName() {// 获取顶部的activityComponentName cn = am.getRunningTasks(1).get(0).topActivity;// 获取底部的activity。ComponentName cn1 = am.getRunningTasks(1).get(0).baseActivity;// 将maxTasks设置成2,就是最多获得两个应用的task。// get(x)中的值x,是获得应用的角标,最上面一层是0,依次往下是1、2、3...// get(1),就是获得第二层的应用,比如说我现在正在看短信,忽然电话来了,call应用覆盖了短信,call在上面,此时call应用就是get(0),// 短信mms就是get(1)。然后在决定获得短信的base还是topComponentName cn3 = am.getRunningTasks(2).get(1).baseActivity;ComponentName cn4 = am.getRunningTasks(2).get(1).topActivity;// 更具ComponentName获得需要的activity的名字String topAtyName = cn.getClassName();// 获得应用的包名String topPkgName = cn.getPackageName();// 获得“.MainActivity”形式的结果String topScName = cn.getShortClassName();System.out.println("topAtyName--->" + topAtyName);System.out.println("topPkgName--->" + topPkgName);System.out.println("topScName--->" + topScName);}/** * 获取表示task的id,进行销毁操作 */private void getRunningtaskList() {List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(1,ActivityManager.RECENT_IGNORE_UNAVAILABLE);ActivityManager.RecentTaskInfo rtInfo = recentTasks.get(0);int persistentId = rtInfo.persistentId;int id = rtInfo.id;System.out.println("persistentId--->" + persistentId);System.out.println("id--->" + id);// 可以根据唯一的标识task id进行销毁应用// am.removeTask(persistentId,// ActivityManager.REMOVE_TASK_KILL_PROCESS);}/** * 获得系统正在运行的进程 */private void getRuningProcessList() {List<ActivityManager.RunningAppProcessInfo> appList1 = am.getRunningAppProcesses();for (RunningAppProcessInfo running : appList1) {System.out.println("process--->" + running.processName);System.out.println("pid--->" + running.pid);// 所有已加载到进程中的包。大部分只有一个包名,和processName一致,个别的有两个包名System.out.println("pkgList--->" + Arrays.toString(running.pkgList));System.out.println("uid--->" + running.uid);}}/** * 获得系统正在运行的service */private void getRunningServiceList() {List<ActivityManager.RunningServiceInfo> serviceList = am.getRunningServices(1000);for (RunningServiceInfo running : serviceList) {System.out.println("--->" + running.service.getClassName());System.out.println("--->" + running.service.getPackageName());}}private void getOrigRunningList() {List<ActivityManager.RecentTaskInfo> origList = am.getRecentTasks(100,1);for (RecentTaskInfo running : origList) {System.out.println("origActivityName--->>"+ running.origActivity.getClassName());System.out.println("origPkgName--->>"+ running.origActivity.getPackageName());}}}




http://www.apihome.cn/api/android/android.app

ActivityManager--获得正在运行的activitiy与service   http://androidbin.iteye.com/blog/1594908

Android中获取正在运行的应用程序--ActivityManager.RunningAppProcessInfo类详解  http://blog.csdn.net/qinjuning/article/details/7009824

Android中获取系统内存信息以及进程信息--ActivityManager的使用  http://blog.csdn.net/qinjuning/article/details/6978560







0 0
原创粉丝点击