web-dev-qa-db-ja.com

カスタムリストビューアダプタgetViewメソッドが複数回、一貫した順序で呼び出されない

カスタムリストアダプタがあります。

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  

私の知る限り、明示的にそれを見つけることができませんでしたが、getView()は可視行に対してのみ呼び出されます。私のアプリは4つの表示可能な行から始まるため、少なくとも0〜3の位置番号が意味をなします。しかし、残りは混乱です。

  • Getviewが各行に対して3回呼び出されるのはなぜですか?
  • まだスクロールしていないとき、これらの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>

お時間をいただきありがとうございます

158
edzillion

これは問題ではありません。getView()が呼び出される順序や回数については一切保証されません。あなたの特定のケースでは、height=wrap_contentを与えることで、ListViewで可能な限り最悪のことをしています。これにより、ListViewは、レイアウト時にアダプターから数人の子を測定し、その大きさを把握します。これは、ListViewconvertViewsを提供し、スクロールする前であってもgetView()に渡されることを示しています。

265
Romain Guy

リストビューのmatch_parentプロパティでlayout_heightを試してください。 getView()が頻繁に呼び出されるのを防ぎます。

53
Fred T

Layout_widthとlayout_heightの両方をmatch_parentに変更すると、この問題はなくなりました(layout_heightのみを変更しても解決しませんでした)。


役立つメモネストされたアイテムがある場合は注意してください。 「最高」のものをmatch_parentに変更する必要があります。それが誰かを助けることを願っています。

45
Eugene Chumak

私はあなたの「なぜ」質問に答えることはできませんが、私は間違いなく刺激的な「ListViewアイテム繰り返し」問題の解決策を持っています(あなたが画面の高さを超えるアイテムがurコレクションにあります)。

上記の多くの人々が言及したように、Android:layout_heightプロパティのListVewfill_parentとしてタグ付けします。

また、getView()関数については、static classと呼ばれるViewHolderthis の例をご覧ください。 ur ArrayまたはArrayCollectionのすべてのアイテムを追加するタスクを正常に実行します。

これが友達に役立つことを願っています!!

よろしく、シドハン

7
Siddhant

質問:アダプターがgetView()を何度も呼び出すのはなぜですか?回答:Listviewがスクロール時にレンダリングされると、次の今後のビューでビューが更新されるため、アダプターはgetView()を呼び出してビューを取得する必要があります。

質問:リストビューの幅と高さがfill_parentに設定されている場合、呼び出し回数が少なくなるのはなぜですか?回答:インフレータはリスト用の画面領域のサイズが固定されているため、ビューを画面にレンダリングするために一度計算されます。

クエリが解決されることを願っています。

4
jitain sharma

AutoCompleteTextViewのドロップダウンでも同じ問題が発生していました。私はここに到着するまで2日間問題と戦っていましたが、解決策を見せてくれました。

DropDownHeight = "match_parent"と書くと、問題は修正されます。現在、問題はUIに関連しています(1つのアイテムがある場合、ドロップダウンが大きすぎます)が、複数の呼び出し(はるかに重要)の問題は修正されています。

ありがとうございました!!

私は同じ問題を抱えています。 heightをfill_parentに設定している場合、「通常」行ごとに2回の呼び出しが行われます。しかし、ListViewの高さを正確な値に設定した場合、たとえば300dpにすると、行ごとにGetView呼び出しが1つだけ取得されます。

だから、唯一の方法は最初に画面の高さを決定し、次にプログラムでlistvilewの高さをその値に設定することだと思われます。好きじゃない。もっと良い方法があるといいのですが。

2
bobetko

「各行でgetviewが3回呼び出されるのはなぜですか?」リストビューをスクロールするとgetViewが呼び出され、リストのビューの位置が変更されたときに呼び出されると言ったほうがいいからです!

2
Ungureanu Liviu

まだ(heightListViewmatch_parentに設定した後)スタックしているすべての人(私がそうだったように):

また、親レイアウトのheightmatch_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>
2
B001ᛦ

私はこのソリューションを作成しましたが、おそらく最良のソリューションではありませんが、仕事をします...

//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;
}

それが役に立てば幸い!

0
yago

これは多分遅くなりますが、layout_weightを使用している場合は、常にlayout_width="0dp"を設定することを忘れないでください

0
Kuti Gbolahan