사용자 정의 listview 어댑터 getView 메소드가 여러 번 호출되며 일관된 순서로 호출되지 않습니다.


162

사용자 정의 목록 어댑터가 있습니다.

class ResultsListAdapter extends ArrayAdapter<RecordItem> {

재정의 된 'getView'메서드에서 위치를 확인하고 위치가 convertView인지 여부를 확인하기 위해 인쇄합니다.

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        System.out.println("getView " + position + " " + convertView);

이것의 출력 (목록이 처음 표시 될 때 아직 사용자 입력이 없음)

04-11 16:24:05.860: INFO/System.out(681): getView 0 null  
04-11 16:24:29.020: INFO/System.out(681): getView 1 android.widget.RelativeLayout@43d415d8  
04-11 16:25:48.070: INFO/System.out(681): getView 2 android.widget.RelativeLayout@43d415d8  
04-11 16:25:49.110: INFO/System.out(681): getView 3 android.widget.RelativeLayout@43d415d8  
04-11 16:25:49.710: INFO/System.out(681): getView 0 android.widget.RelativeLayout@43d415d8  
04-11 16:25:50.251: INFO/System.out(681): getView 1 null  
04-11 16:26:01.300: INFO/System.out(681): getView 2 null  
04-11 16:26:02.020: INFO/System.out(681): getView 3 null  
04-11 16:28:28.091: INFO/System.out(681): getView 0 null  
04-11 16:37:46.180: INFO/System.out(681): getView 1 android.widget.RelativeLayout@43cff8f0  
04-11 16:37:47.091: INFO/System.out(681): getView 2 android.widget.RelativeLayout@43cff8f0  
04-11 16:37:47.730: INFO/System.out(681): getView 3 android.widget.RelativeLayout@43cff8f0  

AFAIK, 명시 적으로 찾을 수는 없지만 getView ()는 보이는 행에 대해서만 호출됩니다. 내 앱은 4 개의 보이는 행으로 시작하기 때문에 적어도 0-3에서 순환하는 위치 번호가 의미가 있습니다. 그러나 나머지는 엉망입니다.

  • 왜 각 행마다 getview가 세 번 호출됩니까?
  • 아직 스크롤하지 않았을 때 이러한 convertView는 어디에서 오는가?

나는 약간의 재교육을 받았으며 좋은 대답을 얻지 못한 채 사람들 이이 문제를 레이아웃 문제와 관련시키고 있음을 알았습니다. 따라서 목록이 포함 된 레이아웃은 다음과 같습니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent" 
    android:orientation="vertical" >

    <TextView android:id="@+id/pageDetails"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" />

    <ListView android:id="@+id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:drawSelectorOnTop="false" />

</LinearLayout>

각 개별 행의 레이아웃 :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="108dp"    
android:padding="4dp">

<ImageView
    android:id="@+id/thumb"        
    android:layout_width="120dp"
    android:layout_height="fill_parent"        
    android:layout_alignParentTop="true"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_marginRight="8dp"        
    android:src="@drawable/loading" />

<TextView  
    android:id="@+id/price"
    android:layout_width="wrap_content"
    android:layout_height="18dp"         
    android:layout_toRightOf="@id/thumb"
    android:layout_alignParentBottom="true"       
    android:singleLine="true" />

<TextView  
    android:id="@+id/date"
    android:layout_width="wrap_content"
    android:layout_height="18dp"         
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true" 
    android:paddingRight="4dp"       
    android:singleLine="true" />

<TextView
    android:id="@+id/title"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="17dp" 
    android:layout_toRightOf="@id/thumb"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    android:paddingRight="4dp"   
    android:layout_alignWithParentIfMissing="true"
    android:gravity="center" />

</RelativeLayout>

시간 내 주셔서 감사합니다

답변:


271

이것은 문제가 아니며, getView()몇 번이나 호출 될지 에 대한 보장은 없습니다 . 당신의 특별한 경우에 당신은 ListView그것을 제공함으로써 가능한 최악의 일 을하고 있습니다 height=wrap_content. 이렇게 ListView하면 레이아웃 타임에 어댑터에서 몇 개의 자식을 측정하여 크기가 얼마나 큰지 알 수 있습니다. 이것은 스크롤하기 전에 전달 된 것을 제공 ListView하는 convertViewsgetView()입니다.


10
나는 이것이 좋은 이유를 찾지 못한다. 변경하고 싶더라도 괜찮습니다. 그러나 현재 왜이 동작을 수행하고 있는지에 대한 답을 얻지 못하고 있습니까?
cdpnet

45
@cdpnet이 그 일을 한 이유 그는 당신이 말 했는가 ListView의 높이가 wrap_content그것의 높이 확실하지 그래서, 그러므로에 맞는 것을 볼 테스터의 일종의에서 일부 아이를 낳는다. 당신의 변경 ListViewfill_parent한 후 로그를 확인 통화가 크게 줄어들어야합니다.
Blundell

4
2.3과 4.x 사이의 ListView 동작이 크게 변경되었습니다. 해결 방법은 ListView가 설계되었으므로 셀 / 목록 항목이 순수한 뷰 여야하고 빠르게 그리기 위해 최적화되어야합니다. Romain이 발표 한 ListView의 Google I / O 토크에 따르면 getView는 뷰 렌더링을 최적화하고 결과를 버릴 수 있도록 호출 될 수 있습니다. 필자의 의견으로는 iOS UITableView만큼 개발자 친화적이지 않지만 그 방법입니다.
Cameron Lowell Palmer

4
정말 고맙습니다! 왜 getView ()가 그렇게 자주 호출되는지 이해하지 못했습니다. 나는 fill_parent에 wrap_content를 swithced 지금 내 응용 프로그램 : 다시 빠르게
줄리아 헥센

28
ListViews를 layout_height = wrap_content로 설정하면 많은 성능 문제가 발생하므로 경고가 발생합니다.
nathanielwolf

53

목록보기 match_parentlayout_height속성을 사용해보십시오 . 그것은 방지 할 수 getView()너무 자주 호출 할 수 있습니다.


4
Fred T는 LIST VIEW ...의
레이아웃 _ 높이를

8
참고 fill_parent로 대체해야 match_parentAPI 레벨 8 이상에 대한.
Jason Axelson

getView () 메소드는 ListView에 대해 match_parent로 너비와 높이를 설정하여 여러 번 호출하여 성능 문제 만 해결할 것이라고 생각합니다.
Cuong Vo

45

layout_width와 layout_height를 match_parent로 변경했을 때이 문제를 제거했습니다 (layout_height 만 변경해도 도움이되지 않음).


유용한 참고 사항 중첩 된 항목이 있는지 확인하십시오. "가장 높은"것을 match_parent 로 변경해야합니다 . 그것이 누군가를 돕기를 바랍니다.


한 단어 친구는 "멋진"이지만 왜 wrap_content가 문제를 일으키는 지 모릅니다. 이것은 내 문제를 해결했습니다.
Android Killer

사용할 때 @AndroidKiller wrap_content, 다음 ListView목록의 내용이되기 위해 얼마나 많은 목록 항목 모르고, 왜 그게 전부 ListView가 생각하는 시도가 여러 행으로 만들 수있는 디스플레이에 적합하며, 당신이 사용하는 경우 fill_parent또는 match_parent, ListView, 괜찮아, 내 높이를 생각한다 입니다 . 표시하려면 행 수가 x필요합니다 n.
Adil Soomro

정말 고맙습니다 ! 이 동작으로 인해 여러 번의 호출로 인해 이미지가 임의로 변경되었습니다 ... 이제 처음부터 괜찮습니다.
Chostakovitch

7

"왜"질문에 대답 할 수는 없지만 " ListView items repeating "문제 (스크린 높이보다 더 높은 항목이있는 경우) 에 대한 문제를 해결할 수있는 솔루션 이 있습니다.

위의 많은 사람들이 언급했듯이 ListVew 태그 의 android : layout_height 속성을 fill_parent로 유지하십시오 .

getView () 함수에 대한 해결책은 ViewHolder 라는 정적 클래스 를 사용하는 입니다. 예를 확인하십시오 . ur 배열 또는 ArrayCollection의 모든 항목을 추가하는 작업을 성공적으로 수행합니다.

이것이 친구를 돕기를 바랍니다!

안부 인사, Siddhant


초기 버전의 Android (Pre ICS)에서 ViewHolder 패턴을 사용하면 MemoryLeak 예외가 발생할 수 있으므로주의해야합니다. ICS + 버전에서 자유롭게 사용하십시오.
Vahid Ghadiri

@Siddhant 덕분에 나는 내에서 반복되는 이미지의 이유에서 하루 TTO 그림을 지출 GridView하고 변화 android:layout_heightandroid:layout_width나를 위해 일을하지 않습니다. 그러나 ViewHolder나를 위해 고정 된 반복 이미지를 사용 하여이 튜토리얼 android-vogue.blogspot.com/2011/06/…을 진행했습니다.
Nikolay Podolnyy

4

질문 : 어댑터가 getView ()를 여러 번 호출하는 이유는 무엇입니까? 답변 : 스크롤 할 때 Listview가 렌더링 될 때 어댑터가 getView ()를 호출하여보기를 가져와야 할 다음보기가있는보기입니다.

Ques : listview 너비와 높이가 fill_parent로 설정되어 있으면 왜 호출이 적습니까? Ans : 팽창기가리스트의 화면 영역에 대해 고정 된 크기를 가지기 때문에 뷰를 화면에 렌더링하기 위해 한 번 계산됩니다.

쿼리가 해결되기를 바랍니다.


좋은 설명입니다. 그러나 match_parent 가 더 나은 선택 일 수 있습니다.
Fattie

예 @JoeBlow, API 2.4 / 3.0부터 fill_parent 대신 match_parent를 사용하는 것이 좋습니다
jitain sharma

4

AutoCompleteTextView의 드롭 다운과 동일한 문제가 발생했습니다. 여기에 도착할 때까지 이틀 동안 문제와 싸우고 있었고 해결책을 보여주었습니다.

dropDownHeight = "match_parent"를 쓰면 문제가 해결 된 것입니다. 이제 문제는 UI와 관련이 있습니다 (하나의 항목이있는 경우 드롭 다운이 너무 큼). 그러나 여러 호출 문제 (보다 중요)가 수정되었습니다.

감사합니다!!


2

"왜 각 행마다 getview가 세 번 호출됩니까?" getView는 listview를 스크롤 할 때 호출되고 더 잘 말하면 목록보기의 위치가 변경되면 호출됩니다!


그래도보기는 바뀌지 않았습니다. 활동이 시작될 때 화면에 4 개의 행보기가 있으며, 스크롤 또는 사용자 입력이 전혀없이 각 행에 대해 3 개의 getView 호출을
받습니다

이 답변은 잘못되었습니다. 정답은 ** wrap_content **를 사용하면 많은 수의 getView 호출이 발생한다는 것입니다.
Fattie

2

같은 문제가 있습니다. 높이를 fill_parent로 설정하면 행당 "보통"2 번의 호출이 발생합니다. 그러나 ListView의 높이를 정확한 값으로 설정하면 300dp라고 가정하면 행 당 정확히 하나의 GetView 호출을 얻습니다.

따라서 유일한 방법은 먼저 화면의 높이를 결정한 다음 프로그래밍 방식으로 listvilew의 높이를 해당 값으로 설정하는 것 같습니다. 나는 그것을 좋아하지 않는다. 더 좋은 방법이 있기를 바랍니다.


1
고마워 재밌습니다.이 질문은 몇 개월 동안 휴면 상태에 처해 있으며 지난 몇 주 동안 몇 가지 의견 만 남게되었습니다. 나는 더 이상이 프로젝트를하지 않고 있지만 시간이 좀 지나서 시도해 본 후 다시 확인을하려고한다. 다시 감사합니다.
edzillion

여기서도 행당 두 번의 통화가 발생합니다. 행 0, 1, 2, 3 다음 나중에 다른 0, 1, 2, 3 100MS - 행을 볼 수 있습니다 무엇에 대한 통계를 수집 할 때 엉덩이에 통증 인
어딘가의 누군가가

2

(설정 후 여전히 누가의 모든 height의를 ListViewmatch_parent) (나처럼) 붙어 있습니다 :

또한 height부모 레이아웃을 로 설정해야 합니다 match_parent.

아래 예를 참조하십시오. 는 LinearLayout여기에 부모입니다 :

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

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/something" />

        <ListView
            android:id="@+id/friendsList"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

1

이것은 늦게 올지 모르지만 layout_weight항상 사용하려면 기억하십시오.layout_width="0dp"


0

이 솔루션을 만들었을 수도 있습니다. 아마도 최고의 솔루션은 아니지만 작업을 수행합니다 ...

//initialize control string
private String control_input = " ";

그런 다음 =

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View gridview = convertView;

    // change input_array for the array you use
    if (!control_input.equals(input_array[position])) {
        control_input = input_array[position];

        //do your magic

    } 

    return gridview;
}

그것이 도움이되기를 바랍니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.