[TOC]
单例模式 定义 确保某个类中只有一个实例,而且子性实例化并向整个系统提供整个实例
例子 饿汉: 1 2 3 4 5 6 7 8 9 public class Singleton { private static final Singleton instance = new Singleton (); private Singleton () {} public static Singleton getInstance () { return instance; } }
懒汉: 1 2 3 4 5 6 7 8 9 10 11 public class Singleton { private static Singleton instance; private Singleton () {} public static synchronized Singleton getInstance () { if (instance == null ) { instance = new Singleton (); } return instance; }
双重校验锁(DCL): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Singleton { private static volatile Singleton instance; private Singleton () { } public static Singleton getInstance () { if (instance == null ) { synchronized (Singleton.class){ if (instance == null ){ instance = new Singleton (); } } } return instance; } }
双重判断的原因?
第一个判断减少锁的使用,提升性能
多个线程同时等待锁,当第一个创建后,就不需要其他线程重复重建
volatile的理解
禁止重排序导致instance获取失败。
给Singleton的实例分配内存
调用构造函数,初始化成员
将instance对象指向分配的内存空间
执行顺序有可能是1-2-3,1-3-2
如果是1-3-2,new Singleton()方法执行时可能导致分配了空间,并指向了内存空间,但是没有赋值,这样另一个线程拿到后会导致出错
缺点:部分情况下,这种单例模式会失效
静态内部类: 1 2 3 4 5 6 7 8 9 10 11 12 public class Singleton { private Singleton () { } public static Singleton getInstance () { return SingletonHolder.instance; } private static class SingletonHolder { private static final Singleton instance = new Singleton (); } }
首次加载Singleton不会初始化instance,当调用getInstance方法时,初始化SingletonHolder类,这样虚拟机加载该类是线程安全的,保证单例对象的唯一性
枚举单例 1 2 3 4 5 6 public enum SingletonEnum { INSTANCE; public void doSomething () { ...... } }
注意:在反序列化时,会重新创建对象,不符合单例
容器单例 1 2 3 4 5 6 7 8 9 10 11 12 public class SingletonManager { private static Map<String,Object> objMap = new HashMap <>(); private SingletonManager () {} public static void registerService (String key,Object instance) { if (!objMap.containsKey(key)){ objMap.put(key,instance); } } public static Object getValue (String key) { return objMap.get(Key); } }
对单例内容统一管理,放置在map中,但是HashMap线程不安全,所以最好使用ConcurrentHashMap,管理多个单例类
源码应用
LayoutInflater.from(context)
进入main函数
新建ActivityThread,调用attach函数
AMS通信最终调用ahndlelauncherActivity
创建Activity
创建Application
获取Context对象
将context对象attach到activity中
调用Activity的onCreate方法
在虚拟机第一次加载ContextImpl时会注册LayoutInflater Service,将这些服务存储在HashMap中,下次直接从缓存中读取,应用的是容器单例形式。
深入LayoutInflater LayoutInflater是抽象类,具体实现类是PhoneLayoutInflater
inflate方法:
解析xml根标签(父布局)
判断merge,如果是merge直接将子布局添加到根布局
如果是普通标签,调用createViewFromTag对该元素进行解析
解析所有子view,将这些子view都添加到根布局temp下
返回解析到根视图
q:为什么自定义view要使用全包名,而内置view(TextView)就不用?
a:因为在布局加载过程中,如果是内置view,直接执行onCreateView方法创建view,并将“android.widget.”加在内置view前(android.widget.TextView),然后执行createView方法。如果是自定义view,从xml中获取全量包名直接执行createView方法即可,默认前缀为null
inflate通过深度优先 遍历来构造视图树
优缺点 优点:
减少内存开支,避免创建和销毁的性能损耗
减少性能开销,永久驻留内存方式初始化复杂对象和依赖
避免对同一资源的多重占用,例如-个写文件操作,只有一个实例可以写,避免对这一个资源文件的同时写操作(避免线程不安全)
设置全局访问点,优化和共享资源访问,便于管理
缺点:
拓展困难,只能修改代码
如果持有context对象,会造成内存泄漏
建造者模式 例子 将一个复杂对象的构建与他的表示分离,是的同样的构建过程可以创建不同的表示
核心思想是添加建造者构建主类,减少主类功能,建造者只负责构建主类
简单例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 public class Computer { String display; String cpu; String mainBoard; String gpu; public Computer (Builder builder) { this .display = builder.display; this .cpu = builder.cpu; this .mainBoard = builder.mainBoard; this .gpu = builder.gpu; } @Override public String toString () { return "显示器是" + display + "\ncpu是" + cpu + "\n主板是" + mainBoard + "\n显卡是" + gpu; } static class Builder { String display; String cpu; String mainBoard; String gpu; public Builder () { this .display = "三星曲屏" ; this .cpu = "i5 8400" ; this .mainBoard = "华硕Z360-B" ; this .gpu = "GTX 1050Ti" ; } public Builder setDisplay (String display) { this .display = display; return this ; } public Builder setcpu (String cpu) { this .cpu = cpu; return this ; } public Builder setMainBoard (String mainBoard) { this .mainBoard = mainBoard; return this ; } public Builder setGpu (String gpu) { this .gpu = gpu; return this ; } public Computer build () { return new Computer (this ); } } public static void main (String args[]) { Computer computer = new Computer .Builder() .setcpu("i9 4700u" ) .setGpu("GTX 2060Ti" ) .setMainBoard("华硕Z480" ) .build(); System.out.println(computer.toString()); } }
源码应用
AlertDialog 内部调用Buidler模式构建,最终通过WindowManager显示在手机屏幕上。
WindowManager源码分析 所有需要显示到屏幕上的内容都是通过WindowManager来操作的,WM的一个非常重要的子系统为WMS(WindowManagerService) 在android.app.SystemServiceRegistry中:
1 2 3 4 5 6 registerService(Context.WINDOW_SERVICE, WindowManager.class, new CachedServiceFetcher <WindowManager>() { @Override public WindowManager createService (ContextImpl ctx) { return new WindowManagerImpl (ctx); }});
WMS也是初始化的众多服务的一种,所以在ContentImpl中初始化,并将初始化的服务注册到一个map中,需要时通过键获取调用,属于单例模式的容器单例。
以PopupWindow为例,我们获取到popupWindow的初始化:
1 mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
通过以上方法获取WM,显示时使用showAtLocation()方法,
1 2 3 4 5 6 7 8 9 10 11 public void showAtLocation (IBinder token, int gravity, int x, int y) { ...... invokePopup(p); } private void invokePopup (WindowManager.LayoutParams p) { ...... mWindowManager.addView(decorView, p); ...... }
通过一系列的调用,最终使用WM的addView方法添加布局,回溯之前的分析WM的实例是WindowManagerImpl,进入addView方法
1 2 3 4 5 @Override public void addView (@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); }
而在WMImpl方法中调用WMGlobal.addView方法,进入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void addView (View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { ...... ViewRootImpl root; View panelParentView = null ; ...... root = new ViewRootImpl (view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); try { root.setView(view, wparams, panelParentView); } catch (RuntimeException e) { if (index >= 0 ) { removeViewLocked(index, true ); } throw e; } }
构建ViewRootImpl
将布局参数设置给view
存储ViewRootImpl、View、LayoutParam到列表
调用ViewRootImpl.setView将view显示在窗口
进一步查看ViewRootImpl是什么?
1 2 3 4 5 6 7 8 9 public ViewRootImpl (Context context, Display display) { mContext = context; mWindowSession = WindowManagerGlobal.getWindowSession(); ...... mThread = Thread.currentThread(); ...... }
进入WMGlobal.getWindowSession方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static IWindowSession getWindowSession () { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null ) { try { InputMethodManager imm = InputMethodManager.getInstance(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( new IWindowSessionCallback .Stub() { @Override public void onAnimatorScaleChanged (float scale) { ValueAnimator.setDurationScale(scale); } }, imm.getClient(), imm.getInputContext()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowSession; } }
进入getWindowManagerService,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static IWindowManager getWindowManagerService () { synchronized (WindowManagerGlobal.class) { if (sWindowManagerService == null ) { sWindowManagerService = IWindowManager.Stub.asInterface( ServiceManager.getService("window" )); try { if (sWindowManagerService != null ) { ValueAnimator.setDurationScale( sWindowManagerService.getCurrentAnimatorScale()); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowManagerService; } }
通过ServiceManager.getService()获取WMS,
1 2 3 4 5 6 7 8 9 10 11 12 13 public static IBinder getService (String name) { try { IBinder service = sCache.get(name); if (service != null ) { return service; } else { return Binder.allowBlocking(getIServiceManager().getService(name)); } } catch (RemoteException e) { Log.e(TAG, "error in getService" , e); } return null ; }
通过sCache获取到一个IBinder对象,所以FrameWork与WMS之间也是通过Binder机制进行通信的,回溯到之前,会调用IWindowManager.Stub.asInterface(),将IBinder对象转化为WM对象,然后通过openSession与WMS建立通信绘画,之后通过这个session进行交换信息,但是到现在还是没有显示view,所以继续走ViewRootImpl.setView方法,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public void setView (View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this ) { if (mView == null ) { ...... requestLayout(); ...... try { res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mInputChannel); } } }
requestlayout:请求布局
向WMS请求显示布局
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Override public void requestLayout () { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true ; scheduleTraversals(); } } void scheduleTraversals () { if (!mTraversalScheduled) { mTraversalScheduled = true ; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null ); if (!mUnbufferedInputDispatch) { scheduleConsumeBatchedInput(); } notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); } }
通过handler回调执行MTraversalRunnable,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 final class TraversalRunnable implements Runnable { @Override public void run () { doTraversal(); } } void doTraversal () { if (mTraversalScheduled) { mTraversalScheduled = false ; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); if (mProfile) { Debug.startMethodTracing("ViewAncestor" ); } performTraversals(); if (mProfile) { Debug.stopMethodTracing(); mProfile = false ; } } }
最终进入performTraversals进行具体操作
获取Surface对象,用于图形绘制
performMeasure函数,测量整个视图树各个view的大小
performLayout,布局整个view
performDraw,绘制整个view
优缺点 优点:
良好的封装性,使客户端不知道产品内部组成细节
独立,容易拓展
缺点:
产生多余Builder对象和Director对象,消耗内存
原型模式 定义 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象
简单例子 深拷贝和浅拷贝 原型模式实际上是浅拷贝,也称为影子拷贝。拷贝实际不是将所有字段重新构造一份,而是拷贝文档的字段引用原始文档的字段而已,所以会导致修改副本的字段,原始字段也会跟着修改,因为最终修改的是同一个内存单元,所以在原型模式中,要尽量使用深拷贝。
源码分析
ArrayList的clone方法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 public Object clone () { try { ArrayList<?> v = (ArrayList<?>) super .clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0 ; return v; } catch (CloneNotSupportedException e) { throw new InternalError (e); } }
克隆自身后,在克隆数组对象,并没有对size进行克隆是因为size是值类型,并不是引用类型。
Intent的clone方法分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @Override public Object clone () { return new Intent (this ); } public Intent (Intent o) { this (o, COPY_MODE_ALL); } private Intent (Intent o, @CopyMode int copyMode) { this .mAction = o.mAction; this .mData = o.mData; this .mType = o.mType; this .mPackage = o.mPackage; this .mComponent = o.mComponent; if (o.mCategories != null ) { this .mCategories = new ArraySet <>(o.mCategories); } if (copyMode != COPY_MODE_FILTER) { this .mFlags = o.mFlags; this .mContentUserHint = o.mContentUserHint; this .mLaunchToken = o.mLaunchToken; if (o.mSourceBounds != null ) { this .mSourceBounds = new Rect (o.mSourceBounds); } if (o.mSelector != null ) { this .mSelector = new Intent (o.mSelector); } if (copyMode != COPY_MODE_HISTORY) { if (o.mExtras != null ) { this .mExtras = new Bundle (o.mExtras); } if (o.mClipData != null ) { this .mClipData = new ClipData (o.mClipData); } } else { if (o.mExtras != null && !o.mExtras.maybeIsEmpty()) { this .mExtras = Bundle.STRIPPED; } } } }
在Intent的clone方法中直接使用new方法构建了新intent
所以延伸出一个问题,new和clone怎么选择?
如果对象的构造成本太高或者构造比较麻烦,那么使用clone函数效率高,否则使用new
intent的查找和匹配
intent是怎么查找对应的组件然后跳转的呢?
在ContextImpl初始化的SystemServiceRegistry中初始化各种服务(WMS,AMS等),其中,初始化了PMS(PackageManagerService)
在ContextImpl中执行getPackageManager方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Override public PackageManager getPackageManager () { if (mPackageManager != null ) { return mPackageManager; } IPackageManager pm = ActivityThread.getPackageManager(); if (pm != null ) { return (mPackageManager = new ApplicationPackageManager (this , pm)); } return null ; }
进入ActivityThread.getPackageManager()
1 2 3 4 5 6 7 8 9 10 11 12 public static IPackageManager getPackageManager () { if (sPackageManager != null ) { return sPackageManager; } IBinder b = ServiceManager.getService("package" ); sPackageManager = IPackageManager.Stub.asInterface(b); return sPackageManager; }
获取到PackageManagerService服务,这个服务是在系统初始化时通过SystemServer启动的,现在只是获取,查看PackageManagerService类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 public class PackageManagerService extends IPackageManager .Stub implements PackageSender { public PackageManagerService (Context context, Installer installer,boolean factoryTest, boolean onlyCore) { final File privilegedAppDir = new File (Environment.getRootDirectory(), "priv-app" ); scanDirTracedLI(privilegedAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRIVILEGED, 0 ); final File systemAppDir = new File (Environment.getRootDirectory(), "app" ); scanDirTracedLI(systemAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM, 0 ); File privilegedVendorAppDir = new File (Environment.getVendorDirectory(), "priv-app" ); try { privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile(); } catch (IOException e) { } scanDirTracedLI(privilegedVendorAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR | SCAN_AS_PRIVILEGED, 0 ); File vendorAppDir = new File (Environment.getVendorDirectory(), "app" ); try { vendorAppDir = vendorAppDir.getCanonicalFile(); } catch (IOException e) { } scanDirTracedLI(vendorAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR, 0 ); File privilegedOdmAppDir = new File (Environment.getOdmDirectory(), "priv-app" ); try { privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile(); } catch (IOException e) { } scanDirTracedLI(privilegedOdmAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR | SCAN_AS_PRIVILEGED, 0 ); File odmAppDir = new File (Environment.getOdmDirectory(), "app" ); try { odmAppDir = odmAppDir.getCanonicalFile(); } catch (IOException e) { } scanDirTracedLI(odmAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR, 0 ); final File oemAppDir = new File (Environment.getOemDirectory(), "app" ); scanDirTracedLI(oemAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_OEM, 0 ); File privilegedProductAppDir = new File (Environment.getProductDirectory(), "priv-app" ); try { privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile(); } catch (IOException e) { } scanDirTracedLI(privilegedProductAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRODUCT | SCAN_AS_PRIVILEGED, 0 ); File productAppDir = new File (Environment.getProductDirectory(), "app" ); try { productAppDir = productAppDir.getCanonicalFile(); } catch (IOException e) { } scanDirTracedLI(productAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRODUCT, 0 ); } }
PMS会加载一系列,在不同目录下的包执行scanDirTracedLI方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 private void scanDirTracedLI (File dir, final int parseFlags, int scanFlags, long currentTime) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + dir.getAbsolutePath() + "]" ); try { scanDirLI(dir, parseFlags, scanFlags, currentTime); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } private void scanDirLI (File dir, int parseFlags, int scanFlags, long currentTime) { final File[] files = dir.listFiles(); ...... for (File file : files) { final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); if (!isPackage) { continue ; } parallelPackageParser.submit(file, parseFlags); fileCount++; } ...... for (; fileCount > 0 ; fileCount--) { scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags, currentTime, null ); } ...... } }
扫描目录下的子目录,对apk文件进行解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public void submit (File scanFile, int parseFlags) { mService.submit(() -> { ParseResult pr = new ParseResult (); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]" ); try { PackageParser pp = new PackageParser (); pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); pp.setDisplayMetrics(mMetrics); pp.setCacheDir(mCacheDir); pp.setCallback(mPackageParserCallback); pr.scanFile = scanFile; pr.pkg = parsePackage(pp, scanFile, parseFlags); } catch (Throwable e) { pr.throwable = e; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } try { mQueue.put(pr); } catch (InterruptedException e) { Thread.currentThread().interrupt(); mInterruptedInThread = Thread.currentThread().getName(); } }); } @VisibleForTesting protected PackageParser.Package parsePackage (PackageParser packageParser, File scanFile, int parseFlags) throws PackageParser.PackageParserException { return packageParser.parsePackage(scanFile, parseFlags, true ); }
创建一个PackageParser,调用parsePackage函数解析apk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public Package parsePackage (File packageFile, int flags, boolean useCaches) throws PackageParserException { Package parsed = useCaches ? getCachedResult(packageFile, flags) : null ; if (parsed != null ) { return parsed; } if (packageFile.isDirectory()) { parsed = parseClusterPackage(packageFile, flags); } else { parsed = parseMonolithicPackage(packageFile, flags); } cacheResult(packageFile, flags, parsed); return parsed; }
如果是文件夹类型,加载多个apk文件,如果是单个apk,只加载一个apk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Deprecated public Package parseMonolithicPackage (File apkFile, int flags) throws PackageParserException { final AssetManager assets = newConfiguredAssetManager(); final PackageLite lite = parseMonolithicPackageLite(apkFile, flags); if (mOnlyCoreApps) { if (!lite.coreApp) { throw new PackageParserException (INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Not a coreApp: " + apkFile); } } try { final Package pkg = parseBaseApk(apkFile, assets, flags); pkg.setCodePath(apkFile.getAbsolutePath()); pkg.setUse32bitAbi(lite.use32bitAbi); return pkg; } finally { IoUtils.closeQuietly(assets); } }
进入parseBaseApk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 private Package parseBaseApk (File apkFile, AssetManager assets, int flags) throws PackageParserException { final String apkPath = apkFile.getAbsolutePath(); String volumeUuid = null ; if (apkPath.startsWith(MNT_EXPAND)) { final int end = apkPath.indexOf('/' , MNT_EXPAND.length()); volumeUuid = apkPath.substring(MNT_EXPAND.length(), end); } mParseError = PackageManager.INSTALL_SUCCEEDED; mArchiveSourcePath = apkFile.getAbsolutePath(); if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath); final int cookie = loadApkIntoAssetManager(assets, apkPath, flags); Resources res = null ; XmlResourceParser parser = null ; try { res = new Resources (assets, mMetrics, null ); parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); final String[] outError = new String [1 ]; final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError); if (pkg == null ) { throw new PackageParserException (mParseError, apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0 ]); } pkg.setVolumeUuid(volumeUuid); pkg.setApplicationVolumeUuid(volumeUuid); pkg.setBaseCodePath(apkPath); pkg.setSignatures(null ); return pkg; ...... }
获取apk路径,解析apk资源文件及AndroidManifest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 private boolean parseBaseApkChild (Package parentPkg, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { Package childPkg = new Package (childPackageName); childPkg.mVersionCode = parentPkg.mVersionCode; childPkg.baseRevisionCode = parentPkg.baseRevisionCode; childPkg.mVersionName = parentPkg.mVersionName; childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion; childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion; childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError); if (childPkg == null ) { return false ; } if (parentPkg.childPackages == null ) { parentPkg.childPackages = new ArrayList <>(); } parentPkg.childPackages.add(childPkg); childPkg.parentPackage = parentPkg; return true ; }
创建package对象,将版本信息存储进来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private Package parseBaseApkCommon (Package pkg, Set<String> acceptedTags, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { ....... int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { ...... if (tagName.equals(TAG_APPLICATION)) { ...... if (!parseBaseApplication(pkg, res, parser, flags, outError)) { return null ; } } else if (tagName.equals(TAG_PERMISSION)) { if (!parsePermission(pkg, res, parser, outError)) { return null ; } } return pkg; }
获取AndroidManifest的深度,然后深度遍历获取所有的标签并依次处理,这里以Application为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 private boolean parseBaseApplication (Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { final ApplicationInfo ai = owner.applicationInfo; final String pkgName = owner.applicationInfo.packageName; TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestApplication); ...... String manageSpaceActivity = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, Configuration.NATIVE_CONFIG_VERSION); ...... boolean allowBackup = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true ); ai.theme = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_theme, 0 ); ai.descriptionRes = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_description, 0 ); ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, str, outError); final int innerDepth = parser.getDepth(); int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue ; } String tagName = parser.getName(); if (tagName.equals("activity" )) { Activity a = parseActivity(owner, res, parser, flags, outError, false , owner.baseHardwareAccelerated); if (a == null ) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false ; } owner.activities.add(a); } else if (tagName.equals("receiver" )) { Activity a = parseActivity(owner, res, parser, flags, outError, true , false ); if (a == null ) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false ; } owner.receivers.add(a); } } return true ; }
解析Application的其他属性及其子标签,而后返回方法直到scanDirLI方法,执行scanPackageLI函数
scanPackageLI—>scanPackageInternalLI—>scanPackageLI—>scanPackageDirtyLI—>commitPackageSettings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private void commitPackageSettings (PackageParser.Package pkg, PackageSetting pkgSetting, UserHandle user, int scanFlags, boolean chatty) throws PackageManagerException { ...... N = pkg.activities.size(); r = null ; for (i=0 ; i<N; i++) { PackageParser.Activity a = pkg.activities.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName); mActivities.addActivity(a, "activity" ); if (chatty) { if (r == null ) { r = new StringBuilder (256 ); } else { r.append(' ' ); } r.append(a.info.name); } } ...... }
将解析的标签,例activity记载到PMS的缓存中。至此,apk的所有信息就被存储在系统中,当使用intent跳转时会在该信息表中进行查找,然后跳转。
我们使用intent时,一般是这样:
1 2 Intent intent = new Intent (this ,MainActivity.class);this .startActivity(intent);
跟踪源码,最终跳转到startActivityForResult:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public void startActivityForResult (@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null ) { options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this , mMainThread.getApplicationThread(), mToken, this , intent, requestCode, options); if (ar != null ) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0 ) { mStartedActivity = true ; } cancelInputsAndStartExitTransition(options); } else { if (options != null ) { mParent.startActivityFromChild(this , intent, requestCode, options); } else { mParent.startActivityFromChild(this , intent, requestCode); } } }
通过instrumentation启动Activity,并向主线程发送启动请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public ActivityResult execStartActivity ( Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; ...... try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target, requestCode, 0 , null , options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException ("Failure from system" , e); } return null ; }
进入AMS方法,调用
startActivityAsUser—>ActivityStarter.startActivityMayWait—>ActivityStackSupervisor.resolveIntent—>AMS.getPackageManagerInternalLocked—>PMS.resolveIntent—>PMS.resolveIntentInternal—>PMS.queryIntentActivitiesInternal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 private @NonNull List<ResolveInfo> queryIntentActivitiesInternal (Intent intent, String resolvedType, int flags, int filterCallingUid, int userId, boolean resolveForStart) { ...... final String pkgName = intent.getPackage(); ComponentName comp = intent.getComponent(); if (comp != null ) { final List<ResolveInfo> list = new ArrayList <ResolveInfo>(1 ); final ActivityInfo ai = getActivityInfo(comp, flags, userId); ...... } ...... synchronized (mPackages) { if (pkgName == null ) { List<CrossProfileIntentFilter> matchingFilters = getMatchingCrossProfileIntentFilters(intent, resolvedType, userId); ResolveInfo xpResolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent, resolvedType, flags, userId); if (xpResolveInfo != null ) { List<ResolveInfo> xpResult = new ArrayList <ResolveInfo>(1 ); xpResult.add(xpResolveInfo); return applyPostResolutionFilter( filterIfNotSystemUser(xpResult, userId), instantAppPkgName); } } else { final PackageParser.Package pkg = mPackages.get(pkgName); result = null ; if (pkg != null ) { result = filterIfNotSystemUser( mActivities.queryIntentForPackage( intent, resolvedType, flags, pkg.activities, userId), userId); } ...... }
如果intent指明了Component(即MainActivity),直接获取到ActivityInfo并且数量只有一个,直接返回。如果Component为空,会检测发起方所在的包名,如果有包名,通过包名获取ActivityInfo,反之,根据其他信息比如外部拉起,action,Category等判断。
总结:在系统启动时,PMS启动分析所有apk的信息,创建一个信息表,当用胡使用Intent跳转时,会根据intent中包含的信息到PMS的信息表查找,最后跳转到目标组件
优缺点 优点:
内存中二进制流的拷贝,其比直接new一个对象性能会好很多 缺点:
直接在内存中拷贝,不会执行构造函数,使用过程中对比new和clone方法的区别
原型模式就是要实现深拷贝
工厂模式 定义 用于创建对象的接口,让子类决定实例化那个类,解决对象之间的解耦
例子 简单工厂 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public abstract class Product { public abstract void method () ; } public class ProductA extends Product { @Override public void method () { System.out.println("制造ProductA" ); } } public class ProductB extends Product { @Override public void method () { System.out.println("制造ProductB" ); } } public class Factory { public Product create (String type) { if ("A" .equals(type)){ return new ProductA (); }else if ("B" .equals(type)){ return new ProductB (); }else { return null ; } } } public static void main (String args[]) { Factory factory = new Factory (); Product a = factory.create("A" ); a.method(); Product b = factory.create("B" ); b.method(); }
运行后:
制造ProductA
制造ProductB
工厂方法抽象 产品类不变,工厂变为抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public abstract class Factory { public abstract Product create () ; } public class FactoryA extends Factory { @Override public Product create () { return new ProductA (); } } public class FactoryB extends Factory { @Override public Product create () { return new ProductB (); } } public static void main (String args[]) { FactoryA factoryA = new FactoryA (); FactoryB factoryB = new FactoryB (); factoryA.create().method(); factoryB.create().method(); }
运行后:
制造ProductA
制造ProductB
抽象工厂 需要多个产品最终组成为一个产品
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 public abstract class Cpu { public abstract void method () ; } public class CpuA extends Cpu { @Override public void method () { System.out.println("A型号CPU" ); } } public class CpuB extends Cpu { @Override public void method () { System.out.println("B型号CPU" ); } } public abstract class Display { public abstract void method () ; } public class DisplayA extends Display { @Override public void method () { System.out.println("A型号显示屏" ); } } public class DisplayB extends Display { @Override public void method () { System.out.println("B型号显示屏" ); } } public abstract class Factory { public abstract Cpu createCpu () ; public abstract Display createDisplay () ; } public class FactoryA extends Factory { @Override public Cpu createCpu () { return new CpuA (); } @Override public Display createDisplay () { return new DisplayA (); } } public class FactoryB extends Factory { @Override public Cpu createCpu () { return new CpuB (); } @Override public Display createDisplay () { return new DisplayB (); } } public static void main (String args[]) { FactoryA factoryA = new FactoryA (); FactoryB factoryB = new FactoryB (); factoryA.createCpu().method(); factoryA.createDisplay().method(); factoryB.createCpu().method(); factoryB.createDisplay().method(); }
执行结果如下:
A型号CPU
A型号显示屏
B型号CPU
B型号显示屏
抽象工厂的核心是复杂的工厂模式。存在多个工厂,多种产品类型,就会使用抽象工厂,在android源码中使用较少,并没有那么多产品种类,大部分使用简单工厂或者工厂方法就可以解决。
源码分析
ArrayList和HashSet都继承自Collection接口,collection接口继承自Iterator接口。
xxxActivity都继承自Activity,其onCreate方法就是工厂方法,两个Activity构建不同的view,可以将view看成product,Activity为Factory。
xxService都继承自Service,其onBind方法也可以看作是一个工厂方法
优缺点 优点:
缺点:
抽象工厂的优点:
分离接口与实现,使用方不知道具体的实现是什么,同时使抽象该工厂方法模式在切换产品类时更加灵活,容易
抽象工厂的缺点:
策略模式 定义 定义一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,策略模式让算法独立于使用他们的客户而独立存在,解决if-else滥用的问题
例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class CalculatePrice { public enum TransPortType { BUS, SUBWAY } private void calculateBus (int km) { System.out.println("公交车" + km + "公里的车票" ); } private void calculateSubWay (int km) { System.out.println("地铁" + km + "公里的车票" ); } private void calculate (int km, TransPortType transPortType) { switch (transPortType) { case BUS: calculateBus(km); break ; case SUBWAY: calculateSubWay(km); break ; default : break ; } } public static void main (String args[]) { CalculatePrice calculatePrice = new CalculatePrice (); calculatePrice.calculate(16 ,TransPortType.BUS); calculatePrice.calculate(15 ,TransPortType.SUBWAY); } }
结果: 公交车16公里的车票
地铁15公里的车票
当需要拓展时,比如多了一个出租车,需要这样做
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public class CalculatePrice { public enum TransPortType { BUS, SUBWAY, TAXI } private void calculateBus (int km) { System.out.println("公交车" + km + "公里的车票" ); } private void calculateSubWay (int km) { System.out.println("地铁" + km + "公里的车票" ); } private void calculateTaxi (int km) { System.out.println("出租车" + km + "公里的车票" ); } private void calculate (int km, TransPortType transPortType) { switch (transPortType) { case BUS: calculateBus(km); break ; case SUBWAY: calculateSubWay(km); break ; case TAXI: calculateTaxi(km); break ; default : break ; } } public static void main (String args[]) { CalculatePrice calculatePrice = new CalculatePrice (); calculatePrice.calculate(16 ,TransPortType.BUS); calculatePrice.calculate(15 ,TransPortType.SUBWAY); calculatePrice.calculate(17 ,TransPortType.TAXI); } }
结果:
公交车16公里的车票
地铁15公里的车票
出租车17公里的车票
改动还是比较大的,对源代码的基础上做了更改,并且添加了if-else判断taxi类型。 如果把他改成策略模式,试试效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public abstract class CalculateStrategy { public abstract void getPrice (int km) ; } public class BusCalculateStrategy extends CalculateStrategy { @Override public void getPrice (int km) { System.out.println("公交车" + km + "公里的车票" ); } } public class SubWayCalculateStrategy extends CalculateStrategy { @Override public void getPrice (int km) { System.out.println("地铁" + km + "公里的车票" ); } } public static void main (String args[]) { CalculateStrategy calculateStrategy = new BusCalculateStrategy (); calculateStrategy.getPrice(16 ); CalculateStrategy calculateStrategy1 = new SubWayCalculateStrategy (); calculateStrategy1.getPrice(15 ); }
结果:
公交车16公里的车票
地铁15公里的车票
当需要拓展出租车时
1 2 3 4 5 6 7 8 9 10 11 public class TaxiCalculateStrategy extends CalculateStrategy { @Override public void getPrice (int km) { System.out.println("出租车" + km + "公里的车票" ); } } public static void main (String args[]) { CalculateStrategy calculateStrategy2 = new TaxiCalculateStrategy (); calculateStrategy2.getPrice(17 ); }
只需要添加Taxi类继承自策略类,执行具体车费计算方法,在main中调用即可,这样对代码的侵入性最小,不用修改原有逻辑代码,在咋付逻辑出引用效果优秀
状态模式 定义 当一个对象的内在行为改变时,允许改变其行为,整个对象看起来像是改变了其类
源码解析
wifi状态管理
责任链模式 定义 使多个对象都有机会处理请求,这些对象形成一条链,依次执行,直到结束。
源码解析
view的事件传递
观察者模式 定义 定义对象间一种一对多的一栏关系,使得每当一个对象改变状态,则所有依赖与他的对象都会得到通知并被自动更新
例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public class Mode2 { static public interface IObserver { void update (int temp) ; } static public interface IObservable { void register (IObserver iObserver) ; void unregister (IObserver iObserver) ; void notifyObserver () ; } static class Observable implements IObservable { private ArrayList<IObserver> list = new ArrayList <>(); private int temp; @Override public void register (IObserver iObserver) { list.add(iObserver); } @Override public void unregister (IObserver iObserver) { list.remove(iObserver); } @Override public void notifyObserver () { for (int i = 0 ; i < list.size(); i++) { list.get(i).update(temp); } } public void setTemp (int temp) { this .temp = temp; } } static class Observer1 implements IObserver { @Override public void update (int temp) { System.out.println("Observable1更新为 = " + temp); } } static class Observer2 implements IObserver { @Override public void update (int temp) { System.out.println("Observable2更新为 = " + temp); } } public static void main (String args[]) { Observable observable = new Observable (); Observer1 observer1 = new Observer1 (); Observer2 observer2 = new Observer2 (); observable.register(observer1); observable.register(observer2); observable.setTemp(32131232 ); observable.notifyObserver(); } }