๊พธ์ค€ํ•จ์ด ์ง„๋ฆฌ๋‹ค!!

์–ด์ œ๋ณด๋‹ค ๋ฐœ์ „ํ•œ ์˜ค๋Š˜์ด ๋˜๊ณ ํ”ˆ ๐Ÿง‘๐Ÿปโ€๐Ÿ’ป ์˜ ๋ธ”๋กœ๊ทธ

Android/Java

[Java][Android] Android ViewTreeObserVer onGlobalLayoutListener ํ™œ์šฉํ•˜๊ธฐ

๋ށ์š” 2022. 8. 24. 01:34

์˜ค๋Š˜๋„ ํšŒ์‚ฌ์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ •๋ฆฌ ์ค‘ ์•ฑ์ด destory ๋˜์—ˆ์Œ์—๋„ porifler์—์„œ ์ธ์Šคํ„ด์Šค๋“ค์„ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ํ™•์ธ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

GC๋ฅผ ์•„๋ฌด๋ฆฌ ๋Œ๋ ค๋„ ์ฐธ์กฐ๊ฐ€ ํ•ด์ œ ๋˜์ง€ ์•Š์•„ ํ•ด๋‹น ๋ถ€๋ถ„์„ ํ™•์ธํ•ด๋ณธ ๊ฒฐ๊ณผ MainView์—์„œ ViewTressObeserver์— onGlobalLayoutListener๋ฅผ ๋“ฑ๋กํ•œ ๊ฒƒ์ด ํ•ด์ œ๊ฐ€ ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ํ™•์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 

 

๊ทธ๋Ÿฐ ์˜๋ฏธ๋กœ ์˜ค๋Š˜์€ ViewTreeObserver๊ฐ€ ๋ญ”์ง€ ๋˜ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€์— ์™œ ViewTreeObserver์—์„œ ์ฐธ์กฐ๊ฐ€ ํ•ด์ œ๊ฐ€ ๋˜์ง€ ์•Š์•˜๋Š”์ง€์— ๋Œ€ํ•ด ํฌ์ŠคํŒ…ํ•ด๋ณด๋ ค ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜Ž

 

ViewTreeObserver๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

A view tree observer is used to register listeners that can be notified of global changes in the view tree. Such global events include, but are not limited to, layout of the whole tree, beginning of the drawing pass, touch mode change.... A ViewTreeObserver should never be instantiated by applications as it is provided by the views hierarchy

 

Android Developer์—์„œ๋Š” ์œ„์™€ ๊ฐ™์ด ์„ค๋ช…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฒˆ์—ญํ•˜์ž๋ฉด ViewTreeObserver๋Š” ViewTree์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์•Œ๋ฆด ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ „์—ญ ์ด๋ฒคํŠธ์—๋Š” ์ „์ฒด ํŠธ๋ฆฌ์˜ ๋ ˆ์ด์•„์›ƒ, ๋“œ๋กœ์ž‰ ํŒจ์Šค์˜ ์‹œ์ž‘, ํ„ฐ์น˜ ๋ชจ๋“œ ๋ณ€๊ฒฝ ๋“ฑ์ด ์žˆ์œผ๋ฉฐ, ViewTreeObserver๋Š” ๋ทฐ ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ ์ œ๊ณตํ•˜๋ฏ€๋กœ ์ธ์Šคํ„ด์Šคํ™” ํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.๋ผ๊ณ  ๋ณ€์—ญ ๋˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งํ•ด ViewTree์˜ ์ƒํƒœ๋ฅผ ๊ด€์ฐฐํ•˜๋Š” ๊ด€์ฐฐ์ž๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

ViewTreeObserver์—์„œ ์ œ๊ณตํ•˜๋Š” ์ด๋ฒคํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์œผ๋ฉฐ ํ•„์š”ํ•œ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ViewTreeObserver.OnDrawListener
//๋ทฐ๋ฅผ ๊ทธ๋ฆด ๋•Œ


ViewTreeObserver.OnGlobalFocusChangeListener
//์ „์ฒด ๋ทฐ์˜ ํฌ์ปค์Šค๊ฐ€ ๋ฐ”๋€” ๋•Œ


ViewTreeObserver.OnGlobalLayoutListener
//์ „์ฒด ๋ทฐ๊ฐ€ ๊ทธ๋ ค์งˆ ๋•Œ


ViewTreeObserver.OnPreDrawListener
//๋ทฐ๊ฐ€ ๊ทธ๋ ค์ง€๊ธฐ ์ „


ViewTreeObserver.OnScrollChangedListener
//์Šคํฌ๋กค ์ƒํƒœ์˜ ๋ณ€๊ฒฝ ๋  ๋•Œ


ViewTreeObserver.OnTouchModeChangeListener
// ํ„ฐ์น˜ ๋ชจ๋“œ ๋ณ€๊ฒฝ ๋  ๋•Œ


ViewTreeObserver.OnWindowAttachListener
// ๋ทฐ์˜ ๊ณ„์ธต ๊ตฌ์กฐ์— ๋ถ™๋Š” ์ƒํ™ฉ๋“ค (๋ถ™๊ฑฐ๋‚˜ ๋–จ์–ด์ง€๊ฑฐ๋‚˜ ๋‘˜๋‹ค)


ViewTreeObserver.OnWindowFocusChangeListener
// ์œˆ๋„์šฐ ํฌ์ปค์Šค๊ฐ€ ๋ณ€๊ฒฝ ๋  ๋•Œ

 

๊ทธ ์ค‘ ์˜ค๋Š˜ ์ œ๊ฐ€ ํฌ์ŠคํŒ…ํ•  ๋‚ด์šฉ์€ onGlobalLayoutListener์— ๋Œ€ํ•œ ๋‚ด์šฉ์ด๋ฉฐ ์ด๋ฏธ์ง€๊ฐ€ ๊ทธ๋ ค์งˆ ๋•Œ ์ด๋ฏธ์ง€์˜ ๋†’์ด๋ฅผ ๋ฐ›์•„ TextView์— ํ‘œ์‹œํ•˜๋Š” ๋™์ž‘์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

 

์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

- ๋ ˆ์ด์•„์›ƒ xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/image_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/android_bg"
            />

        <TextView
            android:id="@+id/height_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="๋†’์ด"
            android:textSize="22sp" />
    </LinearLayout>



</androidx.constraintlayout.widget.ConstraintLayout>

- JAVA ์ฝ”๋“œ

package com.example.viewtreeobserverparctice;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private final static String TAG = "MainActivity";

    TextView mTextView;
    ImageView mImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate()");
        setContentView(R.layout.activity_main);

        initView();

        if(mImageView != null){
            mImageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    Log.d(TAG, "onGlobalLayout: ImageView set!");
                    if(mTextView != null){
                        mTextView.setText("๋†’์ด๋Š” " + mImageView.getHeight() + "์ž…๋‹ˆ๋‹ค.");
                        mImageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    }
                }
            });
        }
    }

    private void initView() { //initialize views
        Log.d(TAG, "initView()");
        mTextView = findViewById(R.id.height_text_view);
        mImageView = findViewById(R.id.image_view);
    }

    private void removeInstance() {
        Log.d(TAG, "removeInstance()");
        mTextView = null;
        mImageView = null;
    }

    @Override
    protected void onDestroy() {
        removeInstance();
        super.onDestroy();
        Log.d(TAG, "onDestroy()");
    }
}

 

โ€ป ViewTreeObserver๋Š” ๋ณ€๊ฒฝ ๊ฐ์ง€๊ฐ€ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ์—๋Š” ์ถ”๊ฐ€ํ•ด์ค€ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋ฐ˜๋“œ์‹œ ์ œ๊ฑฐํ•ด์•ผ ํ•˜๋ฉฐ ํ•ด๋‹น ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐ Listener๋ฅผ ๊ณ„์† ํ˜ธ์ถœ ํ•˜๋Š” ์ƒํƒœ๊ฐ€ ๋ฐœ์ƒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ํ•ด๋‹น ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋”์ด์ƒ ์‚ฌ์šฉ์ด ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ์—๋Š” ํŒ๋‹จ์— ๋”ฐ๋ผ ์ ์ ˆํ•˜๊ฒŒ ๋ฆฌ์Šค๋„ˆ๋ฅผ ํ•ด์ œํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฉ๋ฒ•์€ ์œ„ ์™€ ๊ฐ™์ด removeOnGlobalLayoutListener()๋ฅผ ํ†ตํ•ด ํ•ด์ œํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.