近期列表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添加到recycle的view中。
一个简单的方法实现
然后就是mLinearLayout.removeView(v);在布局上移除相应的视图。
然后就是mCallback.handleSwipe(v);实际的实现在RecentsPanelView中。
首先获得TaskDescription,也就得到了某个条目的包括id,description,等等信息。
然后每一个item是一个RecentTaskDescription对象,然后将这个对象移除了。
紧接着调用RecentTaskLoader的remove方法。
然后就是将存放的list集合的相应index给remove掉。
其实真正滑动销毁应用生效的一句话就是am.removeTask(ad.presistentTaskId,ActivityManager.REMOVE_TASK_KILL_PROCESS);
上面的内容是关键,根据存储的taskid,kill掉相应的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,用于加载初始化每个Task。doInbackground中用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。
然后调用RecentActivity的onDestroy()
在方法体中进行了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
- 近期列表Recents源码流程简单解析以及ActivityManager的简单使用:
- ActivityManager的简单使用
- Android近期任务列表Recent List(Recents Screen)的实现方式
- 简单的列表解析
- SpringMVC的执行流程及源码简单解析
- 简单的源码解析
- Spring定时任务的实现方式--ScheduledExecutorService and ScheduledExecutorFactoryBean的简单源码解析以及使用
- AsyncTask源码解析,简单使用
- Handler源码的简单解析
- python列表的简单使用
- MapReduce流程简单解析
- MVVM的简单使用流程
- Lottie源码简单分析以及使用
- 简单Rxjava订阅的源码流程分析
- EventBus简单使用和源码解析
- 简单解析PHP程序的运行流程
- 对Android近期任务列表(Recent Applications)的简单分析
- 对Android近期任务列表(Recent Applications)的简单分析
- 实现页面侧滑的两种方式GestureDetector和ViewPager
- Poj.3100 Root of the Problem【水】 2015/09/22
- 无锁编程(三) - 忙等待
- java多线程关键字synchronized用法
- springMVC + Mybatis delete 返回值
- 近期列表Recents源码流程简单解析以及ActivityManager的简单使用:
- JAVA 处理Word模板文件,替换其中的占位符
- maven构建eclipse工程的编码问题
- c++ 使用throw抛出异常
- 在html中打开app
- BZOJ 4264 小C找朋友
- HDU 5444 Elven Postman(重建二叉树)
- hive建表存储格式造成的问题
- phpfpm使用自带的status优化步骤