From f81616f2f1331a867843c322c2f0490385cdbfed Mon Sep 17 00:00:00 2001 From: REAndroid Date: Sat, 11 Mar 2023 05:14:01 -0500 Subject: [PATCH] implement destroy Block --- .../java/com/reandroid/apk/ApkModule.java | 54 +++- .../java/com/reandroid/apk/FrameworkApk.java | 242 ++++++++++++++---- .../reandroid/arsc/array/PackageArray.java | 8 + .../com/reandroid/arsc/array/StringArray.java | 9 +- .../com/reandroid/arsc/array/StyleArray.java | 7 + .../reandroid/arsc/chunk/PackageBlock.java | 11 + .../com/reandroid/arsc/chunk/TableBlock.java | 18 +- .../arsc/chunk/xml/ResXmlDocument.java | 10 + .../reandroid/arsc/chunk/xml/ResXmlIDMap.java | 3 + .../reandroid/arsc/container/BlockList.java | 6 + .../reandroid/arsc/container/PackageBody.java | 8 + .../com/reandroid/arsc/item/StringItem.java | 7 + .../com/reandroid/arsc/item/StyleItem.java | 5 +- .../com/reandroid/arsc/pool/StringPool.java | 4 + 14 files changed, 331 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/reandroid/apk/ApkModule.java b/src/main/java/com/reandroid/apk/ApkModule.java index 2a3769a..f829cf3 100644 --- a/src/main/java/com/reandroid/apk/ApkModule.java +++ b/src/main/java/com/reandroid/apk/ApkModule.java @@ -201,7 +201,7 @@ public class ApkModule implements ApkFile { } logVerbose("Dir validated: '"+path+"' -> '"+pathNew+"'"); } - TableStringPool stringPool= getTableBlock().getTableStringPool(); + TableStringPool stringPool= getTableBlock().getStringPool(); stringPool.refreshUniqueIdMap(); getTableBlock().refresh(); } @@ -226,7 +226,7 @@ public class ApkModule implements ApkFile { } logVerbose("Root changed: '"+path+"' -> '"+pathNew+"'"); } - TableStringPool stringPool= getTableBlock().getTableStringPool(); + TableStringPool stringPool= getTableBlock().getStringPool(); stringPool.refreshUniqueIdMap(); getTableBlock().refresh(); } @@ -236,7 +236,7 @@ public class ApkModule implements ApkFile { public List listResFiles(int resourceId, ResConfig resConfig) throws IOException { List results=new ArrayList<>(); TableBlock tableBlock=getTableBlock(); - TableStringPool stringPool= tableBlock.getTableStringPool(); + TableStringPool stringPool= tableBlock.getStringPool(); for(InputSource inputSource:getApkArchive().listInputSources()){ String name=inputSource.getAlias(); StringGroup groupTableString = stringPool.get(name); @@ -274,7 +274,7 @@ public class ApkModule implements ApkFile { } return results; } - public String getPackageName() throws IOException { + public String getPackageName(){ if(hasAndroidManifestBlock()){ return getAndroidManifestBlock().getPackageName(); } @@ -289,7 +289,7 @@ public class ApkModule implements ApkFile { } return pkg.getName(); } - public void setPackageName(String name) throws IOException { + public void setPackageName(String name) { String old=getPackageName(); if(hasAndroidManifestBlock()){ getAndroidManifestBlock().setPackageName(name); @@ -319,6 +319,46 @@ public class ApkModule implements ApkFile { return mTableBlock!=null || getApkArchive().getInputSource(TableBlock.FILE_NAME)!=null; } + public void destroy(){ + getApkArchive().clear(); + AndroidManifestBlock manifestBlock = this.mManifestBlock; + if(manifestBlock!=null){ + manifestBlock.destroy(); + this.mManifestBlock = null; + } + TableBlock tableBlock = this.mTableBlock; + if(tableBlock!=null){ + tableBlock.destroy(); + this.mTableBlock = null; + } + } + public void setManifest(AndroidManifestBlock manifestBlock){ + APKArchive archive = getApkArchive(); + if(manifestBlock==null){ + mManifestBlock = null; + archive.remove(AndroidManifestBlock.FILE_NAME); + return; + } + manifestBlock.setApkFile(this); + BlockInputSource source = + new BlockInputSource<>(AndroidManifestBlock.FILE_NAME, manifestBlock); + archive.add(source); + mManifestBlock = manifestBlock; + } + public void setTableBlock(TableBlock tableBlock){ + APKArchive archive = getApkArchive(); + if(tableBlock==null){ + mTableBlock = null; + archive.remove(TableBlock.FILE_NAME); + return; + } + tableBlock.setApkFile(this); + BlockInputSource source = + new BlockInputSource<>(TableBlock.FILE_NAME, tableBlock); + archive.add(source); + mTableBlock = tableBlock; + } + @Override public AndroidManifestBlock getAndroidManifestBlock() { if(mManifestBlock!=null){ return mManifestBlock; @@ -374,7 +414,7 @@ public class ApkModule implements ApkFile { // loading packages and other chunk blocks for faster and less memory usage public TableStringPool getVolatileTableStringPool() throws IOException{ if(mTableBlock!=null){ - return mTableBlock.getTableStringPool(); + return mTableBlock.getStringPool(); } InputSource inputSource = getApkArchive() .getInputSource(TableBlock.FILE_NAME); @@ -388,7 +428,7 @@ public class ApkModule implements ApkFile { inputStream.close(); return stringPool; } - return getTableBlock().getTableStringPool(); + return getTableBlock().getStringPool(); } TableBlock loadTableBlock() throws IOException { APKArchive archive=getApkArchive(); diff --git a/src/main/java/com/reandroid/apk/FrameworkApk.java b/src/main/java/com/reandroid/apk/FrameworkApk.java index c581267..1c99689 100644 --- a/src/main/java/com/reandroid/apk/FrameworkApk.java +++ b/src/main/java/com/reandroid/apk/FrameworkApk.java @@ -13,47 +13,144 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.reandroid.apk; + package com.reandroid.apk; -import com.reandroid.archive.APKArchive; -import com.reandroid.archive.InputSource; -import com.reandroid.arsc.chunk.TableBlock; -import com.reandroid.arsc.chunk.xml.AndroidManifestBlock; -import com.reandroid.arsc.chunk.xml.ResXmlAttribute; -import com.reandroid.arsc.chunk.xml.ResXmlElement; -import com.reandroid.arsc.util.FrameworkTable; -import com.reandroid.arsc.value.ValueType; + import com.reandroid.archive.APKArchive; + import com.reandroid.archive.ByteInputSource; + import com.reandroid.archive.InputSource; + import com.reandroid.archive.InputSourceUtil; + import com.reandroid.arsc.chunk.PackageBlock; + import com.reandroid.arsc.chunk.TableBlock; + import com.reandroid.arsc.chunk.xml.AndroidManifestBlock; + import com.reandroid.arsc.chunk.xml.ResXmlAttribute; + import com.reandroid.arsc.chunk.xml.ResXmlElement; + import com.reandroid.arsc.util.FrameworkTable; + import com.reandroid.arsc.value.ValueType; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; + import java.io.File; + import java.io.IOException; + import java.io.InputStream; + import java.util.Map; + import java.util.Objects; /* - * Produces compressed framework apk by removing unnecessary files and entries, + * Produces compressed framework apk by removing irrelevant files and entries, * basically it keeps only resources.arsc and AndroidManifest.xml */ -public class FrameworkApk extends ApkModule{ + public class FrameworkApk extends ApkModule{ + private final Object mLock = new Object(); + private int versionCode; + private String versionName; + private String packageName; + private boolean mOptimizing; + private boolean mDestroyed; public FrameworkApk(String moduleName, APKArchive apkArchive) { super(moduleName, apkArchive); + super.setLoadDefaultFramework(false); } public FrameworkApk(APKArchive apkArchive) { this("framework", apkArchive); } - @Override - public APKArchive getApkArchive() { - APKArchive archive=super.getApkArchive(); - clearFiles(archive); - return archive; - } - private void clearFiles(APKArchive archive){ - if(archive.entriesCount()==2){ - return; + + public void destroy(){ + synchronized (mLock){ + this.versionCode = -1; + this.versionName = "-1"; + this.packageName = "destroyed"; + super.destroy(); + this.mDestroyed = true; + } + } + public boolean isDestroyed() { + synchronized (mLock){ + if(!mDestroyed){ + return false; + } + if(hasTableBlock()){ + this.versionCode = 0; + this.versionName = null; + this.packageName = null; + mDestroyed = false; + return false; + } + return true; + } + } + + public int getVersionCode() { + if(this.versionCode == 0){ + initValues(); + } + return this.versionCode; + } + public String getVersionName() { + if(this.versionName == null){ + initValues(); + } + return this.versionName; + } + @Override + public String getPackageName() { + if(this.packageName == null){ + initValues(); + } + return this.packageName; + } + @Override + public void setPackageName(String packageName) { + super.setPackageName(packageName); + this.packageName = null; + } + private void initValues() { + if(hasAndroidManifestBlock()){ + AndroidManifestBlock manifest = getAndroidManifestBlock(); + Integer code = manifest.getVersionCode(); + if(code!=null){ + this.versionCode = code; + } + if(this.versionName == null){ + this.versionName = manifest.getVersionName(); + } + if(this.packageName == null){ + this.packageName = manifest.getPackageName(); + } + } + if(hasTableBlock()){ + FrameworkTable table = getTableBlock(); + if(this.versionCode == 0 && table.isOptimized()){ + int version = table.getVersionCode(); + if(version!=0){ + versionCode = version; + if(this.versionName == null){ + this.versionName = String.valueOf(version); + } + } + } + if(this.packageName == null){ + PackageBlock packageBlock = table.pickOne(); + if(packageBlock!=null){ + this.packageName = packageBlock.getName(); + } + } + } + } + @Override + public void setManifest(AndroidManifestBlock manifestBlock){ + synchronized (mLock){ + super.setManifest(manifestBlock); + this.versionCode = 0; + this.versionName = null; + this.packageName = null; + } + } + @Override + public void setTableBlock(TableBlock tableBlock){ + synchronized (mLock){ + super.setTableBlock(tableBlock); + this.versionCode = 0; + this.versionName = null; + this.packageName = null; } - InputSource tableSource= archive.getInputSource(TableBlock.FILE_NAME); - InputSource manifestSource= archive.getInputSource(AndroidManifestBlock.FILE_NAME); - archive.clear(); - archive.add(tableSource); - archive.add(manifestSource); } @Override public FrameworkTable getTableBlock() { @@ -69,28 +166,60 @@ public class FrameworkApk extends ApkModule{ InputStream inputStream = inputSource.openStream(); FrameworkTable frameworkTable=FrameworkTable.load(inputStream); frameworkTable.setApkFile(this); - if(hasAndroidManifestBlock()){ - optimizeTable(frameworkTable); - } + BlockInputSource blockInputSource=new BlockInputSource<>(inputSource.getName(), frameworkTable); blockInputSource.setMethod(inputSource.getMethod()); blockInputSource.setSort(inputSource.getSort()); archive.add(blockInputSource); return frameworkTable; } - private void optimizeTable(FrameworkTable table) throws IOException { - if(table.isOptimized()){ - return; + public void optimize(){ + synchronized (mLock){ + if(mOptimizing){ + return; + } + if(!hasTableBlock()){ + mOptimizing = false; + return; + } + FrameworkTable frameworkTable = getTableBlock(); + if(frameworkTable.isOptimized()){ + mOptimizing = false; + return; + } + FrameworkOptimizer optimizer = new FrameworkOptimizer(this); + optimizer.optimize(); + mOptimizing = false; } - int prev=table.countBytes(); - logMessage("Optimizing ..."); - AndroidManifestBlock manifestBlock = getAndroidManifestBlock(); - String version=String.valueOf(manifestBlock.getVersionCode()); - String name=manifestBlock.getPackageName(); - table.optimize(name, version); - long diff=prev - table.countBytes(); - long percent=(diff*100L)/prev; - logMessage("Optimized: "+percent+" %"); + } + public String getName(){ + if(isDestroyed()){ + return "destroyed"; + } + String pkg = getPackageName(); + if(pkg==null){ + return ""; + } + return pkg + "-" + getVersionCode(); + } + @Override + public int hashCode(){ + return Objects.hash(getClass(), getName()); + } + @Override + public boolean equals(Object obj){ + if(obj==this){ + return true; + } + if(getClass()!=obj.getClass()){ + return false; + } + FrameworkApk other = (FrameworkApk) obj; + return getName().equals(other.getName()); + } + @Override + public String toString(){ + return getName(); } public static FrameworkApk loadApkFile(File apkFile) throws IOException { APKArchive archive=APKArchive.loadZippedApk(apkFile); @@ -100,7 +229,7 @@ public class FrameworkApk extends ApkModule{ APKArchive archive=APKArchive.loadZippedApk(apkFile); return new FrameworkApk(moduleName, archive); } - public static boolean isFramework(ApkModule apkModule) throws IOException { + public static boolean isFramework(ApkModule apkModule) { if(!apkModule.hasAndroidManifestBlock()){ return false; } @@ -115,4 +244,27 @@ public class FrameworkApk extends ApkModule{ } return attribute.getValueAsBoolean(); } -} + public static FrameworkApk loadApkBuffer(InputStream inputStream) throws IOException{ + return loadApkBuffer("framework", inputStream); + } + public static FrameworkApk loadApkBuffer(String moduleName, InputStream inputStream) throws IOException { + APKArchive archive = new APKArchive(); + FrameworkApk frameworkApk = new FrameworkApk(moduleName, archive); + Map inputSourceMap = InputSourceUtil.mapInputStreamAsBuffer(inputStream); + ByteInputSource source = inputSourceMap.get(TableBlock.FILE_NAME); + FrameworkTable tableBlock = new FrameworkTable(); + if(source!=null){ + tableBlock.readBytes(source.openStream()); + } + frameworkApk.setTableBlock(tableBlock); + + AndroidManifestBlock manifestBlock = new AndroidManifestBlock(); + source = inputSourceMap.get(AndroidManifestBlock.FILE_NAME); + if(source!=null){ + manifestBlock.readBytes(source.openStream()); + } + frameworkApk.setManifest(manifestBlock); + archive.addAll(inputSourceMap.values()); + return frameworkApk; + } + } diff --git a/src/main/java/com/reandroid/arsc/array/PackageArray.java b/src/main/java/com/reandroid/arsc/array/PackageArray.java index 0d6d405..5b69695 100755 --- a/src/main/java/com/reandroid/arsc/array/PackageArray.java +++ b/src/main/java/com/reandroid/arsc/array/PackageArray.java @@ -36,6 +36,14 @@ public class PackageArray extends BlockArray this.mPackageCount=packageCount; mPackageCount.setBlockLoad(this); } + public void destroy(){ + Iterator itr = iterator(true); + while (itr.hasNext()){ + PackageBlock packageBlock=itr.next(); + packageBlock.destroy(); + } + clearChildes(); + } public PackageBlock pickOne(){ PackageBlock[] items=getChildes(); if(items==null||items.length==0){ diff --git a/src/main/java/com/reandroid/arsc/array/StringArray.java b/src/main/java/com/reandroid/arsc/array/StringArray.java index 37140f7..1af2145 100755 --- a/src/main/java/com/reandroid/arsc/array/StringArray.java +++ b/src/main/java/com/reandroid/arsc/array/StringArray.java @@ -51,9 +51,12 @@ public abstract class StringArray extends OffsetBlockArray }; } public List removeUnusedStrings(){ - List allUnused=listUnusedStrings(); - remove(allUnused); - return allUnused; + List unusedList=listUnusedStrings(); + remove(unusedList); + for(T item:unusedList){ + item.onRemoved(); + } + return unusedList; } public List listUnusedStrings(){ List results=new ArrayList<>(); diff --git a/src/main/java/com/reandroid/arsc/array/StyleArray.java b/src/main/java/com/reandroid/arsc/array/StyleArray.java index 6d3d6a7..25350d9 100755 --- a/src/main/java/com/reandroid/arsc/array/StyleArray.java +++ b/src/main/java/com/reandroid/arsc/array/StyleArray.java @@ -31,6 +31,13 @@ public class StyleArray extends OffsetBlockArray implements JSONConve setEndBytes(END_BYTE); } @Override + public void clearChildes(){ + for(StyleItem styleItem:listItems()){ + styleItem.onRemoved(); + } + super.clearChildes(); + } + @Override void refreshEnd4Block(BlockReader reader, ByteArray end4Block) throws IOException { end4Block.clear(); if(reader.available()<4){ diff --git a/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java b/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java index f5578fc..18f60d9 100755 --- a/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java @@ -66,6 +66,14 @@ package com.reandroid.arsc.chunk; addChild(mSpecStringPool); addChild(mBody); } + public void destroy(){ + getEntriesGroupMap().clear(); + getPackageBody().destroy(); + getTypeStringPool().destroy(); + getSpecStringPool().destroy(); + setId(0); + setName(""); + } public Entry getOrCreate(String qualifiers, String type, String name){ ResConfig resConfig = new ResConfig(); resConfig.parseQualifiers(qualifiers); @@ -162,6 +170,9 @@ package com.reandroid.arsc.chunk; public SpecStringPool getSpecStringPool(){ return mSpecStringPool; } + public PackageBody getPackageBody() { + return mBody; + } public SpecTypePairArray getSpecTypePairArray(){ return mBody.getSpecTypePairArray(); } diff --git a/src/main/java/com/reandroid/arsc/chunk/TableBlock.java b/src/main/java/com/reandroid/arsc/chunk/TableBlock.java index 9b0027f..88de6c6 100755 --- a/src/main/java/com/reandroid/arsc/chunk/TableBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/TableBlock.java @@ -38,7 +38,7 @@ import java.util.*; implements MainChunk, JSONConvert, EntryStore { private final TableStringPool mTableStringPool; private final PackageArray mPackageArray; - private final Set mFrameWorks=new HashSet<>(); + private final List mFrameWorks=new ArrayList<>(); private ApkFile mApkFile; public TableBlock() { super(new TableHeader(), 2); @@ -48,6 +48,16 @@ import java.util.*; addChild(mTableStringPool); addChild(mPackageArray); } + public void destroy(){ + getPackageArray().destroy(); + getStringPool().destroy(); + clearFrameworks(); + refresh(); + } + public int countPackages(){ + return getPackageArray().childesCount(); + } + public PackageBlock pickOne(){ return getPackageArray().pickOne(); } @@ -232,7 +242,7 @@ import java.util.*; jsonObject.put(BuildInfo.NAME_arsc_lib_version, BuildInfo.getVersion()); jsonObject.put(NAME_packages, getPackageArray().toJson()); - JSONArray jsonArray = getTableStringPool().toJson(); + JSONArray jsonArray = getStringPool().toJson(); if(jsonArray!=null){ jsonObject.put(NAME_styled_strings, jsonArray); } @@ -247,8 +257,8 @@ import java.util.*; if(tableBlock==null||tableBlock==this){ return; } - if(getPackageArray().childesCount()==0 && getTableStringPool().countStrings()==0){ - getTableStringPool().merge(tableBlock.getTableStringPool()); + if(countPackages()==0 && getStringPool().countStrings()==0){ + getStringPool().merge(tableBlock.getStringPool()); } getPackageArray().merge(tableBlock.getPackageArray()); refresh(); diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java index fc8675f..234ee22 100755 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java @@ -55,6 +55,16 @@ addChild(mResXmlIDMap); addChild(mResXmlElementContainer); } + public void destroy(){ + ResXmlElement root = getResXmlElement(); + if(root!=null){ + root.clearChildes(); + setResXmlElement(null); + } + getResXmlIDMap().destroy(); + getStringPool().destroy(); + refresh(); + } public void setAttributesUnitSize(int size, boolean setToAll){ ResXmlElement root = getResXmlElement(); if(root!=null){ diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlIDMap.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlIDMap.java index cfdb64b..678261c 100755 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlIDMap.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlIDMap.java @@ -31,6 +31,9 @@ this.mResXmlIDArray=new ResXmlIDArray(getHeaderBlock()); addChild(mResXmlIDArray); } + public void destroy(){ + getResXmlIDArray().clearChildes(); + } public ResXmlIDArray getResXmlIDArray(){ return mResXmlIDArray; } diff --git a/src/main/java/com/reandroid/arsc/container/BlockList.java b/src/main/java/com/reandroid/arsc/container/BlockList.java index 7902273..271b7ea 100755 --- a/src/main/java/com/reandroid/arsc/container/BlockList.java +++ b/src/main/java/com/reandroid/arsc/container/BlockList.java @@ -32,6 +32,12 @@ public class BlockList extends Block { super(); mItems=new ArrayList<>(); } + public void clearChildes(){ + ArrayList childList = new ArrayList<>(getChildes()); + for(T child:childList){ + remove(child); + } + } public void sort(Comparator comparator){ mItems.sort(comparator); } diff --git a/src/main/java/com/reandroid/arsc/container/PackageBody.java b/src/main/java/com/reandroid/arsc/container/PackageBody.java index 651f34e..9d653ba 100755 --- a/src/main/java/com/reandroid/arsc/container/PackageBody.java +++ b/src/main/java/com/reandroid/arsc/container/PackageBody.java @@ -50,6 +50,14 @@ public class PackageBody extends FixedBlockContainer { addChild(4, mOverlayablePolicyList); addChild(5, mUnknownChunkList); } + public void destroy(){ + getSpecTypePairArray().clearChildes(); + getLibraryBlock().getLibraryInfoArray().clearChildes(); + getStagedAliasList().clearChildes(); + getOverlayableList().clearChildes(); + getOverlayablePolicyList().clearChildes(); + getUnknownChunkList().clearChildes(); + } public OverlayableList getOverlayableList() { return mOverlayableList; } diff --git a/src/main/java/com/reandroid/arsc/item/StringItem.java b/src/main/java/com/reandroid/arsc/item/StringItem.java index 4231e91..04024c6 100755 --- a/src/main/java/com/reandroid/arsc/item/StringItem.java +++ b/src/main/java/com/reandroid/arsc/item/StringItem.java @@ -80,6 +80,13 @@ public class StringItem extends BlockItem implements JSONConvert { ref.set(newIndex); } } + public void onRemoved(){ + StyleItem style = getStyle(); + if(style!=null){ + style.onRemoved(); + } + setParent(null); + } @Override public void onIndexChanged(int oldIndex, int newIndex){ reUpdateReferences(newIndex); diff --git a/src/main/java/com/reandroid/arsc/item/StyleItem.java b/src/main/java/com/reandroid/arsc/item/StyleItem.java index 4e6ce91..524bbcf 100755 --- a/src/main/java/com/reandroid/arsc/item/StyleItem.java +++ b/src/main/java/com/reandroid/arsc/item/StyleItem.java @@ -15,7 +15,6 @@ */ package com.reandroid.arsc.item; -import com.reandroid.arsc.base.Block; import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.model.StyleSpanInfo; import com.reandroid.arsc.pool.StringPool; @@ -33,8 +32,10 @@ public class StyleItem extends IntegerArray implements JSONConvert { super(); this.mReferences = new HashSet<>(); } - void onRemoved(){ + public void onRemoved(){ setStylePieceCount(0); + mSpanInfoList = null; + setParent(null); } public void onDataLoaded(){ linkAll(); diff --git a/src/main/java/com/reandroid/arsc/pool/StringPool.java b/src/main/java/com/reandroid/arsc/pool/StringPool.java index f8436a3..6145b87 100755 --- a/src/main/java/com/reandroid/arsc/pool/StringPool.java +++ b/src/main/java/com/reandroid/arsc/pool/StringPool.java @@ -68,6 +68,10 @@ package com.reandroid.arsc.pool; mUniqueMap = new HashMap<>(); } + public void destroy(){ + getStyleArray().clearChildes(); + getStringsArray().clearChildes(); + } public List toStringList(){ return getStringsArray().toStringList(); }