Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

草稿 #1

Merged
merged 8 commits into from
Nov 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@

这是一份Android进阶计划。主要是学习和总结一些Android项目中会用到的一些关键技术,分析一些著名开源框架的源码。希望对他们的整理来带动我对Android各方面的深入研究。对于每一个技术点,我都希望我自己都可以入木三分而不是浅尝辄止
这是一份Android进阶计划。主要是学习和总结一些Android项目中会用到的一些关键技术,分析一些著名开源框架的源码。希望通过对他们的整理和学习来带动我对Android各方面的深入研究。对于每一个技术点,我都希望我自己都可以仔细研究而不是浅尝辄止

项目相关技术点索引如下:


|技术点| |简介|
|:----|:-----|:-----|
|Router|<a href="router/README.md">详情</a>|主要分析了WMRouter和ARouter两款开源框架|
|Router|<a href="router/README.md">详情</a>|主要分析了WMRouter和ARouter两款开源框架的工作原理|
|Gradle插件、代码注入|<a href="gradle插件与字节码注入/README.md">详情</a>|Gradle插件与代码生成等|
|屏幕适配|<a href="屏幕适配/README.md">详情</a>|屏幕适配相关原理及知识|
|插件化|<a href="插件化/README.md">详情</a>|分析VirtualApk和Replugin等开源框架,透过他们了解Android底层组件的运行机制|
|Fresco|ing|主要分析Fresco框架的设计层级以及图片处理的整体流程|
|Android UI 刷新原理|ing||
|Fresco|next|主要分析Fresco框架的设计层级以及图片处理的整体流程|
|Android UI 刷新原理|next||
|......| |
| | |



如果你感觉某个技术点,有一些更好的分析,欢迎提 pull request给我。

>文章有我自己写的,也有的是贴的一些比较好的文章链接(如有侵权,请联系我)。

Expand All @@ -27,3 +27,4 @@




2 changes: 1 addition & 1 deletion router/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@

在阅读完`ARouter`和`WMRouter`的源码后,我对这两个框架的路由功能做了一个对比:

- <a href="Android路由框架:WMRouter与ARouter的对比.md"> WMRouter与ARouter的对比 </a>
- <a href="./Android路由框架:WMRouter与ARouter的对比.md"> WMRouter与ARouter的对比 </a>

98 changes: 98 additions & 0 deletions 插件化/PathClassLoader与DexClassLoader到底有什么不同.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@

先说一下为什么要抛出这个问题吧?

最近在看插件化相关的技术,因此会涉及到插件中的类如何加载,根据我以前的了解,再加上在网上查了解的知识,认为他们的区别是:

- DexClassLoader : 可加载jar、apk和dex,可以SD卡中加载
- PathClassLoader : 只能加载已安裝到系統中(即/data/app目录下)的apk文件

有这两个区别是因为`DexClassLoader`在构造的时候多传了一个`optimizedDirectory`参数,因此造成了这个区别:

```
public DexClassLoader(String dexPath, String optimizedDirectory,String librarySearchPath, ClassLoader parent) {
super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);
}
```

但我在看源码的时候发现了一个问题 : 我发现在最新的源码中这个参数已经被`deprecated`了。而且,看源码我真没看出来这两个ClassLoader在能力上到底有什么不同。。。

>DexClassLoader.java
```
public class DexClassLoader extends BaseDexClassLoader {
/**
@param optimizedDirectory this parameter is deprecated and has no effect since API level 26.
*/
public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) {
super(dexPath, null, librarySearchPath, parent);
}
}
```

>PathClassLoader.java
```
public class PathClassLoader extends BaseDexClassLoader {
public PathClassLoader(String dexPath, ClassLoader parent) {
super(dexPath, null, null, parent);
}

public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
super(dexPath, null, librarySearchPath, parent);
}
}
```

即,`DexClassLoader`传的`optimizedDirectory` 参数根本没用。 官方已经标注了`is deprecated` & `no effect since API level 26`。 这我就有疑问了? 文章一开始 *DexClassLoader相比于PathClassLoader可以加载SD卡上的apk* 是怎么得出的呢?

在最新源码中,这两者构造函数的能力是一样的。并且 *基类是不可能强判子类做相关处理逻辑的吧?*, 因此,再看一下官方文档对这两个类的解释:

- PathClassLoader
>提供ClassLoader在本地文件系统中的文件和目录列表上运行的简单实现,但不尝试从网络加载类。Android将此类用于其系统类加载器及其应用程序类加载器。

- DexClassLoader
>它可以加载 .jar、.apk和dex文件。这可用于执行未作为应用程序的一部分安装的代码。在API级别26之前,此类加载器需要一个应用程序专用的可写目录来缓存优化的类。使用Context.getCodeCacheDir()创建这样一个目录:
>`File dexOutputDir = context.getCodeCacheDir();`自`API 26`后不要在外部存储上缓存优化的类。 外部存储不提供保护应用程序免受代码注入攻击所必需的访问控制。

看官方文档,好像说的也不明白。但是在26以前`optimizedDirectory`参数是用来指明缓存优化后的加载的类的目录。26以后就废弃了。

我对这两个类做了一个测试发现: `PathClassLoader`也是可以加载`SD卡`上的apk的。

下面是测试代码:

```
private void loadClassTest() {
File apk = new File(Environment.getExternalStorageDirectory(), "Test1.apk");
PathClassLoader pathClassLoader = new PathClassLoader(apk.getAbsolutePath(), null, this.getApplication().getClassLoader());
DexClassLoader dexClassLoader = new DexClassLoader(apk.getAbsolutePath(), null, null, this.getApplication().getClassLoader());

String classNameInTestApk = "com.susion.myapplication.modle2.Module2";

try {
Class loadByPathClassLoader = pathClassLoader.loadClass(classNameInTestApk);
Log.e("susion", " PathClassLoader load success : " + loadByPathClassLoader.getName());

Class loadByDexClassLoader = dexClassLoader.loadClass(classNameInTestApk);
Log.e("susion", " DexClassLoader load success : " + loadByDexClassLoader.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
```

*跑这段代码前注意申请相关存储权限。* 这个`Test1.apk`是我用另一个工程打的包,放在了sd卡的根目录。并没有安装在手机上。

首先我在 `API Platform 27`上跑了这段代码(即 compileSdkVersion = 27),打印的log如下:

```
PathClassLoader load success : com.susion.myapplication.modle2.Module2
DexClassLoader load success : com.susion.myapplication.modle2.Module2
```

然后我在 `API Platform 21`上跑了这段代码,打印的log如下:

```
PathClassLoader load success : com.susion.myapplication.modle2.Module2
DexClassLoader load success : com.susion.myapplication.modle2.Module2
```

即,都能加载成功。so,这两个ClassLoader到底有什么区别呢?从我现在所看到的,好像没什么区别。

This file was deleted.

14 changes: 12 additions & 2 deletions 插件化/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@

`VirtualApk`是由滴滴开源的一款插件化框架。主要实现思路是`hook`系统多处对于`Android四大组件`的处理,以达到调用插件的四大组件的实现。我们这里主要看一下它是如何实现的、用到了哪些东西。下面的文章不会去细究实现逻辑,只看`VirtualApk`关于一些关键点的实现思路。

### 如何解析一个插件APK

在`VirtualApk`中,一个插件会被打成一个`.apk`文件。因此加载插件其实就是加载这个`.apk`文件,那么如何加载一个`.apk`文件,并解析出这个文件中的信息,比如四大组件、resourse、类等等 :

<a href="VirtualApk/插件APK的解析.md">插件APK的解析</a>

其实不只是`VirtualApk`,很多其他插件化框架对于插件apk的解析也是这个思路。

上一篇文章已经详细了解了一个插件的apk的类、资源、四大组件信息时如何被加载到宿主中了。那么接下来我们就来看一下宿主如何使用插件的四大组件。以启动一个插件的Activity为例:
### 插件Activity的启动

上一篇文章已经详细了解了一个插件的apk的类、资源、四大组件信息时如何被加载到宿主中了。那么接下来我们就来看一下宿主如何使用插件的四大组件。以启动一个插件的Activity为例。

在看`VirtualApk`启动插件Activity时,发现了一个问题,这里先记录一下:

<a href="./PathClassLoader与DexClassLoader到底有什么不同.md">PathClassLoader与DexClassLoader到底有什么不同?</a>

然后具体看一下,插件Activity是如何启动的:

<a href="VirtualApk/插件Activity的启动.md">插件Activity的启动</a>
<a href="VirtualApk/插件Activity的启动.md">插件Activity的启动</a>
Binary file added 插件化/VirtualApk/.DS_Store
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading