Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android DexClassLoader動態加載技術詳解

android DexClassLoader動態加載技術詳解

編輯:關於Android編程

介紹

做項目到一定龐大的時候就會發現方法數太多,安裝包根本就裝不上去了,這個也不足為奇,我們都知道當方法數目超過65536這個數目限制的時候,擋在2.x的系統上面就會出現無法安裝的情況,這個時候動態加載技術就顯得非的重要了,我們的項目中為了兼容2.x的手機也是用到了android的動態加載技術,這裡我會詳細的講解一下怎麼去用,怎麼實戰,我感覺,空談理論不如動手來得實在。

實例

下面就通過一個例子反復的說明怎麼來實現動態加載,通過不同的方法來調用。

准備工作

1:新建一個java工程(我比較懶我就直接新建Android工程了) 2:然後看看包路徑。 \ 我們敲入裡面的代碼:先是Iinterface.java
package com.demo.dex;

/**
 * 對外接口
 * 
 * @author edsheng
 * 
 */
public interface Iinterface {
	public void call();

	public String getData();
}

然後是Iclass.java
package com.demo.dex;

import android.content.Context;
import android.widget.Toast;

public class IClass implements Iinterface {

	private Context context;

	public IClass(Context context) {
		super();
		this.context = context;
	}

	@Override
	public void call() {
		Toast.makeText(context, "call method", 0).show();
	}

	@Override
	public String getData() {
		return "hello,i am from IClass";
	}

}
注意上面的實現類,在構造的時候我給它傳遞了以Context對象,為什麼要這樣呢?因為在android裡面什麼東西不都是通過context來獲取的嗎?我這裡為了實驗就只調用了一下toast。 既然准備工作都准備好了,那就開始下一步吧。導出為jar。工程上面右鍵,export->java->jar file選中src下面的這兩個類就行了。 \
導出我們的jar文件我給他命名為test.jar,然後把java的class文件轉換成android能識別的字節碼吧。使用dx工具,可以在andorid的SKD目錄下面搜索一下這個工具,以前的說在platfZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcm0tdG9vbHPV4rj2xL/CvM/Cw+a1q8rHztLDu9PQ1dK1vaOsz+C3tM7S1NpidWlsZC10b29sc8Dvw+a1xNfTxL/CvMDvw+bV0rW9wcuyu82ssOaxvrXEZHi5pL7fo6zO0svmsePV0sHL0ru49rDmsb61xDE5LjAuM8i7uvOw0XRlc3QuamFyuLTWxrW91eK49sS/wrzPwsPmo6wKINTaY21kw/zB7sDvw+bHw8jrPHByZSBjbGFzcz0="brush:java;">dx --dex --output=testdex.jar test.jar
\ 然後准備工作就完成了,這樣一個優化的jar或者說是dex就准備好了。

正式開始

新建一個andorid工程(我比較懶,剛才已經就是使用的andorid工程),然後把testdex.jar復制到assets目錄下面,來看看我的工程目錄吧。\
然後貼出FileUtil.java的代碼
package com.demo.utile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import android.content.Context;
import android.os.Environment;

public class FileUtile {
	public static void CopyAssertJarToFile(Context context, String filename,
			String des) {
		try {

			File file = new File(Environment.getExternalStorageDirectory()
					.toString() + File.separator + des);
			if (file.exists()) {
				return;
			}

			InputStream inputStream = context.getAssets().open(filename);
			file.createNewFile();
			FileOutputStream fileOutputStream = new FileOutputStream(file);
			byte buffer[] = new byte[1024];
			int len = 0;
			while ((len = inputStream.read(buffer)) != 0) {
				fileOutputStream.write(buffer, 0, len);
			}
			fileOutputStream.close();
			fileOutputStream.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
這個類主要的作用就是把我們的jar相當於解壓到一個目錄下面。我這裡是解壓到外置設備上的其實這樣做的安全性並不高,但是為了方便我就這樣做了,建議是解壓到包目錄下面。記住別忘了給應用加權限!!!!!文件讀寫權限!!!! 最後我們來看看Activity裡面的代碼
package com.demo.activity;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;

import com.demo.utile.FileUtile;

import dalvik.system.DexClassLoader;

public class MainActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		FileUtile.CopyAssertJarToFile(this, "testdex.jar", "testdex.jar");

		File file = new File(Environment.getExternalStorageDirectory()
				.toString() + File.separator + "testdex.jar");
		final File optimizedDexOutputPath = getDir("temp", Context.MODE_PRIVATE);
		DexClassLoader classLoader = new DexClassLoader(file.getAbsolutePath(),
				optimizedDexOutputPath.getAbsolutePath(), null,
				getClassLoader());
		try {
			Class iclass = classLoader.loadClass("com.demo.dex.IClass");
			Constructor istructor = iclass.getConstructor(Context.class);
			//利用反射原理去調用
			Method method = iclass.getMethod("call", null);
			String data = (String) method.invoke(istructor.newInstance(this), null);
			System.out.println(data);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
其實這樣調用還有一點要注意的是我感覺這樣做每次都要去調用反射,總給我感覺來說不太友好,那麼這裡我有給出了下面一種寫法,這種寫法最主要的地方是,要獲得Iinterface這個接口,把Iinterface.java這個文件復制到你的工程裡面,記得包名相同,調用的時候我們可以這樣來調用它。
Class iclass = classLoader.loadClass("com.demo.dex.IClass");
			Constructor istructor = iclass.getConstructor(Context.class);
			Iinterface iinterface = (Iinterface) istructor.newInstance(this);
			 String data = iinterface.getData();
			 iinterface.call();
			 Toast.makeText(this, data, 0).show();
這樣是不是看起來更舒服呢? 好了今天就分享到這裡。Demo下載地址:CSDN上傳抽風了,這裡先上到百度網盤點擊這裡

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved