1. 程式人生 > >Android實現資源動態載入的兩種方式

Android實現資源動態載入的兩種方式

這是Android Apk源載入機制原理分析以及動態載入實現系列文章 的最後一篇。經過前兩篇的介紹之後,相關基礎都講的差不多了,現在要實現自己專案中的資源載入框架,這裡提供兩種方式,區別在於由誰來載入資源。

  • 1、利用系統載入資源Apk
  • 2、主動手動實現資源的載入

利用系統載入資源Apk

如果看了我的前兩篇對系統資源載入機制分析的文章,這種方式很容易聯想到。既然系統有一套成熟的資源載入機制,並經過分析完全可以獨立出來,並且還很簡單。從前兩篇文章中很容易看到系統載入資源主要就是靠AssetManager類來實現,再通過Resources來載入具體的資源,以及Activity中的資源載入都是轉由mBase(ContextImpl)來完成的,那麼動態載入的話,我們就可以不利用mBase,重寫ContextWrapper的獲取Asset和Resources方法:

public class ContextWrapper extends Context {
 Context mBase;
....
protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

 @Override
    public Resources getResources
() { return mBase.getResources(); } ..... }

直接在Activity中覆蓋這兩個方法的實現,讓資源獲取都轉到自己單獨載入的Resource中,實現如下:

public class DynamicResourcesActivity extends Activity{
....
  AssetManager mLocalAssetManager ;
  Resources  mLoacalResources ;

@Override
  public AssetManager getAssets(){
          return
mLocalAssetManager ; } @Override public Resources getResources(){ return mLoacalResources ; } .... }

接下來就是要實現載入動態資源的AssetManager和Resources即上文的mLocalAssetManager 和mLoacalResources ,程式碼如下:

privated void loadResources() {  
    try {  
        mLocalAssetManager  = AssetManager.class.newInstance();  
        Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);  
        addAssetPath.invoke(assetManager, mDexPath);  
        mAssetManager = assetManager;  
    } catch (Exception e) {  
        e.printStackTrace();  
    }  
    Resources superRes = super.getResources();  
    mLoacalResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),  
            superRes.getConfiguration());  
    mTheme = mLoacalResources .newTheme();  
    mTheme.setTo(super.getTheme());  
}  

Android App啟動時Apk資源載入機制原始碼分析中就介紹了資源Apk的載入就是通過addAssetPath來實現的,但這個方法是隱藏的,故利用反射方式。

這樣就可以通過DynamicResourcesActivity 來動態載入Apk資源了。這種方式簡單快捷,但是也有缺陷,必須要維護AssetManager以及Resources,對於的資源是一個res目錄或者zip檔案,必須由aapt工具來對資源打包編譯,不夠靈活,需要資源id,如果res佈局檔案下,僅僅是手動佈局,簡單載入少數資源。那就有另一種方式主動載入任意
目錄下的檔案。

主動手動實現資源的載入

Res目錄下資源如圖片檔案和xml檔案資源如何被載入顯示出來中提到過圖片的載入實際上就是獲取了對應資料位元組流,以及xmL資源是解析了對應的檔案內容,原理都是這樣,那我們就是手動實現資源載入獲取,模仿系統載入機制需要如下方面工作:

  • 1、Drawable快取機制
    為了加快和節省記憶體

  • 2、圖片檔案以及其他資源讀取資料
    讀取流資料以及xml檔案解析

  • 利用Drawable類對資源資料處理
    若是Xml檔案通過 Drawable.createFromXml(wrapper, rp, theme)
    來實現,而對於圖片就是通過mAssets即AssetManager直接獲取對應的圖片的位元組流然後通過
    Drawable.createFromResourceStream(wrapper, value, is, file, null)
    轉成Drawable物件。

  • 3、根據當前解析度顯示資源並適配

這種方式對於適配不同解析度下就麻煩點,剛開始都是用大圖片來適配小圖片。其實也可以模擬不同解析度檔案來分開載入不同圖片。

總結

兩種方式均用到專案中去,如果僅僅是簡單的替換資源,且內容不多的話就可以直接用第二種方式,第一種對於動態載入框架來說很有用的。

相關推薦

Android實現資源動態載入方式

這是Android Apk源載入機制原理分析以及動態載入實現系列文章 的最後一篇。經過前兩篇的介紹之後,相關基礎都講的差不多了,現在要實現自己專案中的資源載入框架,這裡提供兩種方式,區別在於由誰來載入資源。 1、利用系統載入資源Apk 2、主動手動實現資

Android實現音訊錄製的方式

package com.hb56.MyAndroidUtil; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.Dat

詳解SpringCloud-gateway動態路由方式,以及路由載入過程

gateway配置路由主要有兩種方式,一種是用yml配置檔案,一種是寫程式碼裡,這兩種方式都是不支援動態配置的。如: 下面就來看看gateway是如何載入這些配置資訊的。 1 路由初始化 無論是yml還是程式碼,這些配置最終都是被封裝到RouteDefinition

Android JNI 函式註冊的方式(靜態註冊/動態註冊)

JNI/NDK 在Android開發中,由於種種原因我們需要呼叫C/C++程式碼, 這個時候就要用到Android開發者都聽說

Android: Android Studio簽名打包的方式(zz)

信息 rda pan 相同 prop .cn 一個 一次 ack 註:給我們自己開發的app簽名,就代表著我自己的版權,以後要進行升級,也必須要使用相同的簽名才行。簽名就代表著自己的身份(即keystore),多個app可以使用同一個簽名。如果不知道簽名是啥意思,請自行百度

使用aspectJ實現Spring AOP的方式

classpath .org 導入 ntc www. 之前 oid 方式 public 方式一:基於aspectJ的XML配置 方式二:基於aspectJ的註解方式 基於aspectJ的XML配置 1) 引入相關jar包 2) 創建Spr

Android以JSONOject和GSON方式解析json

length pre ray oid 字符 CA clas img name json文件如下: 將獲取到的json數據轉化為String形式 OkHttpClient client = new OkHttpClient(); R

基於aspectj實現AOP操作的方式——xml配置

aop ont 方式 alt 分享圖片 文件 分享 spa 技術分享 1. 要導入的 jar 包: 常用的aspectj表達式: 權限修飾符可以省略,以下表示:返回值類型為任意,com.chy.service包以及其子包下的、任意類的、參數任意的、任意方法 ex

18.2 實現線程的方式

pri java虛擬機 run 構造 語法 oid except 方式 reads 一、概述   在Java中主要提供兩種方式實現線程,分別為繼承java.lang.Thread類與實現java.lang.Runnable接口。 二、繼承Thread類   a、Thread

Android專案開源到JCenter方式

前言 開發中,或多或少都會用到無私的程式猿分享的開源專案,Androidstudio中使用開源也很方便 例如家喻戶曉的Rxjava,只需要一句話 compile 'io.reactivex:rxjava:1.1.6',就可以新增到專案中,時間久了,是不是自己也想試試開源一下自己的成果

【C語言】實現一個計算器(方式

1.使用switch…case…語句實現 #define _CRT_SECURE_NO_DEPRECATE 1 #include <stdio.h> #include <stdlib.h> int add(int x, int y) {   &nb

java:多執行緒(匿名內部類實現執行緒的方式)

public class Demo4_Thread { public static void main(String[] args) { new Thread() {//1.繼承Thread類 public void run() {//2.重寫run方法 for(int i

Go基礎系列:Go實現工作池的方式

worker pool簡介 worker pool其實就是執行緒池thread pool。對於go來說,直接使用的是goroutine而非執行緒,不過這裡仍然以執行緒來解釋執行緒池。 線上程池模型中,有2個佇列一個池子:任務佇列、已完成任務佇列和執行緒池。其中已完成任務佇列可能存在也可能不存在,依據實際需

vue-router 原始碼實現前端路由的方式

在學習 vue-router 的程式碼之前,先來簡單瞭解一下前端路由。 前端路由主要有兩種實現方法: Hash 路由 History 路由 先來看看這兩種方法的實現原理。 接著我們將用它們來簡單實現一個自己的前端路由。 前端路由 Hash 路由 u

java實現執行緒的方式

第一種: new Thread(){}.start();這表示呼叫Thread 子類物件的 run 方法, new Thread(){}表示一個Thread 的匿名子類的例項物件,子類加上 run 方法後的程式碼如下:new Thread(){public void run(){}}.s

jquery實現省市聯動的方式(xml,,,json)

省市聯動,xml傳值方式 匯入相應的jar 建立表單 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> &

iText G (Android)PDF文字定位書寫方式介紹

閒言少敘,直接進入話題(相關基礎知識不瞭解,請使用百度之類惡補),有不當之處,請高人批准指正。。 方法一(絕對定位),參考形如: PdfContentByte pdfContentByte = pdfWriter.getDirectContent(); Base

android開啟另外的app方式,內建到自己本身的app,重新開啟app,

android開啟另外的app兩種方式,內建到自己本身的app空間,重新開啟app空間, 目錄 1、內建到自己本身的app空間, 被開啟的app的activity的主配置檔案的程式碼編寫、 <activity android:n

實現序列化的方式Serializable和Parcelable

Serializable       Serializable是Java所提供的一個序列化介面,它是一個空介面,為物件提供標準的序列化和反序列化操作        libcore/ojluni/src/main/java/java/io/Serializable.java

匿名內部類實現執行緒的方式

public static void main(String[] args) { //匿名內部類實現執行緒的兩種方式 /*Thread t1 = new Thread(){ @Override pub