声明:此篇文章借鉴《android内核剖析》整理得来。

一、装载器简介

  “类装载器”(ClassLoader),顾名思义,就是用来动态装载class文件的。标准的Java SDK中有个ClassLoader类,借助此类可以装载需要的class文件,前提是

ClassLoader类初始化必须制定class文件的路径。

  import关键字引用的类文件和ClassLoader动态加载类的区别:

    import引用类的两个特点:1、必须存在于本地,当程序运行该类时,内部类装载器会自动装载该类。

                 2、编译时必须在现场,否则编译过程会因找不到引用文件而不能正常编译。

    classLoader的特点正好于import相反,而且更自由灵活。

  每一个ClassLoader必须有一个父ClassLoader,在装载Class文件时,子ClassLoader会先请求其父ClassLoader加载该文件,只有当其父ClassLoader找不到该文件时,子ClassLoader才会继承装载该类。这是一种安全机制。对于Android而言,最终的apk文件包含的是dex类型的文件,dex文件是将class文件重新打包,打包的规则又不是简单地压缩,而是完全对class文件内部的各种函数表,变量表进行优化,产生一个新的文件,即dex文件。因此加载这种特殊的Class文件就需要特殊的类加载器DexClassLoader。

二、DexClassLoader的方法的实用

  假设有两个apk,第一个叫做Host,第二个叫Plugin。Plugin中第一个一个类Plugin,该类中定义了一个addition函数。

  

 package com.david.plugin;

 import android.util.Log;

 public class Plugin {

     private static final String TAG=Plugin.class.getSimpleName();

     public Plugin(){
Log.i(TAG, "PluginClass is initialized");
} public int addition(int a,int b){
return a+b;
} }

  plugin的apk中AndroidManifest文件中,activity必须声明一个action。

 <activity
android:name="com.david.plugin.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="com.david.plugin.client"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

  将plugin.apk装载进Android设备中。Host.apk中主activity调用的代码如下:

 package com.david.host;

 import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List; import dalvik.system.DexClassLoader;
import android.support.v7.app.ActionBarActivity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; public class MainActivity extends ActionBarActivity implements OnClickListener{ private static final String plugin_package = "com.david.plugin.client";
private PackageManager pm;
private ResolveInfo resolveInfo;
private Button btn_classLoader; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// useDexClassLoader();
btn_classLoader=(Button) findViewById(R.id.btn_classLoader);
btn_classLoader.setOnClickListener(this);
} @SuppressLint("NewApi")
public void useDexClassLoader() {
Intent classIntent = new Intent(plugin_package, null);
pm = getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(classIntent, 0);
resolveInfo = activities.get(0);
ActivityInfo activityInfo = resolveInfo.activityInfo; String div = System.getProperty("path.separator");
String packageName = activityInfo.packageName;
String sourceDir = activityInfo.applicationInfo.sourceDir;
System.out.println(sourceDir);
String outDir = getApplicationInfo().dataDir;
System.out.println(outDir);
String libraryDir = activityInfo.applicationInfo.nativeLibraryDir;
System.out.println(libraryDir); DexClassLoader dexcl = new DexClassLoader(sourceDir, outDir,
libraryDir, this.getClass().getClassLoader());
try {
Class<?> loadClass = dexcl.loadClass(packageName+".Plugin");
Object instance = loadClass.newInstance();
Class[] params = new Class[2];
params[0]=Integer.TYPE;
params[1]=Integer.TYPE;
Method method = loadClass.getMethod("addition", params);
Integer result = (Integer) method.invoke(instance, 12,32);
System.out.println(result);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } @Override
public void onClick(View v) {
useDexClassLoader();
}
}

  运行后得到的结果是:

类加载器在应用中还是用到比较多,还可以基于它设计一种“插件”架构。

Android类装载器DexClassLoader的简单使用-----制作android插件的前奏的更多相关文章

  1. Android中SharedPerforences的简单使用示例 --Android基础

    SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些常用配置,比如Activity状态,Activity暂停时,将此activity的状态保存到SharedP ...

  2. Android系列:res之shape制作

    大家好,pls call me francis. nice to me you. 本文将介绍使用在Android中使用shape标签绘制drawable资源图片. 下面的代码是shap标签的基本使用情 ...

  3. 基于Android平台的图书管理系统的制作(1)

    在学习了郭神的第一行代码前半段之后,想通过一次实践来完成对已学知识的巩固.于是码下了这个图书管理系统客户端. IDE Android studio,语言 JAVA.XML: 在刚开始设计的时候对于这个 ...

  4. Xamarin.Android之Spinner的简单探讨

    一.前言 今天用了一下Spinner这个控件,主要是结合官网的例子来用的,不过官网的是把数据写在Strings.xml中的, 某种程度上,不是很符合我们需要的,比较多的应该都是从数据库读出来,绑定上去 ...

  5. Xamarin.Android之封装个简单的网络请求类

    一.前言 回忆到上篇 <Xamarin.Android再体验之简单的登录Demo> 做登录时,用的是GET的请求,还用的是同步, 于是现在将其简单的改写,做了个简单的封装,包含基于Http ...

  6. [电子书] 《Android编程入门很简单》

    <Android编程入门很简单>是一本与众不同的Android学习读物,是一本化繁为简,把抽象问题具体化,把复杂问题简单化的书.本书避免出现云山雾罩.晦涩难懂的讲解,代之以轻松活泼.由浅入 ...

  7. android复习第一天-----简单的android常识

    前言:要去面试了,这些天花一些事件把android中简单的知识点来串联的复习一下 1,android中的工程结构 src文件夹:存储android文件的源代码 gen文件夹:有工具自动生成,不要去修改 ...

  8. GitHub 上排名前 100 的 Android 开源库进行简单的介绍

    若有任何疑问可通过邮件或微博联系我 项目名称 项目简介 1. react-native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开 ...

  9. [原创]Android中LocationManager的简单使用,获取当前位置

    Android中LocationManager的提供了一系列方法来地理位置相关的问题,包括查询上一个已知位置:注册/注销来自某个 LocationProvider的周期性的位置更新:以及注册/注销接近 ...

随机推荐

  1. 有3D效果的进度条

    // The Unofficial Newsletter of Delphi Users - Issue #12 - February 23rd, 1996 unit Percnt3d; (* TPe ...

  2. MySQL Installation of system tables failed!

    刚开始学习Linux,就遇到了问题. 当在RedHat下安装MySQL时提示如下错误,请高手给点指点,谢谢: rpm -vih  MySQL-server-community-5.0.96-1.rhe ...

  3. Python int() 函数

    Python int() 函数  Python 内置函数 描述 int() 函数用于将一个字符串或数字转换为整型. 语法 以下是 int() 方法的语法: class int(x, base=10) ...

  4. Frog and Portal(思维好题)

    Frog and Portal https://hihocoder.com/problemset/problem/1873 时间限制:1000ms 单点时限:1000ms 内存限制:512MB 描述 ...

  5. C# .net MD5加密函数

    using System.Web.Security; string password =FormsAuthentication.HashPasswordForStoringInConfigFile(t ...

  6. 16-图片上传那些事 org.springframework.web.multipart.MultipartException: The current request is not a multipart request

    https://blog.csdn.net/u010974598/article/details/46458039 我曾尝试了: @RequestMapping(value="/user/r ...

  7. mockito使用

    mockito学习资料: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html http://blog.csdn.net/sdy ...

  8. java 错误: 找不到或无法加载主类

    这个问题应该很常见的,笔者经常手工编译一些测试代码或者小工具,经常用到 javac和java来编译并运行一些简单的小工具. 以Hello World来测试. HelloWorld.java publi ...

  9. sql ltrim/rtrim 字段中为中文时出现?的问题

    字段存储为中文,类型为nvarchar,使用ltrim时结果集中出现的问号,我的解决办法是:将问号replace掉

  10. select查询

    4.2  查询功能 SQL的核心是查询.SQL的查询命令也称作SELECT命令,它的基本形式由SELECT-FROM-WHERE查询块组成,多个查询块可以嵌套执行. 以下表为以后的例子中使用表: 档案 ...