gpt4 book ai didi

android - 通过 onPreDrawListener 将按比例缩小的位图放入 fragment 时创建无限循环

转载 作者:太空狗 更新时间:2023-10-29 14:20:49 25 4
gpt4 key购买 nike

图库 Activity :

==================
TextView (tv)
------------------
| tv | tv | tv |
------------------
GalleryFragment: dynamically created; replaces FrameLayout
FrameLayout: W&H: match_parent


imageView: W&H are match_parent; scaleType: fitCenter;
layout_below: the tv's above;
layout_above: the TextView below;
result: imageView fits snuggly between.
Parent: RelativeLayout W&H: match_parent


------------------
TextView
==================

图库 Activity 描述:此 Activity 一次显示一个属于特定集合的图像。用户点击图片:新 fragment 显示下一张图片。

几天来我一直在思考如何:

  • A.获取 imageView 的大小,以便我可以适本地缩放位图以适合。
  • B.现在我发生了一个无限循环。而且我想我知道为什么,我的意思是从逻辑上讲,当我将位图填充到 imageView 中时,它可能再次触发 onPreDraw() 然后我的代码就开始了。 ...但我不知道如何修复它。
  • C.我认为 synchronization 可能是答案,但我以前从未使用过它,而且我认为我没有正确使用它。
  • D.我想也许放一个 if(workerThread == null) 检查可能会起作用……但它只会暂时减慢它的速度。

此时我迷路了。我不知道如何获取隐藏在动态添加的 fragment 中的 ImageView 的尺寸, 使用这些尺寸缩小位图,然后在调整大小后将该位图加载到 fragment 的 ImageView 中。 p>

如果您需要任何说明,请询问。

下面包含 GalleryFragment 的 onCreateView 和 BitmapWorkerTask 的代码。然后下面是我过滤的 logcat 的粘贴。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflate view
View view = inflater.inflate(R.layout.frag_gallery_image, container, false);

// get view handles
imageView = (ImageView)view.findViewById(R.id.gallery_image);

// TESTING
ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new OnPreDrawListener() {

@Override
public boolean onPreDraw() {
// TESTING
viewWidth = imageView.getMeasuredWidth();
viewHeight = imageView.getMeasuredHeight();

Log.d(TAG, SCOPE +"onPreDraw viewWidth: " +viewWidth +", viewHeight: " +viewHeight);

// TESTING: Added because "synchronization" attempt didn't work
if(bmwt == null){
loadImage(viewWidth, viewHeight);
}

return true;
}
});

// set view actions
imageView.setOnClickListener(GalleryFragment.this);

return view;
}

/**
* A synchronized method for loading bitmaps in background thread.
* Synchronization: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
* ...something isn't working as intended...
*/
private synchronized void loadImage(int viewWidth, int viewHeight){
// TESTING
Log.d(TAG, SCOPE +"loadImage viewWidth: " +viewWidth +", viewHeight: " +viewHeight);

bmwt = new BitmapWorkerTask(imageView, viewWidth, viewHeight);
bmwt.execute(imageUri);
}


/**
* BitmapWorkerTask is a subclass of Asynctask for the purpose of loading
* images off of the UI thread.
*/
private class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap>{
private String uri;
private int imageViewWidth;
private int imageViewHeight;

// Constructor.
public BitmapWorkerTask(ImageView imageView, int width, int height){
imageViewWidth = width;
imageViewHeight = height;
}

// Decode image in background.
@Override
protected Bitmap doInBackground(String... params) {
uri = params[0];
final Bitmap bitmap = ImageUtils.decodeSampledBitmapFromUri(uri, imageViewWidth, imageViewHeight);

return bitmap;
}

@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null; // use some default bitmap
}
if (bitmap != null) {
Log.d(TAG, SCOPE +"bitmap kilobyte count: "+ bitmap.getByteCount() / 1024);

imageView.setImageBitmap(bitmap);

// make BitmapWorkerTask reference null again.
bmwt = null;
}// else do nothing.
}
}

日志。注意“位图千字节计数”在 asyncTask 的 onPostExecute 中被调用。...这是我希望日志记录停止的地方。

06-13 01:50:41.442: D/ROSS(12982): GalleryFragment: imageUri: /mnt/sdcard/So so so beautiful.jpg
06-13 01:50:41.522: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:41.522: D/ROSS(12982): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 01:50:41.632: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:41.827: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:43.053: D/ROSS(12982): GalleryFragment: bitmap kilobyte count: 1183
06-13 01:50:43.142: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:43.142: D/ROSS(12982): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 01:50:43.632: D/ROSS(12982): GalleryFragment: bitmap kilobyte count: 1183
06-13 01:50:43.713: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:43.713: D/ROSS(12982): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 01:50:44.023: D/ROSS(12982): GalleryFragment: bitmap kilobyte count: 1183
06-13 01:50:44.101: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:44.101: D/ROSS(12982): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 01:50:44.332: D/ROSS(12982): GalleryFragment: bitmap kilobyte count: 1183
06-13 01:50:44.414: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:44.414: D/ROSS(12982): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 01:50:44.681: D/ROSS(12982): GalleryFragment: bitmap kilobyte count: 1183
06-13 01:50:44.761: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:44.761: D/ROSS(12982): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 01:50:45.151: D/ROSS(12982): GalleryFragment: bitmap kilobyte count: 1183
06-13 01:50:45.227: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:45.231: D/ROSS(12982): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 01:50:45.521: D/ROSS(12982): GalleryFragment: bitmap kilobyte count: 1183
06-13 01:50:45.593: D/ROSS(12982): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 01:50:45.593: D/ROSS(12982): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 01:50:45.962: D/ROSS(12982): GalleryFragment: bitmap kilobyte count: 1183

编辑:

在实现 Nicholas 的建议后,这里是 logcat 的总和:

06-13 14:51:44.976: D/ROSS(15465): GalleryFragment: imageUri: /mnt/sdcard/RossAndClay - Copy (12).JPG
06-13 14:51:45.146: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:51:45.146: D/ROSS(15465): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 14:51:45.376: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:51:45.422: D/ROSS(15465): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 14:51:45.626: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:51:45.626: D/ROSS(15465): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 14:51:49.336: D/ROSS(15465): GalleryFragment: bitmap kilobyte count: 1183
06-13 14:51:49.356: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:51:51.327: D/ROSS(15465): GalleryFragment: bitmap kilobyte count: 1183
06-13 14:51:51.336: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:51:53.395: D/ROSS(15465): GalleryFragment: bitmap kilobyte count: 1183
06-13 14:51:53.469: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692

点击图片后,在 fragment 中,这是该事件的总 logcat:

06-13 14:54:41.315: D/ROSS(15465): GalleryFragment: imageUri: /mnt/sdcard/RossAndClay - Copy (11).JPG
06-13 14:54:41.402: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:54:41.406: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:54:41.406: D/ROSS(15465): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 14:54:41.655: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:54:41.665: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:54:41.665: D/ROSS(15465): GalleryFragment: loadImage viewWidth: 480, viewHeight: 692
06-13 14:54:44.285: D/ROSS(15465): GalleryFragment: bitmap kilobyte count: 1183
06-13 14:54:44.305: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:54:44.305: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:54:46.965: D/ROSS(15465): GalleryFragment: bitmap kilobyte count: 1183
06-13 14:54:47.036: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692
06-13 14:54:47.036: D/ROSS(15465): GalleryFragment: onPreDraw viewWidth: 480, viewHeight: 692

每次单击图像时,logcat 中的条目数都会越来越长。我的 fragment 交易看起来像:

/*
* Create the fragment that holds the collection image.
* @param imageUri
*/
private void createImageFragment(String imageUri) {
// With each click wipe previous entry, ie: there's no going back.
getFragmentManager().popBackStack();

// create new fragment
GalleryFragment galleryFrag = GalleryFragment.newInstance(imageUri);

// programmatically add new fragment
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.gallery_imageFrame, galleryFrag, GALLERY_FRAG);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}

在我写下这篇文章的那一刻,我尝试将 popBackStack() 更改为 popBackStackImmediate(),这阻止了不断增长的 logcat 条目列表。 现在,在完成加载各种图像尺寸的一些测试之后,看起来图像的大小决定了调用 loadImage() 的次数,这是有道理的(尽管我想阻止这种情况发生)因为(例如) 在实际设置 imageView 的图像之前会触发三个异步任务。所以现在的任务是弄清楚如何确保 loadImage() 只被调用一次。

编辑 2:

有时,一个特定的问题会使我们的大脑冻干。简单地使用类字段 private boolean thisMethodCalled = false; 和 onPreDraw:

解决了对该方法的多次调用
            if(!thisMethodCalled){
loadImage(viewWidth, viewHeight);
thisMethodCalled = true;
}

...虽然这不会阻止 onPreDraw 在每次 fragment 替换时被调用的次数越来越多,但我不确定我能做些什么。

最终编辑 - 最佳解决方案:

this answer 中的一条评论中收集到的概念,只需使用 imageView.getViewTreeObserver().removeOnPreDrawListener(this); 移除靠近末尾的监听器,没有监听器,没有多次调用的方法;显然没有额外的 onPreDraw() 调用。最后,完全按照我的预期工作。

    ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new OnPreDrawListener() {

@Override
public boolean onPreDraw() {
// TESTING
viewWidth = imageView.getMeasuredWidth();
viewHeight = imageView.getMeasuredHeight();

loadImage(viewWidth, viewHeight);

imageView.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});

最佳答案

也许可以尝试将 ImageView 标签设置为 false 或 true。真正的意思是它已经在绘制了。它可能会工作,但不确定它如何处理您的应用程序。

然后你可以有类似的东西

imageView = (ImageView)view.findViewById(R.id.gallery_image);
// we have not loaded the image yet
imageView.setTag(false);

然后在你的预抽中

boolean hasLoaded = ((Boolean) imageView.getTag());
// if we have not loaded the image yet
// we want to load it
if(!hasLoaded){
loadImage(viewWidth, viewHeight);
}

然后在后期执行

    if (bitmap != null) {
Log.d(TAG, SCOPE +"bitmap kilobyte count: "+ bitmap.getByteCount() / 1024);
// we succesfully loaded bitmap
imageView.setTag(true);
imageView.setImageBitmap(bitmap);

// make BitmapWorkerTask reference null again.
bmwt = null;
}

编辑:只是修复了一些代码以使其更易于阅读

关于android - 通过 onPreDrawListener 将按比例缩小的位图放入 fragment 时创建无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17078301/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com