ListView에서 단일 행을 어떻게 업데이트합니까? 가지고 ListView있는 디스플레이 뉴스 항목을. 여기에는

내가 가지고 ListView있는 디스플레이 뉴스 항목을. 여기에는 이미지, 제목 및 일부 텍스트가 포함됩니다. 이미지는 별도의 스레드 (대기열 및 모두 포함)에로드되고 이미지를 다운로드 할 때 notifyDataSetChanged()목록 어댑터를 호출 하여 이미지를 업데이트합니다. 이것은 작동하지만 모든 보이는 항목을 호출 하기 getView()때문에 너무 자주 notifyDataSetChanged()호출 getView()됩니다. 목록에서 단일 항목 만 업데이트하고 싶습니다. 어떻게해야합니까?

현재 접근 방식의 문제점은 다음과 같습니다.

  1. 스크롤이 느립니다
  2. 이미지에 페이드 인 애니메이션이 있습니다. 목록의 단일 새 이미지가로드 될 때마다 발생합니다.


답변

귀하의 정보 Michelle 덕분에 답을 찾았습니다. 를 사용하여 올바른 뷰를 얻을 수 있습니다 View#getChildAt(int index). 캐치는 첫 번째 보이는 항목부터 계산을 시작한다는 것입니다. 실제로 보이는 항목 만 얻을 수 있습니다. 당신은 이것을 해결합니다 ListView#getFirstVisiblePosition().

예:

private void updateView(int index){
    View v = yourListView.getChildAt(index - 
        yourListView.getFirstVisiblePosition());

    if(v == null)
       return;

    TextView someText = (TextView) v.findViewById(R.id.sometextview);
    someText.setText("Hi! I updated you manually!");
}


답변

이 질문은 Google I / O 2010에서 요청되었으며 여기에서 볼 수 있습니다.

ListView의 세계, 시간 52:30

기본적으로 어떤 로맹 가이 설명하는 것은 호출하는 것입니다 getChildAt(int)ListView뷰와 (내가 생각하는) 호출을받을 getFirstVisiblePosition()위치와 지수 사이의 상관 관계를 알아.

Romain은 또한 Shelves 라는 프로젝트를 예로 들어 설명합니다. 그가 방법을 의미한다고 생각 ShelvesActivity.updateBookCovers()하지만의 전화를 찾을 수 없습니다 getFirstVisiblePosition().

멋진 업데이트가옵니다 :

RecyclerView는 가까운 시일 내에이 문제를 해결합니다. http://www.grokkingandroid.com/first-glance-androids-recyclerview/ 에서 지적했듯이 다음과 같이 변경 사항을 정확하게 지정하는 메소드를 호출 할 수 있습니다.

void notifyItemInserted(int position)
void notifyItemRemoved(int position)
void notifyItemChanged(int position)

또한 모든 사람들은 RecyclerView를 기반으로 한 새로운 뷰를 사용하고 싶을 것입니다. 멋진 애니메이션으로 보답하기 때문입니다! 미래는 굉장해 보인다! 🙂


답변

이것이 내가 한 방법입니다.

항목 (행)에는 고유 한 ID가 있어야 나중에 업데이트 할 수 있습니다. 목록이 어댑터에서보기를 가져올 때 모든보기의 태그를 설정하십시오. (기본 태그가 다른 곳에 사용 된 경우 키 태그를 사용할 수도 있습니다)

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    View view = super.getView(position, convertView, parent);
    view.setTag(getItemId(position));
    return view;
}

업데이트의 경우 목록의 모든 요소를 ​​확인하고 주어진 ID가있는보기가 있으면 표시되어 업데이트를 수행합니다.

private void update(long id)
{

    int c = list.getChildCount();
    for (int i = 0; i < c; i++)
    {
        View view = list.getChildAt(i);
        if ((Long)view.getTag() == id)
        {
            // update view
        }
    }
}

실제로 다른 방법보다 쉽고 위치가 아닌 ID를 처리 할 때 더 좋습니다! 또한 보이는 항목에 대해서는 update를 호출해야합니다.


답변

이 모델 클래스 객체와 같이 모델 클래스를 전역으로 가져옵니다.

SampleModel golbalmodel=new SchedulerModel();

그리고 그것을 글로벌로 초기화하십시오

모델을 뷰로 초기화하여 뷰의 현재 행을 가져옵니다.

SampleModel data = (SchedulerModel) sampleList.get(position);
                golbalmodel=data;

변경된 값을 전역 모델 객체 메소드로 설정하고 notifyDataSetChanged를 추가하십시오.

golbalmodel.setStartandenddate(changedate);

notifyDataSetChanged();

여기에 좋은 답변이있는 관련 질문이 있습니다.


답변

대답은 명확하고 정확 CursorAdapter합니다. 여기 에 사례 에 대한 아이디어를 추가 하겠습니다.

하위 클래스 CursorAdapter(또는 ResourceCursorAdapter, 또는 SimpleCursorAdapter) 인 경우 구현 ViewBinder하거나 재정의 bindView()하고 newView()메소드 를 가져 오는 경우 인수에서 현재 목록 항목 색인을받지 못합니다. 따라서 일부 데이터가 도착하고 관련 표시 목록 항목을 업데이트하려는 경우 해당 인덱스를 어떻게 알 수 있습니까?

내 해결 방법은 다음과 같습니다.

  • 작성된 모든 목록 항목보기 목록을 유지하고이 목록에 항목을 추가하십시오. newView()
  • 데이터가 도착하면 데이터를 반복하고 업데이트해야하는 데이터를 확인 notifyDatasetChanged()합니다.

뷰 재활용으로 인해 저장 해야하는 뷰 참조 수와 반복은 화면에 표시되는 목록 항목 수와 거의 같습니다.


답변

int wantedPosition = 25; // Whatever position you're looking for
int firstPosition = linearLayoutManager.findFirstVisibleItemPosition(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;

if (wantedChild < 0 || wantedChild >= linearLayoutManager.getChildCount()) {
    Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
    return;
}

View wantedView = linearLayoutManager.getChildAt(wantedChild);
mlayoutOver =(LinearLayout)wantedView.findViewById(R.id.layout_over);
mlayoutPopup = (LinearLayout)wantedView.findViewById(R.id.layout_popup);

mlayoutOver.setVisibility(View.INVISIBLE);
mlayoutPopup.setVisibility(View.VISIBLE);

RecycleView의 경우이 코드를 사용하십시오


답변

Erik을 제공하는 코드를 사용했지만 훌륭하게 작동했지만 내 목록보기에 복잡한 사용자 정의 어댑터가 있으며 UI를 업데이트하는 코드의 두 번 구현에 직면했습니다. 어댑터 getView 메소드에서 새보기를 얻으려고 시도했습니다 (목록보기 데이터를 보유한 배열 목록이 이미 업데이트 / 변경되었습니다).

View cell = lvOptim.getChildAt(index - lvOptim.getFirstVisiblePosition());
if(cell!=null){
    cell = adapter.getView(index, cell, lvOptim); //public View getView(final int position, View convertView, ViewGroup parent)
    cell.startAnimation(animationLeftIn());
}

잘 작동하지만 이것이 좋은 습관인지는 모르겠습니다. 따라서 목록 항목을 두 번 업데이트하는 코드를 구현할 필요가 없습니다.