Launcher Series Catalogue:
First, android7.x Launcher3 source code parsing (1)-Start process
Second, android7.x Launcher3 source Code Analysis (2)-Frame structure
Iii. android7.x Launcher3 Source code parsing (3)-workspace and AllApps loading process
The first two blogs have carried out some analysis on the Lancher and launcher frame structure respectively. This article. will focus on analyzing the loading process of the interface.
1. Overall process
Let's start with a general flowchart. (image can not be seen to download the next view or right click on the new page to see the picture)
watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvugljyxnzb19m/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/southeast "alt=" here to write a picture descriptive narrative "title=" ">
Start with the Launcher.java OnCreate method.
protected void onCreate(Bundle savedinstancestate) { ......//Establish Launcherappstate objectLauncherappstate.setapplicationcontext (Getapplicationcontext ()); Launcherappstate app = Launcherappstate.getinstance (); ......//Establish Launchermodel objectMmodel = App.setlauncher ( This);//Some other object initialization... setcontentview (r.layout.launcher); Setupviews ();if(!mrestoring) {if(Disable_synchronous_binding_current_page) {//If The user leaves launcher, then we should just load items asynchronously when //They return.Mmodel.startloader (Pagedview.invalid_restore_page); }Else{//We only load the page synchronously if the user rotates (or triggers a //configuration Change) while Launcher are in the foregroundMmodel.startloader (Mworkspace.getrestorepage ()); } } ......}
The focus called the Launchermodel Startloader method, Startloader inside. The most important thing is to start the loadertask.mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage);
We then analyze the Loadertask run method.
Public voidRun () {......Keep_running: {if(debug_loaders)Log.DTAG,"Step 1:loading Workspace"); Loadandbindworkspace ();if(mstopped) {Break keep_running; } waitforidle ();//Second step if(debug_loaders)Log.DTAG,"Step 2:loading all Apps"); Loadandbindallapps (); Waitforidle ();//Third step if(debug_loaders)Log.DTAG,"Step 3:loading Deep Shortcuts"); Loadandbinddeepshortcuts (); }......}
Here are a few steps, loadAndBindWorkspace
–> waitForIdle()
, loadAndBindAllApps()
waitForIdle()
loadAndBindDeepShortcuts()
3 Step loading process inside are interspersed with waitforidle, this method is why?
private void waitForIdle() { ...... synchronized (LoaderTask.this) { final long workspaceWaitTime = DEBUG_LOADERS ?
Systemclock.uptimemillis ():0; Mhandler.postidle (NewRunnable () { Public void Run() {synchronized(Loadertask. This) {mloadandbindstepfinished =true;if(debug_loaders) {LOG.D (TAG,"Done with previous binding step"); } loadertask. This. Notify (); } } }); while(!mstopped &&!mloadandbindstepfinished) {Try{//Just in case mflushingworkerthread changes and we aren ' t woken up, //Wait no longer than 1sec at a time This. Wait ( +); }Catch(Interruptedexception ex) {//Ignore} } ...... } }
The load data is handled in the UI thread, and the UI thread is normally not blocked, otherwise it is possible to generate ANR. This will severely impact the user experience.
All here Loadertask after the result is sent to the UI thread, in order to ensure that the interface binding task can be completed efficiently, it will often suspend its own task, waiting for the UI thread to finish processing.
Analysis of this method:
First of all. Creates a task that the UI thread runs at leisure, which is responsible for setting some key control flags. and add it through the Postidle method to increase the processor's message queue. Once the task has been run. The mloadandbindstepfinished is set to true to control the impending conditional infinite wait. Finally, set a conditional infinite wait, waiting for instructions from the UI thread.
2. Workspace loading Process
As can be seen from the general flowchart, the workspace loading process is mainly divided into loadWorkspace();
bindWorkspace(mPageToBindFirst);
A, Loadworkspace ()
Loadworkspace () The code is too much, here is not all posted out. The main function is to be responsible for reading data from the database tables and translating them into the data structure of the launcher desktop items.
Here are the steps:
1, carry out some pretreatment
2. Load Default values
LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary()
This method of Launcher2 before loadDefaultFavoritesIfNecessary
is loaded into the default layout:
workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, R.xml.default_workspace);
But in Launcher3 , it is loaded in this way:
int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT, "xml", partner.getPackageName());
This place, I have not understood it temporarily. What is the default layout?
3. Initialize data
Empty the previous memory data
/** Clears all the sBg data structures */ privatevoidclearSBgDataStructures() { synchronized (sBgLock) { sBgWorkspaceItems.clear(); sBgAppWidgets.clear(); sBgFolders.clear(); sBgItemsIdMap.clear(); sBgWorkspaceScreens.clear(); } }
4, Query ContentProvider, return the result set of Favorites table
Finalhashmap<string, integer> installingpkgs = Packageinstallercompat. getinstance (mContext). Updat Eandgetactivesessioncache ();FinalArraylist<long> Itemstoremove =NewArraylist<long> ();FinalArraylist<long> restoredrows =NewArraylist<long> ();FinalUri Contenturi = LauncherSettings.Favorites.CONTENT_URI;if(debug_loaders) LOG.D (TAG,"Loading model from"+ Contenturi);FinalCursor C = contentresolver.query (Contenturi,NULL,NULL,NULL,NULL);
5, according to different types, the data is saved to the corresponding ArrayList.
Types include the following:
ITEM_TYPE_APPLICATIONITEM_TYPE_SHORTCUTITEM_TYPE_FOLDERITEM_TYPE_APPWIDGETITEM_TYPE_CUSTOM_APPWIDGET
Save the data to a global variable based on the above types
Sbgitemsidmap,sbgworkspaceitemsm,sbgappwidgets,sbgfolders
Other than that. Assuming the empty directory, empty screen, also delete, finally, all the screen loaded into the global variable Sbgworkspacescreens.
......//Remove any empty folder for(LongFolderId:LauncherAppState.getLauncherProvider (). Deleteemptyfolders ()) { Sbgworkspaceitems.remove (Sbgfolders.get (FolderID)); Sbgfolders.remove (FolderID); Sbgitemsidmap.remove (FolderID); } ... sbgworkspacescreens.addall (Loadworkspacescreensdb (Mcontext));//Remove any empty screensArraylist<long> Unusedscreens =NewArraylist<long> (Sbgworkspacescreens); for(ItemInfo Item:sbgitemsidmap) {LongScreenid = Item.screenid;if(Item.container = = LauncherSettings.Favorites.CONTAINER_DESKTOP && Unusedscreens.contai NS (Screenid)) {unusedscreens.remove (Screenid); } }//If There is any empty screens remove them, and update. if(Unusedscreens.size ()! =0) {Sbgworkspacescreens.removeall (unusedscreens); Updateworkspacescreenorder (context, sbgworkspacescreens); }
B, Bindworkspace
The function of Bindworkspace is to display the data obtained above by launcher.
Steps:
1. Copy the data first:
synchronized (sBgLock) { workspaceItems.addAll(sBgWorkspaceItems); appWidgets.addAll(sBgAppWidgets); orderedScreenIds.addAll(sBgWorkspaceScreens); folders = sBgFolders.clone(); itemsIdMap = sBgItemsIdMap.clone(); }
2. Loading data and sorting
//装载桌面项数据 filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems, otherWorkspaceItems); //装载widget filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets, otherAppWidgets); //装载目录 filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders, otherFolders); //排序 sortWorkspaceItemsSpatially(currentWorkspaceItems); sortWorkspaceItemsSpatially(otherWorkspaceItems);
3. Start binding
watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvugljyxnzb19m/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/southeast "alt=" here to write a picture descriptive narrative "title=" ">
Just the last flowchart.
3. Loading of application Apps
The main process for loading apps. The top of the flowchart has been given, assuming that all the app is not loaded, then loadAllApps();
, or directlyonlyBindAllApps();
1, Loadallapps ()
According to the code, draw the next flowchart, but I am not clear userprofile is a what ghost?
2, Onlybindallapps ()
The function here is much simpler than binding workspace, and notifies launcher binding directly
Runnable r =NewRunnable () { Public void Run() {Final Longt = Systemclock.uptimemillis ();FinalCallbacks callbacks = Trygetcallbacks (oldcallbacks);if(Callbacks! =NULL) {callbacks.bindallapplications (list); Callbacks.bindallpackages (widgetlist); }if(debug_loaders) {LOG.D (TAG,"Bound All"+ list.size () +"Apps from the cache in"+ (Systemclock.uptimemillis ()-T) +"MS"); } } };
Take a look at the launcher bindAllApplications
function. Of course this function is also in the Loadallapps function. is how to bind the data to display it?
The Launcher.java bindAllApplications
function will set the data to Allappscontainerview.
ifnull) { mAppsView.setApps(apps); }
And then with the code to Allappscontainerview.
publicvoidsetApps(List<AppInfo> apps) { mApps.setApps(apps); }
Where does the apps work? The obvious is the onfinishinflate () function,
..... // Load the all apps recycler view mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view); mAppsRecyclerView.setApps(mApps); mAppsRecyclerView.setLayoutManager(mLayoutManager); mAppsRecyclerView.setAdapter(mAdapter); mAppsRecyclerView.setHasFixedSize(true);.....
Set to Recyclerview. Obviously, Launcher's application interface is a recyclerview of its own definition, and the adpter for this recyclerview binding is allappsgridadapter. Take a look at this adpter onCreateViewHolder
function, which is very obvious. Different layouts are loaded depending on the type (application interface has apps and directories. There is also a search box on the head. With Recyclerview This feature is the easiest to implement), about how Recyclerview can be loaded according to different types of layouts, can take a look at the blog I wrote a long time ago Recyclerview different position loaded into different view implementations.
Well, Launcher3 's workspace and application apps are in the process of loading this, and then we'll do a detailed analysis of the contents of launcher.
android7.x Launcher3 Source code Resolution (3)---workspace and allapps loading process