Android开发中getImageMatrix()在早期生命周期返回错误Matrix问题求助
问题原因
为什么早期生命周期拿不到正确的Matrix
Android的View渲染分为三个核心步骤:measure(测量尺寸)、layout(确定位置)、draw(绘制内容)。onCreate、onStart、onResume都属于Activity的早期生命周期,此时View树还没完成完整的测量和布局流程,ImageView的宽高还没有最终确定。
而ImageView的getImageMatrix()返回的矩阵是用来实现图片的缩放、平移适配的,它需要基于ImageView自身的最终尺寸、加载的图片尺寸、设置的scaleType三个参数计算得出。在View还没完成测量时,矩阵还没被计算赋值,只会返回默认的单位矩阵。
为什么onCreateOptionsMenu中返回正确
onCreateOptionsMenu的调用时机晚于View树的首次布局完成时间:Android系统会在Activity完成onResume回调、且View树完成首次测量布局之后,才会调用onCreateOptionsMenu加载选项菜单。此时ImageView已经完成了尺寸计算,内部的缩放矩阵已经被正确赋值,所以能拿到预期的结果。
现有实现的问题
你将依赖ImageView绘制属性的逻辑放在了View还没完成初始化的生命周期节点,调用时机不符合依赖条件。虽然放在onCreateOptionsMenu可以临时解决问题,但这个方法本身是用来加载选项菜单的,和图片处理逻辑无关,属于不规范的实现,后续如果菜单逻辑改动很容易连带影响图片处理功能。
规范解决方案
推荐使用以下任意一种方式来确保逻辑在View布局完成后执行:
方案1:监听View布局变化
给ImageView添加一次性的布局监听,布局完成后自动执行逻辑:
mSelectionImageView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { // 移除监听,避免后续布局变化重复触发 v.removeOnLayoutChangeListener(this); // 在这里执行你的图片加载、边缘检测、坐标转换逻辑 if(getIntent().hasExtra("picture")) { try { mBitmap = BitmapFactory.decodeFile(getIntent().getStringExtra("picture")); mSelectionImageView.setImageBitmap(mMyOpenCVWrapper.getResizedBitmap(mBitmap, MAX_HEIGHT)); List<PointF> points = mMyOpenCVWrapper.findPoints(mBitmap); mSelectionImageView.setPoints(points); } catch (Exception e) { e.printStackTrace(); } } } });
方案2:通过post延迟执行
将逻辑抛到主线程消息队列末尾,等View初始化流程完成后自动执行:
// 在onCreate中直接调用即可 mSelectionImageView.post(new Runnable() { @Override public void run() { // 在这里执行你的图片处理逻辑 } });
内容的提问来源于stack exchange,提问作者user3356013

