[Android] 直接获取组件的宽高:Activity.onWindowFocusChanged()

本文深入解析Android Activity中onResume()与onWindowFocusChanged()方法的区别,通过实践演示了如何获取View的宽高及在特定时机执行特定操作。并提供了获取View宽高的便捷方式,以及利用onWindowFocusChanged()方法进行本地文件记录读取的实例。
由lily同学提示的这个知识点,献花献花..

onWindowFocusChanged():当Activity的当前Window获得或失去焦点时会被回调此方法。当回调了这个方法时表示Activity是完全对用户可见的(只是可见,还一片黑呼呼的,有待draw..)。当对话框弹起/消失及Activity新创建及回退等都会调用此方法。

相比之下,onResume()方法更多的是指Activity进入了可见的状态,但只是状态,并不是真正的界面构建完成了。

眼见为实,动手实践。

写了个简单的demo,一个Activity只显示一个TestImageView,并重写TestImageView下的onMeasure()、onLayout()、onDraw()方法,并对其设置onGlobalLayout()监听,观察这几个方法与Activity的onResume()、onWindowFocusChanged()的调用顺序,如下:


ClipDrawableActivity onCreate() time=1376920332125
ClipDrawableActivity onResume() TestImageView.width=0 time=1376920332149
MainActivity onWindowFocusChanged hasFocus=false
ClipDrawableActivity TestImageView onMeasure()
ClipDrawableActivity TestImageView onMeasure()
ClipDrawableActivity TestImageView onMeasure()
ClipDrawableActivity TestImageView onMeasure()
ClipDrawableActivity TestImageView onLayout()
ClipDrawableActivity onGlobalLayout() TestImageView.width=736 time=1376920332185
ClipDrawableActivity onWindowFocusChanged() hasFocus=true TestImageView.width=736 time=1376920332187
ClipDrawableActivity TestImageView onMeasure()
ClipDrawableActivity TestImageView onMeasure()
ClipDrawableActivity TestImageView onLayout()
ClipDrawableActivity onGlobalLayout() TestImageView.width=736 time=1376920332194
ClipDrawableActivity TestImageView onDraw()

其调用顺序为Activity.oncreate()→Activity.onResume()→
→TestImageView.onMeasure()→TestImageView.onLayout()→onGlobalLayoutListener()→
→Activity.onWidnowFocusChanged()→.....→
→TextImageView.onDraw()

至此,如果需要获取某个View的宽高,可以在onWindowFocusChanged()处直接获取即可,这比对某个view设置onGlobalLayoutListener的方式来获取方便了许此。又比如,对于需要读取本地文件记录来判断是否是第一次打开界面去提示文本图片的,也可以在此方法中去读取然后再显示在ui上。


本文为Sodino所有,转载请注明出处:http://blog.csdn.net/sodino/article/details/10055659
要不?你尝试关注下微信公共帐号sodino,以后的博文将会推送给你。

10-16 17:11:22.870 24736 24736 D AndroidRuntime: Shutting down VM 10-16 17:11:22.871 24736 24736 E AndroidRuntime: FATAL EXCEPTION: main 10-16 17:11:22.871 24736 24736 E AndroidRuntime: Process: com.android.cts.verifier, PID: 24736 10-16 17:11:22.871 24736 24736 E AndroidRuntime: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.view.ViewRootImpl.setView(ViewRootImpl.java:1736) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:537) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:161) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at com.android.cts.verifier.MainActivity.registerTouchInterceptor(MainActivity.java:128) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at com.android.cts.verifier.MainActivity$1.onClick(MainActivity.java:53) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.view.View.performClick(View.java:8103) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.view.View.performClickInternal(View.java:8080) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.view.View$PerformClick.run(View.java:31642) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:995) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:103) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:283) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.os.Looper.loop(Looper.java:392) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9236) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:611) 10-16 17:11:22.871 24736 24736 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:944)
最新发布
10-17
08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: FATAL EXCEPTION: main 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: Process: com.android.provision, PID: 2483 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.view.ViewRootImpl.setView(ViewRootImpl.java:2101) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:546) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:402) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.app.Dialog.show(Dialog.java:366) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.app.AlertDialog$Builder.show(AlertDialog.java:1131) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.widget.VideoView$5.onError(VideoView.java:615) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:3640) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:107) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:249) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.os.Looper.loop(Looper.java:337) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9562) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:648) 08-04 10:45:35.399 1000 2483 2483 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1005) 08-04 10:45:35.402 1000 2483 2483 D OOMEventManagerFK: checkEventAndDumpForJE: 0
08-05
07-21 20:07:15.157 5376 5376 D SourceMng_Manager_20200401: SrcMngAudioSwitchManager abandonAdayoAudioFocus() sourceType = ADAYO_SOURCE_MEDIA id = com.adayo.proxy.infrastructure.sourcemng.Control.SrcMngAudioSwitchManager@f592723com.adayo.medialibrary.util.DeviceServiceProxy$2@af48420 行 339179: 07-21 20:07:15.158 5376 5376 D SourceMng_Manager_20200401: SrcMngAudioSwitchManager abandonAdayoAudioFocus() end abandonRlt = 1 行 339181: 07-21 20:07:15.159 5376 5376 D MediaLibrary<2507201054> VideoPlaybackService: (VideoPlaybackService.java:35)#SetVideoPlaying pre-> [VideoPreviewActivity.java:406#onPause] info->: setVideoPlaying isPlaying false 行 339183: 07-21 20:07:15.159 5376 5376 I am_on_paused_called: [0,com.adayo.medialibrary.ui.VideoPreviewActivity,performPause] 行 339301: 07-21 20:07:15.187 5376 5376 I Adayo-Mvvm-BaseActivity: com.haibing.mvvm.bases.ui.BaseActivity==>onWindowFocusChanged(BaseActivity.java:125): class com.adayo.medialibrary.ui.VideoPreviewActivity==>onWindowFocusChanged hasFocus = false 行 339302: 07-21 20:07:15.188 5376 5376 D MediaLibrary<2507201054> VideoPreviewActivity: (VideoPreviewActivity.java:1580)#OnWindowFocusChanged pre-> [WindowCallbackWrapper.java:125#onWindowFocusChanged] info->: onWindowFocusChanged: hasFocus false 行 342275: 07-21 20:07:17.379 5376 5376 D IJKMEDIA: IjkMediaPlayer_setVideoSurface 行 342276: 07-21 20:07:17.379 5376 5376 D IJKMEDIA: ijkmp_set_android_surface(surface=0x0) 行 342277: 07-21 20:07:17.379 5376 5376 D IJKMEDIA: ffpipeline_set_surface() 行 342278: 07-21 20:07:17.379 5376 5376 D IJKMEDIA: ijkmp_set_android_surface(surface=0x0)=void 行 342311: 07-21 20:07:17.421 5376 5376 D ConnectivityManager: StackLog: [android.net.ConnectivityManager.unregisterNetworkCallback(ConnectivityManager.java:4029)] [com.bumptech.glide.manager.SingletonConnectivityReceiver$FrameworkConnectivityMonitorPostApi24.unregister(SingletonConnectivityReceiver.java:205)] [com.bumptech.glide.manager.SingletonConnectivityReceiver.maybeUnregisterReceiver(SingletonConnectivityReceiver.java:122)] [com.bumptech.glide.manager.SingletonConnectivityReceiver.unregister(SingletonConnectivityReceiver.java:105)] [com.bumptech.glide.manager.DefaultConnectivityMonitor.unregister(DefaultConnectivityMonitor.java:29)] [com.bumptech.glide.manager.DefaultConnectivityMonitor.onStop(DefaultConnectivityMonitor.java:39)] [com.bumptech.glide.manager.LifecycleLifecycle.onStop(LifecycleLifecycle.java:35)] [java.lang.reflect.Method.invoke(Native Method)] [androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:225)] [androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:199)] [androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:190)] [androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:40)] [androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:360)] [androidx.lifecycle.LifecycleRegistry.backwardPass(LifecycleRegistry.java:290)] [androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:308)] [androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:151)] [androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:134)] [androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:68)] [androidx.lifecycle.ReportFragment$LifecycleCallbacks.onActivityPreStopped(ReportFragment.java:210)] [android.app.Activity.dispatchActivityPreStopped(Activity.java:1328)] [android.app.Activity.performStop(Activity.java:8033)] [android.app.ActivityThread.callActivity ... 行 342322: 07-21 20:07:17.424 5376 5376 I Adayo-Mvvm-BaseActivity: com.haibing.mvvm.bases.ui.BaseActivity==>onStop(BaseActivity.java:98): class com.adayo.medialibrary.ui.VideoPreviewActivity==>onStop 行 342323: 07-21 20:07:17.424 5376 5376 I am_on_stop_called: [0,com.adayo.medialibrary.ui.VideoPreviewActivity,STOP_ACTIVITY_ITEM] 行 342324: 07-21 20:07:17.424 5376 5376 D MediaLibrary<2507201054> VideoPreviewActivity: (VideoPreviewActivity.java:746)#OnSaveInstanceState pre-> [Activity.java:2048#performSaveInstanceState] info->: onSaveInstanceState() 行 342325: 07-21 20:07:17.424 5376 5376 D MediaLibrary<2507201054> VideoPreviewActivity.java: (VideoPreviewActivity.java:1548)#SaveLastPlayPosition pre-> [VideoPreviewActivity.java:753#onSaveInstanceState] info->: saveLastPlayPosition sCurrentVideoPath /storage/8C3C-7AC3/视频符号名称/MP4/那些你很冒险的梦-art--林俊杰--art-4ddd1cebd2065ed97b08c8bb84036768.mp4, sCurrentSeekPosition 67303 行 342326: 07-21 20:07:17.425 5376 5376 I MediaLibrary<2507201054> VideoPreviewActivity: (VideoPreviewActivity.java:755)#OnSaveInstanceState pre-> [Activity.java:2048#performSaveInstanceState] info->: onSaveInstanceState mCurrentPosition:9 sCurrentSeekPosition:67303 行 342329: 07-21 20:07:17.426 5376 5376 I MediaLibrary<2507201054> VideoPreviewActivity: (VideoPreviewActivity.java:756)#OnSaveInstanceState pre-> [Activity.java:2048#performSaveInstanceState] info->: onSaveInstanceState: playState = 5 行 344098: 07-21 20:07:18.971 5376 5376 I Adayo-Mvvm-BaseActivity: com.haibing.mvvm.bases.ui.BaseActivity==>onRestart(BaseActivity.java:79): class com.adayo.medialibrary.ui.VideoPreviewActivity==>onRestart 行 344099: 07-21 20:07:18.971 5376 5376 I am_on_restart_called: [0,com.adayo.medialibrary.ui.VideoPreviewActivity,performRestartActivity] 行 344107: 07-21 20:07:18.992 5376 5376 I Adayo-Mvvm-BaseActivity: com.haibing.mvvm.bases.ui.BaseActivity==>onStart(BaseActivity.java:73): class com.adayo.medialibrary.ui.VideoPreviewActivity==>onStart 行 344108: 07-21 20:07:18.992 5376 5376 I am_on_start_called: [0,com.adayo.medialibrary.ui.VideoPreviewActivity,handleStartActivity]
08-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值