diff --git a/README.md b/README.md index af7bee1..d9a1566 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ transferee 可以帮助你完成从缩略视图到原视图的无缝过渡转变 # Sample [demo.apk](https://github.com/Hitomis/transferee/tree/master/preview/app-release.apk) + + # Dependency step1. @@ -111,6 +113,11 @@ step 3: 显示 transferee transferee.apply(config).show(); ``` +step 4: 离开页面的时候需要销毁 transferee 中的资源,防止内存泄漏 (建议写在 onDestroy 方法中) +``` +transferee.destroy() +``` + # Config | 属性 | 说明 | | :--: | :--: | @@ -150,6 +157,7 @@ transferee.apply(config).show(); | isShown() | transferee 是否显示 | | dismiss() | 关闭 transferee | | clear() | 清除图片和视频等所有缓存文件 | +| destroy() | 销毁 transferee 使用到的资源, 防止内存泄漏 | | getImageFile(url) | 获取与 url 对应的缓存图片 | | setOnTransfereeStateChangeListener(listener) | 设置 transferee 显示/关闭状态改变的监听器 | @@ -164,6 +172,8 @@ transferee.apply(config).show(); - 修复打开和关闭的状态不能保持一致的 bug - 下滑手势优化 - 重置不再当前显示区域的图片状态 + - 优化了内存占用,当浏览多图相册时,保证内存稳定 + - 解决了因为 Config 资源未回收而导致的内存泄漏问题 + v1.6.0 - 新增视频播放以及视频配套功能的支持 diff --git a/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferAdapter.java b/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferAdapter.java index 72d3a52..053365a 100644 --- a/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferAdapter.java +++ b/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferAdapter.java @@ -11,8 +11,8 @@ import androidx.annotation.NonNull; import androidx.viewpager.widget.PagerAdapter; -import com.hitomi.tilibrary.view.video.ExoVideoView; import com.hitomi.tilibrary.view.image.TransferImage; +import com.hitomi.tilibrary.view.video.ExoVideoView; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; @@ -25,7 +25,6 @@ * email: 196425254@qq.com */ class TransferAdapter extends PagerAdapter { - private TransferLayout transfer; private int showIndex; private int imageSize; @@ -38,8 +37,7 @@ class TransferAdapter extends PagerAdapter { this.imageSize = imageSize; this.showIndex = nowThumbnailIndex + 1 == imageSize ? nowThumbnailIndex - 1 : nowThumbnailIndex + 1; - this.showIndex = showIndex < 0 ? 0 : showIndex; - + this.showIndex = Math.max(showIndex, 0); containLayoutArray = new SparseArray<>(); } @@ -56,46 +54,8 @@ public boolean isViewFromObject(View view, Object object) { @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); - } - - /** - * 获取指定索引页面中的 TransferImage - * - * @param position - * @return - */ - TransferImage getImageItem(int position) { - FrameLayout parentLayout = containLayoutArray.get(position); - if (parentLayout != null && parentLayout.getChildAt(0) instanceof TransferImage) { - return ((TransferImage) parentLayout.getChildAt(0)); - } - return null; - } - - /** - * 获取指定页面中的 ExoVideoView - * - * @param position - * @return - */ - ExoVideoView getVideoItem(int position) { - FrameLayout parentLayout = containLayoutArray.get(position); - if (parentLayout != null && parentLayout.getChildAt(0) instanceof ExoVideoView) { - return ((ExoVideoView) parentLayout.getChildAt(0)); - } - return null; - } - - SparseArray getCacheItems() { - return containLayoutArray; - } - - FrameLayout getParentItem(int position) { - return containLayoutArray.get(position); - } - - void setOnInstantListener(OnInstantiateItemListener listener) { - this.onInstantListener = listener; + containLayoutArray.remove(position); + transfer.loadedIndexSet.remove(position); } @NonNull @@ -103,16 +63,15 @@ void setOnInstantListener(OnInstantiateItemListener listener) { public Object instantiateItem(@NonNull ViewGroup container, int position) { // ViewPager instantiateItem 顺序:按 position 递减 OffscreenPageLimit, // 再从 position 递增 OffscreenPageLimit 的次序创建页面 - FrameLayout parentLayout = containLayoutArray.get(position); + FrameLayout parentLayout = containLayoutArray.get(position); if (parentLayout == null) { parentLayout = newParentLayout(container, position); - containLayoutArray.put(position, parentLayout); + containLayoutArray.append(position, parentLayout); if (position == showIndex && onInstantListener != null) onInstantListener.onComplete(); } - container.addView(parentLayout); return parentLayout; } @@ -147,6 +106,46 @@ private FrameLayout newParentLayout(ViewGroup container, final int pos) { return parentLayout; } + /** + * 获取指定索引页面中的 TransferImage + * + * @param position + * @return + */ + TransferImage getImageItem(int position) { + FrameLayout parentLayout = containLayoutArray.get(position); + if (parentLayout != null && parentLayout.getChildAt(0) instanceof TransferImage) { + return ((TransferImage) parentLayout.getChildAt(0)); + } + return null; + } + + /** + * 获取指定页面中的 ExoVideoView + * + * @param position + * @return + */ + ExoVideoView getVideoItem(int position) { + FrameLayout parentLayout = containLayoutArray.get(position); + if (parentLayout != null && parentLayout.getChildAt(0) instanceof ExoVideoView) { + return ((ExoVideoView) parentLayout.getChildAt(0)); + } + return null; + } + + SparseArray getCacheItems() { + return containLayoutArray; + } + + FrameLayout getParentItem(int position) { + return containLayoutArray.get(position); + } + + void setOnInstantListener(OnInstantiateItemListener listener) { + this.onInstantListener = listener; + } + interface OnInstantiateItemListener { void onComplete(); } diff --git a/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferConfig.java b/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferConfig.java index 4ec661f..1ec05e0 100644 --- a/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferConfig.java +++ b/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferConfig.java @@ -216,10 +216,6 @@ public void setSourceUrlList(List sourceUrlList) { this.sourceUrlList = sourceUrlList; } - public List getSourceUriList() { - return sourceUriList; - } - public void setSourceUriList(List sourceUriList) { this.sourceUriList = sourceUriList; } @@ -333,6 +329,21 @@ public void setFooterSize(int footerSize) { this.footerSize = footerSize; } + public void destroy() { + setImageView(null); + setCustomView(null); + setListView(null); + setRecyclerView(null); + setProgressIndicator(null); + setIndexIndicator(null); + setImageLoader(null); + setOriginImageList(null); + setSourceUrlList(null); + setSourceUriList(null); + setMissDrawable(null); + setErrorDrawable(null); + } + public static class Builder { private int nowThumbnailIndex; private int offscreenPageLimit; @@ -517,14 +528,6 @@ public Builder setSourceUriList(List sourceUriList) { return this; } -// /** -// * 缩略图地址集合 -// */ -// public Builder setThumbnailImageList(List thumbnailImageList) { -// this.thumbnailImageList = thumbnailImageList; -// return this; -// } - /** * 过渡前原始的 ImageView 集合 */ diff --git a/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferLayout.java b/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferLayout.java index d74a280..3658e15 100644 --- a/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferLayout.java +++ b/Transferee/src/main/java/com/hitomi/tilibrary/transfer/TransferLayout.java @@ -43,11 +43,11 @@ class TransferLayout extends FrameLayout { private TransferChangeListener transChangeListener; private OnLayoutResetListener layoutResetListener; - private Set loadedIndexSet; TransferImage transImage; TransferAdapter transAdapter; ViewPager transViewPager; + Set loadedIndexSet; float alpha; // [0.f , 255.f] boolean isAnimationRunning; diff --git a/Transferee/src/main/java/com/hitomi/tilibrary/transfer/Transferee.java b/Transferee/src/main/java/com/hitomi/tilibrary/transfer/Transferee.java index 3a7383c..f765a2a 100644 --- a/Transferee/src/main/java/com/hitomi/tilibrary/transfer/Transferee.java +++ b/Transferee/src/main/java/com/hitomi/tilibrary/transfer/Transferee.java @@ -248,6 +248,16 @@ public void setOnTransfereeStateChangeListener(OnTransfereeStateChangeListener l transListener = listener; } + /** + * 资源销毁,防止内存泄漏 + */ + public void destroy() { + if (transConfig != null) { + transConfig.destroy(); + transConfig = null; + } + } + /** * Transferee 显示的时候调用 {@link OnTransfereeStateChangeListener#onShow()} *

diff --git a/app/build.gradle b/app/build.gradle index 36706f3..1d9bd89 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -51,4 +51,5 @@ dependencies { implementation libGlide implementation libPicasso implementation libImmersionbar + debugImplementation libLeakcanary } diff --git a/app/src/main/java/com/hitomi/transferimage/activity/BaseActivity.java b/app/src/main/java/com/hitomi/transferimage/activity/BaseActivity.java index e5fcbf2..39651dd 100644 --- a/app/src/main/java/com/hitomi/transferimage/activity/BaseActivity.java +++ b/app/src/main/java/com/hitomi/transferimage/activity/BaseActivity.java @@ -43,6 +43,12 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { testTransferee(); } + @Override + protected void onDestroy() { + super.onDestroy(); + transferee.destroy(); + } + @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode != WRITE_EXTERNAL_STORAGE) { diff --git a/app/src/main/java/com/hitomi/transferimage/activity/LocalImageActivity.java b/app/src/main/java/com/hitomi/transferimage/activity/LocalImageActivity.java index a9423f2..59df029 100644 --- a/app/src/main/java/com/hitomi/transferimage/activity/LocalImageActivity.java +++ b/app/src/main/java/com/hitomi/transferimage/activity/LocalImageActivity.java @@ -13,8 +13,8 @@ import com.hitomi.tilibrary.style.index.NumberIndexIndicator; import com.hitomi.tilibrary.style.progress.ProgressBarIndicator; import com.hitomi.tilibrary.transfer.TransferConfig; -import com.hitomi.transferimage.SourceConfig; import com.hitomi.transferimage.R; +import com.hitomi.transferimage.SourceConfig; import com.vansz.glideimageloader.GlideImageLoader; import com.zhy.adapter.abslistview.CommonAdapter; import com.zhy.adapter.abslistview.ViewHolder; diff --git a/build.gradle b/build.gradle index a10b91f..e16a97e 100644 --- a/build.gradle +++ b/build.gradle @@ -49,6 +49,7 @@ project.ext { libBaseAdapter = "com.zhy:base-adapter:3.0.3" libRecyclerviewAdpater = "com.zhy:base-rvadapter:3.0.3" libImmersionbar = "com.gyf.immersionbar:immersionbar:3.0.0" + libLeakcanary = "com.squareup.leakcanary:leakcanary-android:2.3" // Transferee 核心库所依赖项目 libAppcompat = "androidx.appcompat:appcompat:1.1.0" libSupportRecyclerview = "androidx.recyclerview:recyclerview:1.0.0" @@ -56,6 +57,6 @@ project.ext { libExoExtensionRtmp = "com.google.android.exoplayer:extension-rtmp:2.10.4" libProgresspieview = "com.github.filippudak.progresspieview:library:1.0.4" libGifDrawable = "pl.droidsonroids.gif:android-gif-drawable:1.2.19" - libImmersionbar ="com.gyf.immersionbar:immersionbar:3.0.0" + libImmersionbar = "com.gyf.immersionbar:immersionbar:3.0.0" libLuban = "top.zibin:Luban:1.1.8" } diff --git a/preview/app-release.apk b/preview/app-release.apk index 591b9b3..9da7047 100644 Binary files a/preview/app-release.apk and b/preview/app-release.apk differ diff --git a/preview/memory.png b/preview/memory.png new file mode 100644 index 0000000..d92a8aa Binary files /dev/null and b/preview/memory.png differ