当前位置: 首页 > news >正文

做红包网站开发网站现实网络传输失败

做红包网站,开发网站现实网络传输失败,网站后台不显示,江苏专业做网站的公司哪家好一、说明#xff1a; 基于之前的了解知道ui的绘制最终会走到Android的ViewRootImpl中scheduleTraversals进行发送接收vsync信号绘制#xff0c;在ViewRootImpl中还会进行主线程检测#xff0c;也就是我们所谓子线程更新ui会抛出异常。 像我们常用的刷新ui#xff0c;inval…一、说明 基于之前的了解知道ui的绘制最终会走到Android的ViewRootImpl中scheduleTraversals进行发送接收vsync信号绘制在ViewRootImpl中还会进行主线程检测也就是我们所谓子线程更新ui会抛出异常。 像我们常用的刷新uiinvalidate 和 requestLayout方法按我之前的理解在ViewRootImpl初始化添加后在子线程中刷新ui一定会崩溃如下图 二、问题invalidate一定会导致异常崩溃 2.1、例子子线程更新TextView文本注意这里是TextView为什么是它而不是ImageView,因为我的背景就是使用的TextView使用它的时候发现了invalidate 和 requestLayout方法的区别 某天我在onResume中利用子线程更新了TextView的一段代码,发现并没有抛出异常崩溃代码如下 override fun onResume() {super.onResume()mBind.btTest.setOnClickListener{lifecycleScope.launch(Dispatchers.IO) {mBind.btTest.text 子线程点击改变${Thread.currentThread().name}}}}我在想为什么呢看代码 一步步debugTextView控件中 1.、 public final void setText(CharSequence text) {setText(text, mBufferType); } 2.、 public void setText(CharSequence text, BufferType type) {setText(text, type, true, 0);if (mCharWrapper ! null) {mCharWrapper.mChars null;} } 3.、 private void setText(CharSequence text, BufferType type,boolean notifyBefore, int oldlen) {...省略if (mLayout ! null) {checkForRelayout();}...省略}以上主要看第三步中的 checkForRelayout()检测是否需要重绘方法如下 UnsupportedAppUsage private void checkForRelayout() {// If we have a fixed width, we can just swap in a new text layout// if the text height stays the same or if the view height is fixed.if ((mLayoutParams.width ! LayoutParams.WRAP_CONTENT|| (mMaxWidthMode mMinWidthMode mMaxWidth mMinWidth)) (mHint null || mHintLayout ! null) (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight() 0)) {// Static width, so try making a new text layout.int oldht mLayout.getHeight();int want mLayout.getWidth();int hintWant mHintLayout null ? 0 : mHintLayout.getWidth();/** No need to bring the text into view, since the size is not* changing (unless we do the requestLayout(), in which case it* will happen at measure).*/makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),false);//1.检测文本的显示类型就是我们的过长省略号这种if (mEllipsize ! TextUtils.TruncateAt.MARQUEE) {// In a fixed-height view, so use our new text layout.if (mLayoutParams.height ! LayoutParams.WRAP_CONTENT mLayoutParams.height ! LayoutParams.MATCH_PARENT) {autoSizeText();invalidate();return;}// Dynamic height, but height has stayed the same,// so use our new text layout.if (mLayout.getHeight() oldht (mHintLayout null || mHintLayout.getHeight() oldht)) {autoSizeText();invalidate();return;}}// We lose: the height has changed and we have a dynamic height.// Request a new view layout using our new text layout.requestLayout();invalidate();} else {// Dynamic width, so we have no choice but to request a new// view layout with a new text layout.nullLayouts();requestLayout();invalidate();} }从上面的checkForRelayout()方法中的if (mEllipsize ! TextUtils.TruncateAt.MARQUEE)条件知道成立因为我们没有设置过mEllipsize 跑马灯效果所以走了invalidate()方法然后直接return截断,不会走后面的requestLayout()方法至于requestLayout() 与 invalidate()的区别我就不讲了 2.2、分析requestLayout方法 基于之前的知识我知道调用requestLayout()方法会崩溃,至于为什么调用requestLayout()方法会崩溃 我们先看requestLayout()方法,暂停一会invalidate()的跟进 requestLayout()方法代码如下 public void requestLayout() {if (mMeasureCache ! null) mMeasureCache.clear();if (mAttachInfo ! null mAttachInfo.mViewRequestingLayout null) {// Only trigger request-during-layout logic if this is the view requesting it,// not the views in its parent hierarchyViewRootImpl viewRoot getViewRootImpl();if (viewRoot ! null viewRoot.isInLayout()) {if (!viewRoot.requestLayoutDuringLayout(this)) {return;}}mAttachInfo.mViewRequestingLayout this;}mPrivateFlags | PFLAG_FORCE_LAYOUT;mPrivateFlags | PFLAG_INVALIDATED;if (mParent ! null !mParent.isLayoutRequested()) {mParent.requestLayout();}if (mAttachInfo ! null mAttachInfo.mViewRequestingLayout this) {mAttachInfo.mViewRequestingLayout null;} }requestLayout()方法中会循环递归调用 mParent.requestLayout()方法直到找到ViewRootImpl中的requestLayout()方法,而它的方法做了线程检测如下图这就是requestLayout()方法会崩溃的原因。 验证猜想 为TextView设置跑马灯属性使上面的if (mEllipsize ! TextUtils.TruncateAt.MARQUEE)不成立走下面的requestLayout()方法代码如下 override fun onResume() {super.onResume()mBind.btTest.ellipsize TextUtils.TruncateAt.valueOf(MARQUEE)mBind.btTest.setOnClickListener{lifecycleScope.launch(Dispatchers.IO) {mBind.btTest.text 子线程点击改变${Thread.currentThread().name}}}}果然点击后崩溃 2.3、继续分析invalidate()方法为什么不会导致textview的更新崩溃 看代码在View.java文件中 public void invalidate() {invalidate(true); }public void invalidate(boolean invalidateCache) {invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); }void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,boolean fullInvalidate) {if (mGhostView ! null) {mGhostView.invalidate(true);return;}if (skipInvalidate()) {return;}// Reset content capture cachesmPrivateFlags4 ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;mContentCaptureSessionCached false;if ((mPrivateFlags (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)|| (invalidateCache (mPrivateFlags PFLAG_DRAWING_CACHE_VALID) PFLAG_DRAWING_CACHE_VALID)|| (mPrivateFlags PFLAG_INVALIDATED) ! PFLAG_INVALIDATED|| (fullInvalidate isOpaque() ! mLastIsOpaque)) {if (fullInvalidate) {mLastIsOpaque isOpaque();mPrivateFlags ~PFLAG_DRAWN;}mPrivateFlags | PFLAG_DIRTY;if (invalidateCache) {mPrivateFlags | PFLAG_INVALIDATED;mPrivateFlags ~PFLAG_DRAWING_CACHE_VALID;}// Propagate the damage rectangle to the parent view.final AttachInfo ai mAttachInfo;final ViewParent p mParent;if (p ! null ai ! null l r t b) {final Rect damage ai.mTmpInvalRect;damage.set(l, t, r, b);p.invalidateChild(this, damage);}// Damage the entire projection receiver, if necessary.if (mBackground ! null mBackground.isProjected()) {final View receiver getProjectionReceiver();if (receiver ! null) {receiver.damageInParent();}}} }核心代码是上面第三段invalidateInternal方法中的invalidateChild方法 它回调到ViewGroup中的invalidateChild方法 看invalidateChild如下图我们知道 if (attachInfo ! null attachInfo.mHardwareAccelerated) 条件成立attachInfo不为空 且硬件加速被开启从API 14 (3.0)起。硬件加速默认开启。 attachInfo 是一个view在attach至其父window被赋值的一系列信息。 所以条件成立后走的onDescendantInvalidated方法 如下 CallSuper public void onDescendantInvalidated(NonNull View child, NonNull View target) {/** HW-only, Rect-ignoring damage codepath** We dont deal with rectangles here, since RenderThread native code computes damage for* everything drawn by HWUI (and SW layer / drawing cache doesnt keep track of damage area)*/// if set, combine the animation flag into the parentmPrivateFlags | (target.mPrivateFlags PFLAG_DRAW_ANIMATION);if ((target.mPrivateFlags ~PFLAG_DIRTY_MASK) ! 0) {// We lazily use PFLAG_DIRTY, since computing opaque isnt worth the potential// optimization in provides in a DisplayList world.mPrivateFlags (mPrivateFlags ~PFLAG_DIRTY_MASK) | PFLAG_DIRTY;// simplified invalidateChildInParent behavior: clear cache validity to be safe...mPrivateFlags ~PFLAG_DRAWING_CACHE_VALID;}// ... and mark inval if in software layer that needs to repaint (hw handled in native)if (mLayerType LAYER_TYPE_SOFTWARE) {// Layered parents should be invalidated. Escalate to a full invalidate (and note that// we do this after consuming any relevant flags from the originating descendant)mPrivateFlags | PFLAG_INVALIDATED | PFLAG_DIRTY;target this;}if (mParent ! null) {mParent.onDescendantInvalidated(this, target);} }上面一段代码核心是 mParent.onDescendantInvalidated(this, target); 类似于requestLayout()方法 onDescendantInvalidated中会循环递归调用 mParent.onDescendantInvalidated(this, target);方法直到找到ViewRootImpl中的onDescendantInvalidated(this, target)方法,而它的方法没做线程检测如下图这就是开了硬件加速后invalidate方法不会崩溃的原因。如下图直接走scheduleTraversals绘制刷新有兴趣可看 而关闭硬件加速后会怎样呢 继续看invalidateChild方法 Deprecated Override public final void invalidateChild(View child, final Rect dirty) {final AttachInfo attachInfo mAttachInfo;if (attachInfo ! null attachInfo.mHardwareAccelerated) {// HW accelerated fast pathonDescendantInvalidated(child, child);return;}ViewParent parent this;if (attachInfo ! null) {...do {....parent parent.invalidateChildInParent(location, dirty);....} while (parent ! null);} }上面一段核心是 parent parent.invalidateChildInParent(location, dirty);方法 同理while循环不停调用 invalidateChildInParent方法直到找到ViewRootImpl中的invalidateChildInParent(int[] location, Rect dirty)方法,如下图内部进行了线程检测 **验证猜想关闭硬件加速android:hardwareAcceleratedfalse**果然崩溃了。 三、总结 这就是我遇到的问题单纯的根据TextView在子线程可以更新得出的结论总的来说要想不崩溃还得绕过ViewRootImpl中的checkThread的检测。至于研究它有什么用只有知道理解源码的流程才能写出更好的东西。 Android 学习笔录 Android 性能优化篇https://qr18.cn/FVlo89 Android Framework底层原理篇https://qr18.cn/AQpN4J Android 车载篇https://qr18.cn/F05ZCM Android 逆向安全学习笔记https://qr18.cn/CQ5TcL Android 音视频篇https://qr18.cn/Ei3VPD Jetpack全家桶篇内含Composehttps://qr18.cn/A0gajp OkHttp 源码解析笔记https://qr18.cn/Cw0pBD Kotlin 篇https://qr18.cn/CdjtAF Gradle 篇https://qr18.cn/DzrmMB Flutter 篇https://qr18.cn/DIvKma Android 八大知识体https://qr18.cn/CyxarU Android 核心笔记https://qr21.cn/CaZQLo Android 往年面试题锦https://qr18.cn/CKV8OZ 2023年最新Android 面试题集https://qr18.cn/CgxrRy Android 车载开发岗位面试习题https://qr18.cn/FTlyCJ 音视频面试题锦https://qr18.cn/AcV6Ap
http://www.pierceye.com/news/887234/

相关文章:

  • 做彩票网站需要什么服务器wordpress slug
  • 个人空间网站建设太原做网页软件
  • 网站建站方式有哪些wordpress星座主题自适应
  • 如何为公司做网站算命 网站开发
  • 那些做软件的网站十大装潢公司上海
  • wordpress 仿站 主题公路建设网站
  • 接网站 建设网站建设业务员招聘
  • 江西工程建设信息网站服装公司网站建设
  • 什么店是做网站制作的dw网站结构图怎么做
  • 一个网站开发需要多久软件开发工时费用标准
  • 做网站 公司不懂英文怎么做英文的seo网站
  • 南宁企业门户网站建设价格连云港网站建设电话
  • 石林彝族网站建设网站活动页面设计
  • 网站建设流程表推广联盟有哪些平台
  • 制作网站深圳建大型门户网站
  • 网站开发招标技术规范书网站建设动态静态
  • 阿里巴巴网站开发工具北京的网站制作公司
  • 石家庄网站营销互联网运营培训课程
  • 单位网站服务的建设及维护oa软件定制开发
  • 银川公司网站建设zepto网站开发
  • 看谁做的好舞蹈视频网站电话营销
  • 开封建网站到哪里学平面设计
  • 电子商务与网站建设实践论文化工行业网站建设
  • 如何搭建一个网站平台卖16斤肉赚200元
  • 手机主页网站推荐江宁城乡建设局网站
  • 甜品网站设计论文张家界seo
  • 单位网站及政务新媒体建设管理wordpress刷留言
  • 用花瓣网站上的图片做游戏行吗西安霸屏推广
  • 单片机和做网站医疗网站建设渠道
  • 上海做家纺的公司网站新闻发布稿