내가 가지고 ListView
있는 디스플레이 뉴스 항목을. 여기에는 이미지, 제목 및 일부 텍스트가 포함됩니다. 이미지는 별도의 스레드 (대기열 및 모두 포함)에로드되고 이미지를 다운로드 할 때 notifyDataSetChanged()
목록 어댑터를 호출 하여 이미지를 업데이트합니다. 이것은 작동하지만 모든 보이는 항목을 호출 하기 getView()
때문에 너무 자주 notifyDataSetChanged()
호출 getView()
됩니다. 목록에서 단일 항목 만 업데이트하고 싶습니다. 어떻게해야합니까?
현재 접근 방식의 문제점은 다음과 같습니다.
- 스크롤이 느립니다
- 이미지에 페이드 인 애니메이션이 있습니다. 목록의 단일 새 이미지가로드 될 때마다 발생합니다.
답변
귀하의 정보 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에서 요청되었으며 여기에서 볼 수 있습니다.
기본적으로 어떤 로맹 가이 설명하는 것은 호출하는 것입니다 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());
}
잘 작동하지만 이것이 좋은 습관인지는 모르겠습니다. 따라서 목록 항목을 두 번 업데이트하는 코드를 구현할 필요가 없습니다.