Can a custom View know that onPause has been called?

后端 未结 6 2161
南方客
南方客 2021-02-03 18:52

I have a custom View that runs a Thread operation which sits around making calls to the interwebs periodically. I would like to know if there\'s a way for me to not have to kil

相关标签:
6条回答
  • 2021-02-03 18:57

    Yes you can using below code,

    @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
    }
    
    0 讨论(0)
  • 2021-02-03 19:08

    Yes you can. All that you need is to have a field of LifecycleOwner type. More about it in official documentation. In my case i created a custom view with another view from 3rd party library - CameraView.

    At first, custom view needs to implement LifecycleOberver interface

    public class MakePhotoView extends ConstraintLayout implements LifecycleObserver
    

    So, i have a field in my custom view:

    private LifecycleOwner mLifecycleOwner;
    

    I pass it in the constructor as one of parameters:

    public MakePhotoView(Context context, OnPhotoMadeListener onPhotoMadeListener, LifecycleOwner lifecycleOwner) {
        super(context);
        mOnPhotoMadeListener = onPhotoMadeListener;
        mLifecycleOwner = lifecycleOwner;
        init();
    }
    

    After that i register my custom view as observer for lifecycle events in LifecycleOwner:

    private void init() {
        //other code
        mLifecycleOwner.getLifecycle().addObserver(this);
    }
    

    And finally i can listen for lifecycle events:

    @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();
    }
    
    0 讨论(0)
  • 2021-02-03 19:08

    Either you have to let your view know that the owning Activity is not in the foreground any more, or poll the system with some method to query about which task is currently in the foreground, which seems highly inefficient.

    Here are two links that have addressed this issue:

    • How to check if activity is in foreground or in visible background?
    • Checking if an Android application is running in the background

    (This might not really be an answer, but it was too large for a comment)

    0 讨论(0)
  • 2021-02-03 19:08

    If you simply override the View class and create your own CustomView you could create a interface to act as a listener, which should be implemented by you parent activity, so when something happens you trigger the event and establish the communication between those components back and forth.

    Depending on what you want to achieve, Fragments could be useful since this component has your own lifecycle similar to activity (onPause/onResume for instance) , holds your own state, either has or not a view and could retain their state between configuration chamges.

    See more in: http://developer.android.com/reference/android/app/Fragment.html http://developer.android.com/guide/components/fragments.html

    0 讨论(0)
  • 2021-02-03 19:12

    if 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
    }
    

    then Build.VERSION.SDK_INT >= Build.VERSION_CODES.N

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

    you can read source code of ProgressBar to get idea.

    0 讨论(0)
  • 2021-02-03 19:12

    Not unless you notify it directly.

    For your purpose, override View.onDetachedFromWindow() and relinquish your Thread there. Then, when the view is visible again, spin the Thread back up in View.onAttachedToWindow(). The problem with onPause() and onResume() is that you can still have a view that's visible on screen, but is attached to a paused Activity. An example of when this can happen is if you have one Activity in a window that overlays another.

    Or, as william gouvea suggests, a Fragment might be better suited for your purpose since it already has the life-cycle hooks for pause and resume, and anything that talks to the network really falls in the controller realm anyway.

    0 讨论(0)
提交回复
热议问题