轉自:http://www.cnblogs.com/dividxiaoshuo-fighting/p/3682398.html?utm_source=tuicool
一、裝載器簡介
“類裝載器”(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函數。
1 package com.david.plugin; 2 3 import android.util.Log; 4 5 public class Plugin { 6 7 private static final String TAG=Plugin.class.getSimpleName(); 8 9 public Plugin(){ 10 Log.i(TAG, "PluginClass is initialized"); 11 } 12 13 public int addition(int a,int b){ 14 return a+b; 15 } 16 17 }
plugin的apk中AndroidManifest文件中,activity必須聲明一個action。
1 <activity 2 android:name="com.david.plugin.MainActivity" 3 android:label="@string/app_name" > 4 <intent-filter> 5 <action android:name="com.david.plugin.client"/> 6 <action android:name="android.intent.action.MAIN" /> 7 <category android:name="android.intent.category.LAUNCHER" /> 8 </intent-filter> 9 </activity>
將plugin.apk裝載進Android設備中。Host.apk中主activity調用的代碼如下:
1 package com.david.host; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 import java.util.List; 6 7 import dalvik.system.DexClassLoader; 8 import android.support.v7.app.ActionBarActivity; 9 import android.annotation.SuppressLint; 10 import android.content.Intent; 11 import android.content.pm.ActivityInfo; 12 import android.content.pm.PackageManager; 13 import android.content.pm.ResolveInfo; 14 import android.os.Bundle; 15 import android.view.View; 16 import android.view.View.OnClickListener; 17 import android.widget.Button; 18 19 20 public class MainActivity extends ActionBarActivity implements OnClickListener{ 21 22 private static final String plugin_package = "com.david.plugin.client"; 23 private PackageManager pm; 24 private ResolveInfo resolveInfo; 25 private Button btn_classLoader; 26 27 @Override 28 protected void onCreate(Bundle savedInstanceState) { 29 super.onCreate(savedInstanceState); 30 setContentView(R.layout.activity_main); 31 // useDexClassLoader(); 32 btn_classLoader=(Button) findViewById(R.id.btn_classLoader); 33 btn_classLoader.setOnClickListener(this); 34 } 35 36 @SuppressLint("NewApi") 37 public void useDexClassLoader() { 38 Intent classIntent = new Intent(plugin_package, null); 39 pm = getPackageManager(); 40 List<ResolveInfo> activities = pm.queryIntentActivities(classIntent, 0); 41 resolveInfo = activities.get(0); 42 ActivityInfo activityInfo = resolveInfo.activityInfo; 43 44 String div = System.getProperty("path.separator"); 45 String packageName = activityInfo.packageName; 46 String sourceDir = activityInfo.applicationInfo.sourceDir; 47 System.out.println(sourceDir); 48 String outDir = getApplicationInfo().dataDir; 49 System.out.println(outDir); 50 String libraryDir = activityInfo.applicationInfo.nativeLibraryDir; 51 System.out.println(libraryDir); 52 53 DexClassLoader dexcl = new DexClassLoader(sourceDir, outDir, 54 libraryDir, this.getClass().getClassLoader()); 55 try { 56 Class<?> loadClass = dexcl.loadClass(packageName+".Plugin"); 57 Object instance = loadClass.newInstance(); 58 Class[] params = new Class[2]; 59 params[0]=Integer.TYPE; 60 params[1]=Integer.TYPE; 61 Method method = loadClass.getMethod("addition", params); 62 Integer result = (Integer) method.invoke(instance, 12,32); 63 System.out.println(result); 64 } catch (ClassNotFoundException e) { 65 e.printStackTrace(); 66 } catch (InstantiationException e) { 67 e.printStackTrace(); 68 } catch (IllegalAccessException e) { 69 e.printStackTrace(); 70 } catch (NoSuchMethodException e) { 71 e.printStackTrace(); 72 } catch (IllegalArgumentException e) { 73 e.printStackTrace(); 74 } catch (InvocationTargetException e) { 75 // TODO Auto-generated catch block 76 e.printStackTrace(); 77 } 78 79 } 80 81 @Override 82 public void onClick(View v) { 83 useDexClassLoader(); 84 } 85 }
運行後得到的結果是:
類加載器在應用中還是用到比較多,還可以基於它設計一種“插件”架構。