2013-08-05 3 views
0

시스템이 목록보기에서 올바른 위치의보기를로드 할 때까지 시스템이 재생보기 인 것으로 보이므로 몇 초 동안 이미지와 텍스트가 중복됩니다. 누구든지 도와 줄 수 있습니까?flinging 및 스크롤하는 동안 몇 초 동안 잘못된보기를 표시하는 목록보기

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    View v = convertView; 
    Log.d("position",""+position); 

    if(v==null){ 
     LayoutInflater inflater = LayoutInflater.from(mContext); 
     v = inflater.inflate(R.layout.layout_appinfo, null); 

     holder = new ViewHolder(); 
     holder.ivAppIcon = (ImageView)v.findViewById(R.id.ivIconApp); 
     holder.tvAppName = (TextView)v.findViewById(R.id.tvNameApp); 
     holder.progress = (ProgressBar)v.findViewById(R.id.progress_spinner); 
     v.setTag(holder); 
    } else { 
     holder = (ViewHolder) v.getTag(); 
    } 
    holder.ivAppIcon.setImageDrawable(null); 
    holder.tvAppName.setText(null); 
    holder.progress.setVisibility(View.VISIBLE); 
    holder.ivAppIcon.setVisibility(View.GONE); 

    // Using an AsyncTask to load the slow images in a background thread 
    new AsyncTask<ViewHolder, Void, Drawable>() { 
     private ViewHolder v; 
     private ResolveInfo entry = (ResolveInfo) mListAppInfo.get(position); 

     @Override 
     protected Drawable doInBackground(ViewHolder... params) { 
      v = params[0]; 
      return entry.loadIcon(mPackManager); 
     } 

     @Override 
     protected void onPostExecute(Drawable result) { 
      super.onPostExecute(result); 
      // If this item hasn't been recycled already, hide the 
      // progress and set and show the image 
      v.progress.setVisibility(View.GONE); 
      v.ivAppIcon.setVisibility(View.VISIBLE); 
      v.ivAppIcon.setImageDrawable(result); 
      v.tvAppName.setText(entry.loadLabel(mPackManager)); 
     } 
    }.execute(holder); 
    return v; 
} 

static class ViewHolder { 
     TextView tvAppName; 
     ImageView ivAppIcon; 
     ProgressBar progress; 
     //int position; 
} 

마치 몇 초 동안 위치를 잘못 설정 한 것과 같습니다.

+0

getView는 asyncTask를 넣을 적절한 위치가 아니며 독립적으로 실행하고 데이터를 사용할 수있는 경우 뷰를 업데이트하십시오. 어댑터에서 notifydatasetchanged를 호출하면 getView에서만 이미지를 사용할 수 있는지 확인하십시오. 그렇지 않으면 기본 이미지가 표시됩니다. 당신은 DiskLruCache를 사용하여 작은 버전의 이미지를 유지할 수 있습니다. Google의 클래스는 프레임 워크의 일부가 아니지만 빠르게 작동합니다. 여기에 그냥 볼 때마다 이미지를 다운로드 –

+0

http://android-developers.blogspot.in/2010/07/multithreading-for-performance.html – Raghunandan

답변

6

ViewHolder가 AsyncTask에 대한 참조를 보유하도록 할 수 있습니다. convertView != null 일 때로드중인 이미지가이 새 행에 맞지 않는다는 것을 알고 있으므로 ViewHolder가 보유한 AsyncTask에 cancel()을 호출 할 수 있습니다. doInBackgrond()onPostExecute()에서 무엇이든하기 전에 먼저 if(!isCancelled())을 확인하십시오.

static class ViewHolder { 
    TextView tvAppName; 
    ImageView ivAppIcon; 
    ProgressBar progress; 
    AsyncTask task; 
} 

public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    if (convertView == null) { 
     /* inflate new view, make new ViewHolder, etc. */ 
     ... 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
     holder.task.cancel(); 
    } 

    // always make a new AsyncTask, they cannot be reused 
    holder.task = new AsyncTask ... 
    holder.execute(...); 
    ... 
} 
+0

나는 이것을 시도했지만 활동을 종료하고 내가 시도했던 것처럼 행동 취소 (true)를 호출 했음에도 불구하고 같은 AsyncTask를 동시에 두 번 실행합니다. convertview! = null 인 경우에! –

+0

항상 새로운 AsyncTask를 만들고 ViewHolder에 설정해야합니다. – Karakuri

+0

고마워, 작동 해! –

0

현재 항목 이미지보기를 표준로드 이미지로 설정하거나 어댑터를 통해보기를 제공 할 때 바로 설정할 수 있습니다. 이렇게하면 비동기 작업에로드되는 동안 이미지가 항상 "재설정"됩니다. 재활용 된 뷰의 성능 이점을 유지하는 가장 좋은 방법입니다. 텍스트도 마찬가지입니다. 위에서 언급 한 바와 같이

http://developer.android.com/training/displaying-bitmaps/process-bitmap.html

이 문제는, 당신의 AsyncTask를 이미 재활용되어있어보기에 하드 참조를 유지하고 있다는 점이다 :

2

안드로이드의 개발자 문서는이에 큰 부분을 가지고있다.

관련 문제