1. 程式人生 > >Resource()中的getDrawable(int id)是怎樣將圖片顯示出來的

Resource()中的getDrawable(int id)是怎樣將圖片顯示出來的

首先看Resources.java中的getDrawable(int id)方法的原始碼:
 public Drawable getDrawable(int id) throws NotFoundException {
        synchronized (mTmpValue) {
            TypedValue value = mTmpValue;
            getValue(id, value, true);
            return loadDrawable(value, id);
        }
    }
在這個方法中找到傳入的id的值的圖片並返回.
在這裡我們可以看到該方法將id傳給loadDrawable(value, id);同時傳遞的還有value,顯然這個值是很關鍵的,看看這個值在這裡起到怎樣的作用
(1)final TypedValue mTmpValue = new TypedValue();
官方文件對這個類的解釋:Container for a dynamically typed data value. Primarily used with Resources for holding resource values.
翻譯:
一個動態地資料值的容器。 主要被Resouces使用於持有的資源值.我理解為儲存資料型別
(2)getValue(id,value,true)
執行這個方法獲取該id的資源的屬性


 public void getValue(int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException {
        boolean found = mAssets.getResourceValue(id, outValue, resolveRefs);
        if (found) {
            return;
        }
        throw new NotFoundException("Resource ID #0x"+ Integer.toHexString(id));
    }
這裡涉及的方法:
final AssetManager mAssets;
mAssets.getResourceValue(id, outValue, resolveRefs);
原始碼如下:
final boolean getResourceValue(int ident,TypedValue outValue,boolean resolveRefs){
        int block = loadResourceValue(ident, outValue, resolveRefs);
        if (block >= 0) {
            if (outValue.type != TypedValue.TYPE_STRING) {
                return true;
            }
            outValue.string = mStringBlocks[block].get(outValue.data);
            return true;
        }
        return false;
    }
涉及方法:
  /** Returns true if the resource was found, filling in mRetStringBlock andmRetData. */
    private native final int loadResourceValue(int ident, TypedValue outValue,boolean resolve);
我們已經將載入圖片的方法到了底層的C程式碼,從原始碼的註釋,我們可以看到
"如果資源被找到返回true,同時填補mRetStringBlock andmRetData"
也就是通過id號,我們應該已經拿到資源的屬性,存放在value內,通過TypedValue中的方法和屬性就可以獲得我們想要的值.
在前面做了這麼多的準備工作後,下面的原始碼就是我們實現的核心方法了,
Drawable loadDrawable(TypedValue value, int id)throws NotFoundException {
        if (TRACE_FOR_PRELOAD) {
            // Log only framework resources
            if ((id >>> 24) == 0x1) {
                final String name = getResourceName(id);
                if (name != null) android.util.Log.d("PreloadDrawable", name);
            }
        }
        final long key = (((long) value.assetCookie) << 32) | value.data;
        Drawable dr = getCachedDrawable(key);
        if (dr != null) {
            return dr;
        }
        Drawable.ConstantState cs = sPreloadedDrawables.get(key);
        if (cs != null) {
            dr = cs.newDrawable(this);
        } else {
            if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
                    value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
                dr = new ColorDrawable(value.data);
            }
            if (dr == null) {
                if (value.string == null) {//表示無資源
                    throw new NotFoundException( "Resource is not a Drawable (color or path): " + value);
                }
   //獲取資源的名字
                String file = value.string.toString();
                if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "
                        + value.assetCookie + ": " + file);
                if (file.endsWith(".xml")) {//解析xml檔案,返回drawable
                    try {
                        XmlResourceParser rp = loadXmlResourceParser(
                                file, id, value.assetCookie, "drawable");
                        dr = Drawable.createFromXml(this, rp);
                        rp.close();
                    } catch (Exception e) {
                        NotFoundException rnf = new NotFoundException(
                            "File " + file + " from drawable resource ID #0x"
                            + Integer.toHexString(id));
                        rnf.initCause(e);
                        throw rnf;
                    }
                } else {
                    try {//獲取外部資源Asset
                        InputStream is = mAssets.openNonAsset(value.assetCookie, file, AssetManager.ACCESS_STREAMING);
        //              System.out.println("Opened file " + file + ": " + is);
                        dr = Drawable.createFromResourceStream(this, value, is, file, null);                        is.close();
        //              System.out.println("Created stream: " + dr);
                    } catch (Exception e) {
                        NotFoundException rnf = new NotFoundException(
                            "File " + file + " from drawable resource ID #0x"
                            + Integer.toHexString(id));
                        rnf.initCause(e);
                        throw rnf;
                    }
                }
            }
        }
        if (dr != null) {
            dr.setChangingConfigurations(value.changingConfigurations);
            cs = dr.getConstantState();
            if (cs != null) {
                if (mPreloading) {
                    sPreloadedDrawables.put(key, cs);
                } else {
                    synchronized (mTmpValue) {
                        //Log.i(TAG, "Saving cached drawable @ #" +
                        //        Integer.toHexString(key.intValue())
                        //        + " in " + this + ": " + cs);                        mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
                    }
                }
            }
        }
        return dr;
    }