ListView의 재활용 메커니즘 작동 방식 어떻게 최적화되는지 전혀 알지 못했기

그래서 나는 이전에이 문제가 있었고 당연히 여기 에 도움을 요청 했다 . Luksprog의 대답은 ListView와 GridView가 재활용 뷰로 어떻게 최적화되는지 전혀 알지 못했기 때문에 훌륭했습니다. 그래서 그의 조언으로 그리드 뷰에 뷰를 추가하는 방법을 변경할 수있었습니다. 문제는 이제 이해가되지 않는 것입니다. 이것은 getView나의 것입니다 BaseAdapter:


public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            convertView = inflater.inflate(R.layout.day_view_item, parent, false);
        }
        Log.d("DayViewActivity", "Position is: "+position);
        ((TextView)convertView.findViewById(R.id.day_hour_side)).setText(array[position]);
        LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.day_event_layout);

        //layout.addView(new EventFrame(parent.getContext()));

        TextView create = new TextView(DayViewActivity.this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics()), 1.0f);
        params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        create.setLayoutParams(params);
        create.setBackgroundColor(Color.BLUE);
        create.setText("Test");
        //the following is my original LinearLayout.LayoutParams for correctly setting the TextView Height
        //new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()), 1.0f)   
        if(position == 0) {
            Log.d("DayViewActivity", "This should only be running when position is 0. The position is: "+position);
            layout.addView(create);
        }

        return convertView;
    }

}

스크롤 할 때 문제가 발생하며 위치 0이 아닌 위치 6에 위치합니다. 위치 6과 위치 8처럼 보이고 위치 8에 2를 넣습니다. 이제 여전히 ListView와 GridView를 사용하여 정지하려고합니다. 왜 이런 일이 일어나고 있는지 이해하지 못합니다. 내가이 질문을하는 주된 이유 중 하나는 ListView와 GridView의 재활용보기 또는이 기사 가 그것을 어떻게 다루는 지에 대해 모르는 다른 사람들을 돕기 위해 ScrapView 메커니즘입니다.

여기에 이미지 설명을 입력하십시오

나중에 편집

기본적으로 ListView 작동 방식을 이해하는 데 필요한 모든 Google IO 토크에 대한 링크 추가 댓글에서 링크가 죽었습니다. 따라서 user3427079는 해당 링크를 업데이트하기에 충분했습니다. 여기 에 쉽게 접근 할 수 있습니다.



답변

처음에 나는 또한 listview 재활용과 convertview 사용 메커니즘을 알지 못했지만 하루 종일 연구 한 후에 android.amberfog 의 이미지를 참조하여 목록보기의 메커니즘을 거의 이해했습니다 .
여기에 이미지 설명을 입력하십시오

목록보기는 어댑터로 채워질 때마다 기본적으로 목록 보기가 화면에 표시 할 수있는 수를 표시하며 목록을 스크롤해도 행 수는 증가하지 않습니다. 이것은 안드로이드가 사용하는 트릭으로 목록보기가보다 효율적이고 빠르게 작동합니다. 이제 이미지를 참조하는 listview의 내부 이야기에서 볼 수 있듯이 처음에는 listview에 7 개의 표시 가능한 항목이 있으며, 항목 1이 더 이상 표시되지 않을 때까지 위로 스크롤하면 getView ()가이보기 (예 : item1)를 재활용과 당신은 사용할 수 있습니다

System.out.println("getview:"+position+" "+convertView);

당신의 내부

public View getView(final int position, View convertView, ViewGroup parent)
{
    System.out.println("getview:"+position+" "+convertView);
    ViewHolder holder;
    View row=convertView;
    if(row==null)
    {
        LayoutInflater inflater=((Activity)context).getLayoutInflater();
        row=inflater.inflate(layoutResourceId, parent,false);

        holder=new PakistaniDrama();
        holder.tvDramaName=(TextView)row.findViewById(R.id.dramaName);
        holder.cbCheck=(CheckBox)row.findViewById(R.id.checkBox);

        row.setTag(holder);

    }
    else
    {
        holder=(PakistaniDrama)row.getTag();
    }
            holder.tvDramaName.setText(dramaList.get(position).getDramaName());
    holder.cbCheck.setChecked(checks.get(position));
            return row;
    }

처음에는 리사이클 러에 뷰 (예 : 항목)가 없으므로 getcat ()은 각 보이는 항목에 대해 새보기를 작성하지만 위로 스크롤하고 항목 1이 화면 밖으로 이동하면 재활용기로 전송됩니다. 체크 박스가 체크 상태의 경우, 현재 상태 (예를 들어 텍스트 뷰 ‘텍스트’또는 광산 경우로,이 뷰와 연관되며, 리사이클 러에 보관).

이제 위 / 아래로 스크롤하면 목록보기가 새보기를 만들지 않고 재활용기에있는보기를 사용합니다. 당신의에서 로그 캣 는 ‘convertView는’null이 아닌 것을 알 수 새 항목 (8) 즉, convertview를 사용하여 그려집니다 때문에는, 기본적으로는 그 자리에서 재활용 및 팽창 항목 8에서 항목 1보기를합니다, 당신은 관찰 할 수있다 내 코드에서. 체크 박스가 있고 위치 0에서 체크하면 (항목 1에 체크 박스가 있고 체크했다고 가정 해 봅시다) 아래로 스크롤하면 항목 8 체크 박스가 이미 선택된 것을 볼 수 있습니다. 이것은 listview가 동일한보기를 다시 사용하는 이유입니다. 성능 최적화로 인해 새로운 것을 만들지 않습니다.

중요한 것들

1 . 설정된 절대 layout_heightlayout_width귀하의 목록보기의 wrap_contentgetView()목록보기에서 인출되는 뷰의 높이를 측정하기위한 몇 가지 아이를 얻을 수 있도록 어댑터를 강제하고 convertview에게조차 목록을 반환하는 등의 예기치 않은 동작이 발생할 수 있습니다이 scrolled.always 사용하지 않습니다 match_parent또는 고정 너비 / 높이.

2 . 당신이 당신의 목록보기 및 질문의 힘 후 일부 레이아웃이나 뷰를 사용하려면 내가 설정하면 당신의 마음에 와서 layout_heightfill_parent내부에 목록보기를 넣어하기 위해 더 나은 그래서, 화면을 내려갑니다 표시되지 않습니다 목록보기 이후보기 layout.For 예를 선형 레이아웃 및 요구 사항으로 그 레이아웃의 높이와 폭을 설정하고 확인 높이 에 목록보기의 속성을 레이아웃의 등이다 (폭 레이아웃 경우 같은 320 과 높이가 280) 당신의 목록보기 다음 높이너비 가 같아야합니다. 이것은 getView ()에게 렌더링 할 뷰의 정확한 높이와 너비를 알려주고 getView ()는 몇 번의 임의의 행을 호출하지 않으며 스크롤하기 전에도 변환 뷰를 반환하는 것과 같은 다른 문제가 발생하지 않습니다. 이것은 내 목록보기가 lineaLayout 내부에 있지 않으면 LinearLayout 내부의 Listview를 마법처럼 작동시키는 것처럼 뷰 호출을 반복하고 뷰를 변환하는 것과 같은 문제가있었습니다. (이유를 몰랐습니다)

01-01 14:49:36.606: I/System.out(13871): getview 0 null
01-01 14:49:36.636: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.636: I/System.out(13871): getview 1 android.widget.RelativeLayout@406082c0
01-01 14:49:36.646: I/System.out(13871): getview 2 android.widget.RelativeLayout@406082c0
01-01 14:49:36.646: I/System.out(13871): getview 3 android.widget.RelativeLayout@406082c0
01-01 14:49:36.656: I/System.out(13871): getview 4 android.widget.RelativeLayout@406082c0
01-01 14:49:36.666: I/System.out(13871): getview 5 android.widget.RelativeLayout@406082c0
01-01 14:49:36.666: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.696: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.706: I/System.out(13871): getview 1 null
01-01 14:49:36.736: I/System.out(13871): getview 2 null
01-01 14:49:36.756: I/System.out(13871): getview 3 null
01-01 14:49:36.776: I/System.out(13871): getview 4 null

그러나 이제는 해결되었습니다. 나는 잘 설명하지 못하지만 하루 종일 이해하기 위해 저와 같은 다른 초보자가 내 경험에 도움을받을 수 있다고 생각했으며 지금은 사람들이 조금 이해하기를 바랍니다. 의 의 ListView 정말 지저분하고대로 작동 방식 프레임 워크 까다로운 그래서 초보자는 이해 너무 많은 문제가 발견


답변

Holder 패턴에서 Holder 객체에 위치를 설정하는 경우 매번 다음과 같이 설정해야합니다.

@Override
public final View getView(int position, View view, ViewGroup parent) {
    Holder holder = null;
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) App.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(getContainerView(), parent, false);
        holder = getHolder(position, view, parent);
        holder.setTag(tag);
        view.setTag(holder);
    } else {
        holder = (Holder) view.getTag();
    }
    holder.position = position;
    draw(holder);
    return holder.getView();
}

이것은 추상 클래스의 예입니다.

getHolder(position, view, parent);

에 대한 모든 설정 작업을 수행

ImageViews, TextViews, etc..


답변

홀더 패턴을 사용하면 원하는 것을 얻을 수 있습니다.

이 패턴에 대한 설명은 여기에서 찾을 수 있습니다.

화면을 아래로 스크롤하면 위의 목록보기 항목이 숨겨져 목록보기가 재활용됩니다. 새 목록보기 항목을 표시하기 위해 재사용됩니다.


답변