Android中如何在Activity间传递ZipEntry类型的ArrayList?
解决Activity间传递ZipEntry列表的问题
问题原因
java.util.zip.ZipEntry 虽实现了 Serializable 接口,但它的内部实现和所属的 ZipFile 强绑定,通过 Intent 传递时,系统的 Parcel 序列化机制无法正确处理它的某些内部属性,因此抛出类型未知的异常。
可行解决方案
1. 封装ZipEntry核心信息为自定义Parcelable类
提取ZipEntry中你需要的关键属性(如文件名、大小、是否为目录等),封装成实现Parcelable的自定义类,传递这个类的列表:
// 自定义Parcelable类,存储ZipEntry核心信息 data class ZipEntryInfo( val name: String, val size: Long, val compressedSize: Long, val isDirectory: Boolean ) : Parcelable { constructor(parcel: Parcel) : this( parcel.readString() ?: "", parcel.readLong(), parcel.readLong(), parcel.readByte() != 0.toByte() ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeString(name) parcel.writeLong(size) parcel.writeLong(compressedSize) parcel.writeByte(if (isDirectory) 1 else 0) } override fun describeContents(): Int { return 0 } companion object CREATOR : Parcelable.Creator<ZipEntryInfo> { override fun createFromParcel(parcel: Parcel): ZipEntryInfo { return ZipEntryInfo(parcel) } override fun newArray(size: Int): Array<ZipEntryInfo?> { return arrayOfNulls(size) } } }
传递时转换列表:
// 将原ZipEntry列表转为自定义类列表 val entryInfoList = languageListAdapter.selectedItems.map { entry -> ZipEntryInfo( entry.name, entry.size, entry.compressedSize, entry.isDirectory ) } // 传递到目标Activity val newActIntent = Intent(this, InstallActivity::class.java) newActIntent.putParcelableArrayListExtra("zip_entries", ArrayList(entryInfoList)) startActivity(newActIntent)
目标Activity接收:
val entryInfoList = intent.getParcelableArrayListExtra<ZipEntryInfo>("zip_entries") // 如需原ZipEntry,可结合ZipFile重新获取
2. 传递Zip文件路径与选中文件名列表
如果所有ZipEntry来自同一个ZipFile,直接传递Zip文件路径和选中的ZipEntry名称列表,在目标Activity中重新打开ZipFile获取对应Entry:
传递时:
// 假设你已有Zip文件的本地路径 val zipFilePath = "/path/to/your/target.zip" val selectedEntryNames = languageListAdapter.selectedItems.map { it.name } val newActIntent = Intent(this, InstallActivity::class.java) newActIntent.putExtra("zip_file_path", zipFilePath) newActIntent.putStringArrayListExtra("selected_entry_names", ArrayList(selectedEntryNames)) startActivity(newActIntent)
目标Activity接收并获取ZipEntry:
val zipFilePath = intent.getStringExtra("zip_file_path") ?: return val selectedEntryNames = intent.getStringArrayListExtra("selected_entry_names") ?: return ZipFile(zipFilePath).use { zipFile -> val selectedEntries = selectedEntryNames.mapNotNull { name -> zipFile.getEntry(name) } // 使用获取到的selectedEntries }
3. 全局单例暂存列表
如果两个Activity在同一进程内,可用单例类暂存列表,跳过序列化传递:
// 单例暂存类 object TempDataHolder { var selectedZipEntries: List<ZipEntry>? = null }
传递前暂存:
TempDataHolder.selectedZipEntries = languageListAdapter.selectedItems val newActIntent = Intent(this, InstallActivity::class.java) startActivity(newActIntent)
目标Activity获取:
val selectedEntries = TempDataHolder.selectedZipEntries // 使用完成后清空数据,避免内存泄漏 TempDataHolder.selectedZipEntries = null
注意:此方法仅适用于同一进程内的Activity跳转,且务必在使用后清空暂存数据,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Nishant Bhandari
相关产品推荐
相关产品推荐

