findVIewById에 관하여


안녕하세요 안드로이드 코딩을 하다가 갑자기 궁금한 것이 생겨서 질문올려요!

이미지

그림을 보시면

작은 네모( 파란색으로 구분이 되어있는)들이 총 16개가 있는데 이 것들은 모두 TextView입니다. 그리고 빨간색 네모는 LinearLayout으로 구분한 것입니다.

빨간색 네모(총 4개)끼리는 연관이 없지만, 빨간색 네모 안에 있는 파란색 네모 4개끼리는 나름 연관이 있습니다.

이 화면을 하나의 Activity xml 파일 안에 전부 다 넣으면 복잡할 것 같고, 16개의 TextView에 id를 하나씩 부여하기에는 너무 많고 하여 밑의 코드처럼 include를 사용해서 파일을 분리시키고 id의 개수도 줄였습니다.

[horizontal.xml]

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/text_horizontal_1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center" />

    <View  //라인 구분을 위한 뷰
        android:layout_width="1dp"
        android:layout_height="match_parent"
        android:background="#ccc" />

    <TextView
        android:id="@+id/text_horizontal_2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center" />

</LinearLayout>

[vertical.xml]

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <include
       android:id="@+id/vertical_1"
       layout="@layout/horizontal"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_weight="1" />

    <View  //라인 구분을 위한 뷰
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#ccc" />

    <include
       android:id="@+id/vertical_2"
       layout="@layout/horizontal"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_weight="1" />

</LenearLayout>

[content_main.xml]

<LinearLayout 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"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal">

        <include
            android:id="@+id/main_11"
            layout="@layout/vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="#000" />

        <include
            android:id="@+id/main_12"
            layout="@layout/vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#000" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal">

        <include
            android:id="@+id/main_21"
            layout="@layout/vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="#000" />

        <include
            android:id="@+id/main_22"
            layout="@layout/vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />

    </LinearLayout>

XML코드는 이런식으로 하였습니다.

이제 JAVA 코드로 가서

[MainAcitivity.java]

public static final int[] main_id = { R.id.main_11, R.id.main_12,  R.id.main_21, R.id.main_22 }
public static final int[] vertical_id = { R.id.vertical_1, R.id.vertical_2 }
public static final int[] text_id = { R.id.text_horizontal_1, R.id.text_horizontal_2 }

View[] main_2by2 = new View[main_id.length];

public void setView() {

    for ( int z = 0 ; z  < main_id.length ; z++ ) {
        main_2by2[z] = findViewById(main_id[z]);
        for ( int x = 0 ; x < vertical_id.length ; x++ ) {
            View[] vertical = new View[vertical_id.length];
            vertical[x] = main_2by2[z].findViewById(vertical_id[x]);
            for ( int y = 0 ; y < text_id.length ; y++ ) {
                TextView[] text = new TextView[text_id.length];
                text[y] = (TextView) vertical[x].findViewById(text_id[y]);
                text[y].setText( z + "," + x + "," + y );
            }
        }
    }
}

이런식의 참조를 하였습니다.

저 코드를 실행해 보면 화면에는

이미지

이렇게 나오게 됩니다.

데이터 들의 연관성들을 생각해서 저러한 3차원 배열 구조를 생각하게 되었습니다.

그런데 지금 findViewById를 코드상으로 적은 것은 3번 뿐이지만, for문을 돌다보면 빨간 네모(z), 세로(x), 텍스트뷰(y) 이렇게 해서 총 28번을 부르게 됩니다.

findViewById가 성능상으로 않좋다는 것을 들어본적이 있는데, 혹시 저러한 뷰 배치를 다르게 할 방법이 있을까요? 3차원 배열은 제가 xml코드나 java코드를 조금 줄여보고자 저렇게 한 것이므로 다른 방법이 있다면 추천 부탁드립니다!

또한 제가 지금 TextView들을 setView() 메소드를 벗어나면 참조를 할 수가 없는 형태로 되어있는데, 저 16개의 TextView의 텍스트 전체를 바꿀 일이 있다면 setView() 메소드를 다시 부르게 됩니다. 즉 findViewById를 다시 하는거지요.... 이게 굉장히 않좋다는 것은 알고 있는데, TextView를 TextView[][][] text = new TextView[4][ 2][ 2]; 이렇게 하면 메모리 상으로 좋지 않을 것 같아서 이렇게 하지 않았습니다.

findViewById를 다시 하는 것과 TextView[ 4 ][ 2][ 2]를 가지고 있는 것 어떤 것이 더 좋은 방법 일까요?

질문이 길어졌습니다...ㅠ 죄송합니다.. ㅠㅠ


  • 제목을 제대로 쓴다는 것을 깜빡하고 그냥 올렸었네요.. 제목 수정하였습니다.    TuTanKhamen   2016.5.19 16:24     
조회수 359


1 답변


좋아요
1
싫어요
채택취소하기

안드로이드에서 그리드 스타일의 뷰를 구성하기 위한 위젯들을 제공하는데요. 올려주신 코드처럼 직접 레이아웃을 구성하는 것도 방법이지만 안드로이드에서 제공하는 API를 활용하는 것이 시간적 비용, 가독성, 성능, 유지보수 측면에서 이점이 있을 것 같습니다.

GridLayout

GridView

RecyclerView(GridLayoutManager)

FlexboxLayout (최근에 공개)

그리고 성능은 findViewById의 호출이 문제가 될 수도 있고 아닐 수도 있을 것 같습니다. ListView나 RecyclerView에서는 그런 문제를 회피하기 위해서 ViewHolder 패턴이 존재하는 것은 사실이고요. 다만 직접 구현하신 뷰가 고정적이고 빈번하게 노출되거나 자주 업데이트 되지 않는다면 기준 자체가 모호해질 수 있습니다. 오히려 중첩된 뷰 구조를 플랫하게(평평하게) 펼치는 작업이 랜더링 성능에 더 효과적일 수도 있고, 그리드를 포함하는 하나의 커스텀 뷰를 만드는 것도 방법이 될 수 있습니다.

Hashcode에 findViewById 관련된 질답이 있어서 링크 남겼습니다.

http://hashcode.co.kr/questions/1574/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%EC%97%90%EC%84%9C-findviewbyid-%ED%95%A8%EC%88%98%EA%B0%80-%EC%84%B1%EB%8A%A5%EC%9D%B4-%EB%96%A8%EC%96%B4%EC%A7%80%EB%82%98%EC%9A%94


로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close