Launcher介绍总结

http://blog.csdn.net/ldinvicible/article/details/8488126


一、主要文件和类 

1.Launcher.java:launcher中主要的activity。

 

2.DragLayer.java:launcher layout的根view。DragLayer实际上也是一个抽象的界面,用来处理拖动和对事件进行初步处理然后按情况分发下去,角色是一个controller。它首先用onInterceptTouchEvent(MotionEvent)来拦截所有的touch事件,如果是长按item拖动的话不把事件传下去,直接交由onTouchEvent()处理,这样就可以实现item的移动了,如果不是拖动item的话就把事件传到目标view,交有目标view的事件处理函数做相应处理。如过有要对事件的特殊需求的话可以修改onInterceptTouchEvent(MotionEvent)来实现所需要的功能。

 

3. DragController.java:为Drag定义的一个接口。包含一个接口,两个方法和两个静态常量。接口为DragListener(包含onDragStart(),onDragEnd()两个函数),onDragStart()是在刚开始拖动的时候被调用,onDragEnd()是在拖动完成时被调用。在launcher中典型的应用是DeleteZone,在长按拖动item时调用onDragStart()显示,在拖动结束的时候onDragEnd()隐藏。函数包括startDrag()用于在拖动时传递要拖动的item的信息以及拖动的方式。他有两个常量为DRAG_ACTION_MOVE,DRAG_ACTION_COPY来标识拖动的方式,DRAG_ACTION_MOVE为移动,表示在拖动的时候需要删除原来的item,DRAG_ACTION_COPY为复制型的拖动,表示保留被拖动的item(未使用)。

 

4.LauncherModel.java:辅助的文件。里面有许多封装的对数据库的操作。loadAndBindAllApps加载所有应用程序,loadAndBindWorkspace加载workspace。其他的函数就是对数据库的封装,比如在删除,替换,添加程序的时候做更新数据库和UI的工作。

 

5.Workspace.java:抽象的桌面,继承自ViewGroup,是一个子view。由N个celllaout组成,从cellLayout更高一级的层面上对事件的处理。

 

6.LauncherProvider.java:launcher的数据库,里面存储了桌面的item的信息。在创建数据库的时候会loadFavorites(db)方法,loadFavorites()会解析xml目录下的default_workspace.xml文件,把其中的内容读出来写到数据库中,这样就做到了桌面的预制。

 

7.CellLayout.java:组成workspace的view,继承自viewgroup,既是一个dragSource,又是一个dropTarget,可以将它里面的item拖出去,也可以容纳拖动过来的item。在workspace_screen里面定了一些它的view参数。

 

8.ItemInfo.java:对item的抽象,所有类型item的父类,item包含的属性有id(标识item的id),cellX(在横向位置上的位置,从0开始),cellY(在纵向位置上的位置,从0开始) ,spanX(在横向位置上所占的单位格),spanY(在纵向位置上所占的单位格),screen(在workspace的第几屏,从0开始),itemType(item的类型,有widget,search,application等),container(item所在的)。

 

9.UserFolder.java: 用户创建的文件夹。可以将item拖进文件夹,单击时打开文件夹,长按文件夹上面标题处可以重命名文件夹。

 

10.LiveFolder.java:系统自带的文件夹。从系统中创建出的如联系人的文件夹等。 

 

11.DeleteZone:删除框。在平时是出于隐藏状态,在将item长按拖动的时候会显示出来,如果将item拖动到删除框位置时会删除item。DeleteZone实现了DropTarget和DragListener两个接口。

 

12.LauncherSettings.java:字符串的定义。数据库项的字符串定义,另外在这里定义了container的类型,还有itemType的定义,除此还有一些特殊的widget(如search,clock的定义等)的类型定义。

 

主要布局文件介绍:

packages/apps/Launcher2/res/layout-port/launcher.xml 

总布局文件竖屏,主要显示workspace  HandleView等按键

/packages/res/Launcher2/res/workspase_screen.xml   

cell的数量及显示大小

/packages/res/Launcher2/res/layout/AllAppSpace.xml

显示allapp界面布局(注意不是all_apps_2d.xml

/packages/res/Launcher2/res/xml/default_workspace.xml

显示在workspace上默认的控件位置设置

/packages/res/Launcher2/res/xml/workspace_settings.xml

Workspace界面一些特效设置选项

/packages/res/Launcher2/res/layout/allapp_workspace_screen.xml

All app界面app布局显示

/packages/apps/Launcher2/res/layout-port/all_apps_horizontal.xml

All app界面布局显示(包括指示图标与app布局)

 

 

二、LauncherApplication全局数据初始化过程

LauncherApplication是Application的子类,是整个程序的入口。因此,一些全局信息的初始化和保存工作就放到这里执行。包括屏幕大小,像素密度信息的获取,以及

BroadcastReceiver和ContentObserver的注册都在整个程序的开始就完成。

1、  VMRuntime.getRuntime().setMinimumHeapSize(4 * 1024 * 1024)

设置运行最小堆内存

2、  mIconCache = new IconCache()

实例化图标缓存区的对象

3、  mModel = new LauncherModel()

实例化一个LauncherModel对象,这个类是保存Launcher的内存启动状态,更新Launcher的数据库的作用  

4、  IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);

注册监听,应用package增加,删除,改变的监听。

5、  filter = new IntentFilter() 

注册application是否可用,方向改变的监听

6、 ContentResolver resolver = getContentResolver(),resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URItrue, mFavoritesObserver)。

注册favorites应用程序数据库改变的监听  

7、初始化all app信息

数据库mFavoritesObserver监听内部类

    private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {

        @Override

        public void onChange(boolean selfChange) {

            mModel.startLoader(LauncherApplication.thisfalse);

        }

    };

 

 

三、Launcher.java的onCreate()  所有界面初始化过程

LauncherApplication.onCreate()方法启动完成后,接着开始调用Launcher.java的onCreate()方法之后开始初始化Launcher。

 

可以将Launcher.onCreate()所执行的操作大概分为以下几步:

 

1、  LauncherAppliaction.setLauncher()。

此方法中得到一个LauncherModel对象的引用,LauncherModel这个类中有个回调接口。对LauncherModel进行初始化的时候

public void initialize(Callbacks callbacks){
           synchronized(mLock) {
                 mCallbacks= new WeakReference<Callbacks>(callbacks);
        }
}

由于Launcher实现了Callback接口。在mModel中,将传入的Launcher对象向下转型为Callback赋值给mCallbacks变量。并在LauncherModel中获得了一个Callbacks的软引用。通过这一过程,Launcher对象作为CallbackmModel进行绑定,当mModel后续进行操作时,Launcher可以通过回调得到结果

 

2、  AppWidgetHost.startListening(),

作用:帮助Launcher管理AppWidget,并且能够捕获长按事件,使得应用可以正常的删除、添加AppWidget。通过调用mAppWidgetHost.startListening()方法,开启监听。

 

3、  checkForLocaleChange()

检查本地文件的配置与当前设备的配置是否一致,如果不一致,则更新配置,并且清空IconCache,因为配置的改变可能会改变语言环境,所以需要清空IconCache中的内容重新加载。

 

4、  setupViews(),对所有的UI控件进行加载和配置

DragLayer dragLayer = (DragLayer)findViewById(R.id.drag_layer);

dragLayer.setDragController(dragController);

DragLayer继承自FrameLayout,是整个Launcher的根容器。当快捷图标或者AppWidget被拖拽时,事件的处理就在DragLayer进行操作的。DragController可以帮助实现拖拽。

 

在loadHotseats();中,加载hotseats 增加intent意图启动的activity。

 

dragController.setDragScoller(workspace);

dragController.setDragListener(deleteZone);

dragController.setScrollView(dragLayer);

dragController.setMoveTarget(workspace);

对workspace,deleteZone进行拖拽,move等动作的监听。

dragController.addDropTarget(workspace);

dragController.addDropTarget(deleteZone);

在workspace,deleteZone中注册增加目标如application,appwidget等控件的监听。

 

5、registerContentObservers(),设置内容监听器

6、LauncherModel.startLoader(),为Launcher加载Workspace和AllApps中的内容

if(!mRestoring) {

         //mModel.setmAppsLoading(true);

    mModel.startLoader(thistrue);

}

之后调用

public void startLoader(Context context,boolean isLaunching,boolean onlyLoadAllApp) {

…  …

mLoaderTask =new LoaderTask(context, isLaunching,onlyLoadAllApp);

sWorker.post(mLoaderTask);

}

说明:mModel.startLoader(。。,。。)是开启一个线程,设置线程的优先级NORM_PRIORITY,开始load桌面图标对应的数据库,这个过程是和Launcher.onCreate()同时进行的;

mModel.startLoader(。。,。。) à  LoaderTask.java的run()方法,加载桌面图标对应的数据库的值,这些值能把这些图标显示在workspace屏幕上。

public voidrun() {

… …

    keep_running: {

         ……

        if (loadWorkspaceFirst) {

               if (DEBUG_LOADERS)Log.d(TAG, "step 1: loading workspace");

                loadAndBindWorkspace();

           } else {

                if (DEBUG_LOADERS)Log.d(TAG, "step 1: special: loading all apps");

                loadAndBindAllApps();

            }

            if (mStopped) {

                break keep_running;

            }

                            ……

              waitForIdle();

                // second step

  if(!mOnlyLoadAllApp){// here , we do not load other ,only All_app because of All_APP Switch

       if (loadWorkspaceFirst) {

           if (DEBUG_LOADERS) Log.d(TAG, "step 2:loading all apps");

               loadAndBindAllApps();

            } else {

            if (DEBUG_LOADERS) Log.d(TAG, "step 2:special: loading workspace");

                loadAndBindWorkspace();

              }

       }

  }……

}

 

加载的工作由两部分组成,第一部分是为Workspace加载内容,第二部分则是为AllApps加载内容。每一部分的加载又可以分为两个步骤:

 

1、由LauncherModel完成,主要工作是从数据库中读取信息,并且按类别将内容项分装到不同的数据结构中。

2、由Launcher来完成,通过LauncherModel.Callbacks接口定义的回调方法,从LauncherModel

中获取的数据,将其显示到桌面。

 

第一部分在loadWorkspace中,从ContentProvider获取指定URI中的数据,并将它们分类存放到指定的数据结构中。分类的标准有两条:1、item的类型。包括ITEM_TYPE_APPLICATION  ,ITEM_TYPE_SHORTCUT ,ITEM_TYPE_USER_FOLDER,ITEM_TYPE_APPWIDGET,ITEM_TYPE_LIVE_FOLDER五类。2、item所属的容器。包括CONTAINER_DESKTOP

以及其它(主要指文件夹)。

 

LauncherModel在读取完数据之后,通过LauncherModel.bindWorkspace()将数据传给到Launcher。进入LauncherModel.bindWorkspace()中

 

在bindWorkspace中,

Launcher的内容绑定分为五步:分别对应着startBinding()、bindItems()、bindFolders()、bindAppWidgets()、finishBindingItems()的调用。

 

第二部分AllApps的内容加载loadAndBindAllApps

首先是查询所有的App了,通过向PackagedManager发送指定的Intent就能够获得安装好的应用的信息。查询完毕之后,将数据封装到ArrayList<ApplicationInfo>对象中,然后通过Callbacks.bindAllApplication()或Callbacks.bindAppsAdded()将数据传给Launcher。

 

在这个方法中,还涉及到app排序问题,

Collections.sort(apps,newResolveInfo.DisplayNameComparator(packageManager));

至此All Apps页面的加载完成。

 

其中all app布局显示在从Callbacks.bindAllApplications –> setApps(à addApps()  à

initLayout() à setViewInLayout()(其中通过mHandler.sendEmptyMessage(SORTFINISH);) à

handleMessage() –> 显示屏上app如何布局

 

 

四、workspace触摸事件处理过程

在Launcher的View tree中,从上到下的主要的节点有,DragLayerWorkspace

CellLayout。DragLayer层的主要任务是负责对图标和AppWidget进行拖拽,Workspace则主要负责左右滑动,CellLayout则用于容纳各种桌面的快捷方式

桌面滑动功能主要分两步:1、在onInterceptTouchEvent中进行拦截。2、在onTouchEvent中进行滑动。

在workspace.java中的onInterceptTouchEvent()函数中中

TOUCH_STATE_SCROLLING  状态—> 正在滑动

TOUCH_STATE_REST   状态—> 初始化状态,未滑动

acquireVelocityTrackerAndAddMovement(ev)获取速度跟踪器,记录各个时刻的速度。并且添加当前的MotionEvent以记录更行速度值。  

public booleanonInterceptTouchEvent(MotionEvent ev) {

                   ……

       return mTouchState != TOUCH_STATE_REST;

}

只有进入了滑动状态,才进行拦截,进入onTouchEvent执行滑动操作。当mTouchState != TOUCH_STATE_REST  时,就说明没有进入滑动状态。(因为return  true)。

当mTouchState==TOUCH_STATE_REST时,不需要任何滑动操作,将MotionEvent向子View传递。

开始桌面静止,则mTouchState==TOUCH_STATE_REST,触发switch分支中

MotionEvent.ACTION_DOWN的代码。记录按下点的坐标,设置mAllowLongPress=true。由于mTouchState=TOUCH_STATE_REST,所以动作被传向了子View。接下来,在长按事件被触发之前移动手指则会在代码中调用enableChildrenCache(mCurrentScreen - 1,mCurrentScreen + 1)来决定是否进入滑动状态。进入滑动状态之后mTouchState的值就变为TOUCH_STATE_SCROLLING,然后onTouchEvent中的操作就会被用,开始滑动。

 

在workspace中的onTouchEvent()函数,对接受到的不同的事件进行了分类的处理,大致可以将功能分类为:

1、当接受到ACTION_DOWN时,若滑动正在进行,则停止。

2、当接受到ACTION_MOVE时,根据当前的状态调用scrollBy进行滑动。

3、当接受到ACTION_UP时,根据当前所滑动的位移和速度,判断松手后进入到哪一个分屏。

 

 

在Workspace.Java类实现,相关方法有: 
1) computeScroll():重写了父类的computeScroll();主要功能是计算拖动的位移量、更新背景、设置要显示的屏幕(setScreen(mCurrentScreen);)

。 
2) dispatchDraw():重写了父类的dispatchDraw();主要功能是绘制指定的屏幕,可以绘制当前一屏,也可以绘制当前屏幕和下一屏幕,也可以绘制所有的屏幕,这儿的绘制指显示屏幕上的child(例如:app、folder、Wiget)。 


3) onMeasure():重写了父类的onMeasure();主要功能是设置屏幕的显示大小。由每个child的measure()方法设置。 


4) onLayout():重写了父类的onLayout();主要功能是设置屏幕的显示位置。由child的layout()方法设置。 

 

五、Drop& Drag模型:DragController.java  处理拖曳动作的函数

         DragSource:可以拖动对象来源的容器。

在launcher中主要有AllAppGridView,workspace等。

 将调用此接口:voidonDropCompleted(View target, boolean success,int x,int y);

 

DropTarget:可以放置被拖动的对象的容器。

在launcher中有folder,workspace等,一个View既可以是Dragsource也可以是DropTarget。

 

主要包含以下几个接口:

boolean acceptDrop(DragSource source, intx, int y, int xOffset, int yOffset, Object dragInfo);

acceptDrop函数用来判断dropTarget是否可以接受item放置在自己里面。

 

void onDragEnter(DragSource source, int x,int y, int xOffset, int yOffset, Object dragInfo);

          onDragEnter是item被拖动进入到一个dropTarget的时候的回调。

 

void onDragOver(DragSource source, int x,int y, int xOffset, int yOffset, Object dragInfo);

          onDragOver是item在上一次位置和这一次位置所处的dropTarget相同的时候的回调。

 

void onDragExit(DragSource source, int x,int y, int xOffset, int yOffset, Object dragInfo);

          onDragExit是item被拖出dropTarget时的回调。

 

boolean onDrop(DragSource source, int x,int y, int xOffset, int yOffset, Object dragInfo);

     onDrop是item被放置到dropTarget时的回调。 

 

例如:onDrop在drop()方法中被调用。

Drop()被DragController.java中的onInterceptTouchEvent()或onTouchEvent()调用

    privateboolean drop(float x, float y) {

       final int[] coordinates = mCoordinatesTemp;

       DropTarget dropTarget = findDropTarget((int) x, (int) y,coordinates);

       Log.d(TAG, "dropTarget exist is "+ (dropTarget!=null));

       if (dropTarget != null) {

           dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],

                    (int) mTouchOffsetX,(int) mTouchOffsetY, mDragView, mDragInfo);

//判断dropTarget是否接受接受item放置

           if (dropTarget.acceptDrop(mDragSource, coordinates[0],coordinates[1],

                    (int) mTouchOffsetX,(int) mTouchOffsetY, mDragView, mDragInfo)) {

                dropTarget.onDrop(mDragSource,coordinates[0], coordinates[1],

                        (int) mTouchOffsetX,(int) mTouchOffsetY, mDragView, mDragInfo);

               mDragSource.onDropCompleted((View) dropTarget, true);

                return true;

           } else {

               mDragSource.onDropCompleted((View) dropTarget, false);

                return true;

           }

       }

       return false;

}

 

六、 Launcher 中 View 、ViewGroup事件处理:

        事件处理主要方法:

1)public booleandispatchTouchEvent(MotionEvent ev)  这个方法用来分发TouchEvent

2)public booleanonInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent(只有ViewGroup中有此函数

3)public booleanonTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent(ViewGroup与View中都有)

需要注意以下几点:
1、onInterceptTouchEvent()返回true,那么这个方法只会拦截动作ACTION_DOWN。

2、onInterceptTouchEvent()负责事件分发(事件传递方向),决定了Touch事件是否要向它包含的子View继续传递。

3、onTouchEvent()负责事件处理。决定了事件及后续事件是否继续向上传递。

 

 

当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的dispatchTouchEvent ,然后由  dispatchTouchEvent 方法进行分发,

 

1)如果dispatchTouchEvent返回true ,则交给这个view(本view的onTouchEvent处理,

 

2)如果dispatchTouchEvent返回 false ,则交给这个 view(本view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,

 

3)如果interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,

(本ViewGroup的interceptTouchEvent 只能收到down事件,本ViewGroup的onTouchEvent能收到down,move,up事件,子view不能收到事件)

 

4)如果interceptTouchEvent返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。(本ViewGroup的onInterceptTouchEvent能收到down,move,up事件,本ViewGroup的onTouchEvent没有收到事件;之后(指onInterceptTouchEvent接受所有事件后)子view的onTouchEvent能收到up,move,down事件)

 

5)如果事件传递到某一层的子 view 的onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。

(本view的onTouchEvent只能收到down事件,不能收到move,up事件

 

6)而如果传递到最上面的onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。

 

7)如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

注意1:只要onInterceptTouchEvent()返回false,而且目标控件View::onTouchEvent()返回true,那么事件的每一个动作(按下、移动、抬起等)会都会首先传递到onInterceptTouchEvent()中。

 

注意2:如果事件传递到某一层的子 view  onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会消失,而且接收不到下一次事件。(一次事件指的是 down  up 之间的一系列事件)

 

总结一下就是:onInterceptTouchEvent可以接受到所有的Touch事件,而onTouchEvent则不一定,总体来看, onInterceptTouchEvent是自rootview向下传递, onTouchEvent正好相反。

 

 

备注:关于onClick、onLongClick及onTouchEvent时序上处理过程分析:

在一个View中同时覆写了onClick、onLongClick及onTouchEvent的话,onTouchEvent是最先捕捉到ACTION_DOWN和ACTION_UP事件的,其次才可能触发onClick或者onLongClick。
1,onTouch返回false
首先是onTouch事件的down事件发生(返回false),此时,如果长按,触发onLongClick事件;然后是onTouch事件的up事件发生,up完毕,最后触发onClick事件。

2,onTouch返回true
首先是onTouch事件的down事件发生,然后是onTouch事件的up事件发生;期间不触发onClick和onLongClick事件

3,onTouch:down返回true,up返回false:结果同二。


详细分析:

onTouch事件中:down事件返回值标记此次事件是否为点击事件(返回false,是点击事件;返回true,不记为点击事件(为该事件已经被处理)),而up事件标记此次事件结束时间,也就是判断是否为长按。只要当down返回true时候,系统将不把本次事件记录为点击事件,也就不会触发onClick或者onLongClick事件了。因此尽管当up的时候返回false,系统也不会继续触发onClick事件了。

4,onTouch:down返回false,up返回true:
首先是onTouch事件的down事件发生,此时:
长按,触发onLongClick事件,然后是onTouch事件的up事件发生,完毕。
短按,先触发onTouch的up事件,到一定时间后,自动触发onLongClick事件。
机制分析:
  onTouch事件中:down事件返回值标记此次事件是否为点击事件(返回false,是点击事件;返回true,不记为点击事件),而up事件标记此次事件结束时间,也就是判断是否为长按。
  当down返回false,标记此次事件为点击事件,而up返回了true,则表示此次事件一直没有结束,也就是一直长按下去了,达到长按临界时间后,自然触发长按事件,而onClick事件没有触发到。

 

总结:

onLongClick发生只有在down为false,up为任意时发生;

Onclick发生在down为false,up为false时发生,

七、关于launcher中

Activity 、View 、Window 、 ViewRoot 、DecorRoot介绍及几者之间的关系:

相关类图


(1)  activity: 是逻辑上的东西,增加了生命周期管理等. 里面具体的东西也是view。而且启动activity的实现也是往window里加view,包含一个Window,该Window在Activity的attach方法中通过调用PolicyManager.makeNewWindow创建。

 

(2)  View:  最基本的UI组件,表示屏幕上的一个矩形区域,通过 setContentView这个接口进Window显示。1、所有高级UI组件都继承View类而实现的2、一个View在屏幕上占据一块矩形区域3、负责渲染4、负责处理发生的事件5、设置是否可见6、设置是否可以获得焦点等

 

(3). ViewGroup  1、ViewGroup View的子类2、View的容器 3、负责对添加进ViewGroup的View进行布局 4、一个ViewGroup可以加入到另一个ViewGroup5、各种layout继承自ViewGroup。ViewGroup  与View关系图如下

 

(4). widget 1、界面中展示的各个小组件2、有独立的事件处理能力3、所有Wiget组件都是继承View而来,继承自View或ViewGroup。

(5)  Window:该类提供了一组通用的窗口(Window)操作API,这里的窗口仅仅是程序层面上的,WmS所管理的窗口并不是Window类,而是一个View或者ViewGroup类,一般就是指DecorView类,即一个DecorView就是WmS所管理的一个窗口。Window是一个abstract类型。

 

(6)  PhoneWindow:是Android中的最基本的窗口系统,每个Activity均会创建一个PhoneWindow对象,是Activity和整个View系统交互的接口。

 

(7)  DecorView:DecorView是当前Activity所有View的祖先,该类是一个FrameLayout的子类,并且是PhoneWindow中的一个内部类。DecorView就是对普通的FrameLayout进行了一定的修饰,比如添加一个通用的Titlebar,并响应特定的按键消息等。

Decor View结构图:

1、DecorView为整个Window界面的最顶层View。

2、DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域。

3、LinearLayout里有两个FrameLayout子元素。

 (20)为标题栏显示界面。只有一个TextView显示应用的名称。也可以自定义标题栏,载入后的自定义标题栏View将加入FrameLayout中。

 (21)为内容栏显示界面。就是setContentView()方法载入的布局界面,加入其中。

4、派发从ViewRoot分发来的key、touch、trackball等外部事件;

5、作为PhoneWindow与ViewRoot之间的桥梁,ViewRoot通过DecorView设置窗口属性。


(9) ViewRoot:

1. ViewRoot负责协调decorview与windowmanager直接绘图、事件处理;

2. 向DecorView分发收到的用户发起的event事件,如按键,触屏,轨迹球等事件;

3. 与WindowManagerService交互,完成整个Activity的GUI的绘制。

注意: ViewRoot只是DecorView的代理来接收WindowManagerService发过来的消息,DecorView才是activity Window的展示内容的平台。(ViewRoot实际是一个HandlerViewRoot建立主ViewWindowsManger通讯的桥梁)。

八、View中常用方法简介
onFinishInflate()

当View和它的所有子对象从XML中导入之后,调用此方法 
onMeasure(int, int)

View会调用此方法,来确认自己及所有子对象的大小 
onLayout(boolean, int, int, int, int,int, int)

当View要为所有子对象分配大小和位置时,调用此方法 
onSizeChanged(int, int, int, int)

 当View大小改变时,调用此方法 

onDraw(Canvas)

当View要绘制它的内容时,调用此方法 (ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的,其包含了多个子view,而子View已经实现了自己的绘制方法)

dispatchDraw()

绘制子视图调用(在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法)

onKeyDown(int,KeyEvent)

当一个新的按键事件发生时,调用此方法 
onKeyUp(int, KeyEvent)

当一个按键释放事件发生时,调用此方法 
onMotionEvent(MotionEvent)

当一个动作事件(如触摸)发生时,调用此方法 
onFocusChanged(boolean, int)

当View获得或失去焦点时,调用此方法 

onAttachedToWindow()

当View附加到一个窗体上时,调用此方法 

onDetachedFromWindow()

当View离开它的窗体时,调用此方法 

onWindowVisibilityChanged(int)

当窗口中包含的可见的view发生变化时触发

computeScroll()

主要功能是计算拖动的位移量、更新背景、设置要显示的屏幕。

 

 

九、常用知识点

1、  Ctrl+shift+R 可以查找该工程中的文件(知道文件名但不知道路径时可以使用)。

2、  Ctrl+O 显示该类中的所有方法。

3、  Alt+ß    返回

3、./mk sp6820gb u adrpac system  当修改某一个system目录下的文件,可以使用此命令打包成一个system.img文件。

4、在ubuntu下面一工程下查找某一个字符串可以使用

Find –name ‘xxx.xxx’ | xargs grep  ‘xxx’ |  grep –v “\.svn/*”

查找xxx.xxx文件中的xxx字符串,不显示带.svn的文件

4、  关于抓log方法 –> 在cmd中使用adb  logcat –v  time 就会显示log


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android的launcher是指安卓系统中的桌面启动器,也是安卓系统中的主要程序组件之一。它负责显示和管理用户的应用程序图标、小部件和壁纸等内容。\[3\]在大部分Android开发中,不需要改变Android的launcher。但是对于一些定制的Android系统,比如放在汽车上的平板,可能需要自己做一个定制的launcher来替代Android原生态的launcher。这样可以根据需求自定义图标的数量和大小,提供更好的用户体验。\[1\]在Android系统中,launcher的主Activity是com.android.launcher2.Launcher,它在Manifest文件中进行了配置。\[2\]如果出现Launcher出错的情况,安卓系统会提示“进程 com.android.launcher 意外停止”,此时需要重新启动Launcher。\[3\] #### 引用[.reference_title] - *1* *3* [Android中的Launcher介绍](https://blog.csdn.net/qq_25314345/article/details/104251318)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Android Launcher 详解](https://blog.csdn.net/huangyabin001/article/details/37523715)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值