自定义视图是否可以知道onPause已被调用?

Gen*_* S. 34 multithreading android custom-view

我有一个自定义View运行一个Thread操作,它定期调用interwebs.我想知道是否有一种方法让我不必从父Activity(onPause)中删除该线程,以便Thread在后台(和/或被杀死)后不在后台进行铣削.

这里的意图是自定义View是自给自足的,不需要从Activity中进行额外处理.这样做的方法是让它在其父级被后台时监听,然后让它在线程中的无限睡眠循环到期.我没有看到这样做的方法,但我希望我忽略了一些东西.

Yog*_*thi 50

是的你可以使用下面的代码,

@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
    super.onVisibilityChanged(changedView, visibility);
    if (visibility == View.VISIBLE) //onResume called
    else // onPause() called
}

@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
    super.onWindowFocusChanged(hasWindowFocus);
    if (hasWindowFocus) //onresume() called
    else // onPause() called
}

@Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        // onDestroy() called
}

@Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        // onCreate() called
}
Run Code Online (Sandbox Code Playgroud)

  • 附加/分离的生命周期并不严格模仿创建/销毁生命周期.但是,是的,如果附加了一个视图,那么它的活动就已创建了.但是,在视图分离后,其活动不能保证被破坏.尝试切换最近的菜单. (3认同)
  • 提供的代码可能存在潜在问题:它可能会收到多个 `onPause`、`onResume` 事件。例如,视图可见性已更改为不可见,然后窗口失去焦点,视图将获得 2 个“onPause”。 (3认同)
  • 注意:当显示"活动选项"菜单溢出弹出窗口时,窗口也会失去焦点(并且会调用onWindowFocusChanged(false)).我曾经在onWindowFocusChanged()中刷新ListView,这会导致丢失所选项目的不幸副作用,这在ActionMode的溢出菜单中尤其令人讨厌.所以,我正在考虑使用Application.registerActivityLifecycleCallbacks()并对所有感兴趣的视图(例如通过实现某些接口)进行某种回调. (2认同)

dco*_*cow 13

除非您直接通知它.

为了您的目的,覆盖View.onDetachedFromWindow()并放弃您的线程.然后,当视图再次可见时,将线程重新旋转View.onAttachedToWindow().onPause()和onResume()的问题在于,您仍然可以拥有一个在屏幕上可见的视图,但它附加到暂停的Activity.可能发生这种情况的一个示例是,如果窗口中有一个活动覆盖另一个活动.

或者,正如威廉·古韦亚所暗示的那样,片段可能更适合您的目的,因为它已经具有暂停和恢复的生命周期钩子,并且任何与网络对话的内容实际上都落入了控制器领域.

  • 当按下Home按钮使应用程序背景时,不一定要调用`onDetachedFromWindow()`. (2认同)

Ale*_*nat 9

是的你可以。您所需要的只是拥有一个 LifecycleOwner 类型的字段。更多关于它的官方文档。就我而言,我创建了一个自定义视图,其中包含来自 3rd 方库 - CameraView 的另一个视图。

首先,自定义视图需要实现 LifecycleOberver 接口

public class MakePhotoView extends ConstraintLayout implements LifecycleObserver
Run Code Online (Sandbox Code Playgroud)

所以,我的自定义视图中有一个字段:

private LifecycleOwner mLifecycleOwner;
Run Code Online (Sandbox Code Playgroud)

我在构造函数中将它作为参数之一传递:

public MakePhotoView(Context context, OnPhotoMadeListener onPhotoMadeListener, LifecycleOwner lifecycleOwner) {
    super(context);
    mOnPhotoMadeListener = onPhotoMadeListener;
    mLifecycleOwner = lifecycleOwner;
    init();
}
Run Code Online (Sandbox Code Playgroud)

之后,我将我的自定义视图注册为 LifecycleOwner 中生命周期事件的观察者:

private void init() {
    //other code
    mLifecycleOwner.getLifecycle().addObserver(this);
}
Run Code Online (Sandbox Code Playgroud)

最后我可以监听生命周期事件:

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void startCamera() {
    AppLog.logObject(this, "On Resume called for MakeCameraView");
    mCameraView.start();
}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void stopCamera() {
    AppLog.logObject(this, "On Pause called for MakeCameraView");
    mCameraView.stop();
}

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void destroyCamera() {
    AppLog.logObject(this, "On Destroy called for MakeCameraView");
    mCameraView.destroy();
}
Run Code Online (Sandbox Code Playgroud)


小智 6

如果 Build.VERSION.SDK_INT < Build.VERSION_CODES.N

@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
    super.onVisibilityChanged(changedView, visibility);
    if (visibility == View.VISIBLE) //onResume called
    else // onPause() called
}
Run Code Online (Sandbox Code Playgroud)

然后 Build.VERSION.SDK_INT >= Build.VERSION_CODES.N

@Override
public void onVisibilityAggregated(boolean isVisible) {
    super.onVisibilityAggregated(isVisible);
    if (isVisible) //onresume() called
    else // onPause() called
}
Run Code Online (Sandbox Code Playgroud)

您可以阅读ProgressBar 的源代码来获得想法。