0

Iv'e는 목록 활동을 사용하여 인터넷에서 가져온 항목 목록을 표시하는 Android 앱을 가지고 있습니다. 먼저 AsyncTask를 사용하여 목록을로드하고 Async 작업이 완료되면 다른 비동기 작업이 호출되어 목록 항목과 함께가는 축소 그림을로드합니다. 내가 겪고있는 문제는 사용자가 언제든지 누를 수있는 새로 고침 단추에 액세스 할 수 있고 누를 때 항목의 전체 목록이 삭제되고 로딩이 다시 시작된다는 것입니다. 미리보기 이미지를로드하는 비동기 작업은 이러한 상황이 발생할 경우 계속 실행될 수 있으며 기존 목록 항목에 미리보기 이미지를 추가하려고 시도 할 수 있습니다. Iv'e는 목록에서 동기화를 시도했습니다. 부울을 사용하여 연구 한 후에 작동하지 않는다고 깨달았습니다. 또한 thumbnail 로더를 취소하기 위해 새로 고침이 발생했는지 확인하기 위해 정적 원자 부울을 사용해 보았습니다. 어떤 아이디어? 도움이 될AsyncTasks가 실행 중일 때 새로 고침 버튼을 선택했는지 감지

public class LoadItems extends AsyncTask<Void, Void, Boolean> { 

private Activity activity; 
private static boolean loading = false; 
public static final AtomicBoolean refreshing = new AtomicBoolean(false); 
private static final String TAG = "LoadItems"; 
private int start; 

private List<ListItem> items; 

public LoadItems(Activity activity) { 
    this.activity = activity; 
} 

@Override 
protected void onPreExecute() { 
    loading = true; 
    start = ItemViewer.itemList.size(); 
} 

@Override 
protected Boolean doInBackground(Void... arg0) { 

    items = WebFunctions.getMoreItems(activity); 
    return (items != null); 
} 


protected void onPostExecute(Boolean success) { 
    if (success) { 
     for (ListItem item: items) { 
      ItemViewer.itemList.add(item); 
      Log.d(TAG, "added item " + item.getTitle()); 
     } 
     LoadThumbnails thumbnailLoader = new LoadThumbnails(); 
     thumbnailLoader.execute(start, ItemViewer.itemList.size()); 
    } 
    loading = false; 
} 

public void protectedExecute() { 
    if (!loading) 
     execute(); 
} 

public void refresh() { 
    if (!refreshing.getAndSet(true)) { 
     WebFunctions.reset(); 
     ItemViewer.itemList.removeAllItems(); 
     execute(); 
    } 
} 

} 



public class LoadThumbnails extends AsyncTask<Integer, Void, Drawable> { 
private int position; 
private int end; 

@Override 
protected Drawable doInBackground(Integer... params) { 
    position = params[0]; 
    end = params[1]; 
    Drawable thumbnail = null; 
    synchronized(ItemViewer.itemList) { 
     if (LoadItems.refreshing.get()) 
      cancel(true); 
     String url = ItemViewer.itemList.get(position).getThumbnailUrl(); 
     if (!url.isEmpty()) 
      thumbnail = WebFunctions.loadDrawableFromUrl(ItemViewer.activity, url); 
    } 
    return thumbnail; 
} 

protected void onPostExecute(Drawable d) { 

    synchronized (ItemViewer.itemList) { 
     if (LoadItems.refreshing.get()) 
      cancel(true); 
     if (d != null) 
      ItemViewer.itemList.setThumbnail(position, d); 
     position++; 
     if (position < end) { 
      LoadThumbnails lt = new LoadThumbnails(); 
      lt.execute(position, end); 
     } 
    } 
} 

} 

답변

0

다음 단계 :

  1. 캐시 결과, 이전에 인터넷에서 가져온 무엇 이건이 응용 프로그램이 실행될 때 다시 복원 신속하게 저장해야합니다. 당신이, 차례 차례로, '새로 고침'

  2. 을 눌러에서 사용자를 중지 응용 프로그램 시작, 긴 지연 및 빈 화면을 피할이 방법은 부울 변수 reload_in_progress 수 있도록 당신이 그물에서 데이터를 끌어 시작할 때 true로 설정 모든 미리보기 이미지가 준비되면 false으로 설정하십시오. reload_in_progresstrue 일 때 '재로드'클릭 핸들러가 클릭을 무시해야합니다.

  3. progress bar의 왕이 사용자에게 표시되므로 이미 다시로드 중이며 다시 reload을 푸시하지 않는다는 것을 알 수 있습니다.

  4. 거의 잊어 버렸고, 사용자에게 "라이브"로 표시되는 데이터를 업데이트하지 않습니다. 이로 인해 사용자가 항목을 변경하고 예상 한 것과 완전히 다른 일을하는 멋진 상황이 발생합니다. 긴 업데이트는 자체 데이터를 유지하고 모든 것이 준비되었을 때만 새로운 데이터를 신속하게 교환해야합니다.

0

이것은 매우 간단합니다. 사용자가 새로 고침 버튼을 누를 때마다 새 작업을 만들기 전에 작성한 마지막 비동기 작업에서 cancel()으로 전화하십시오. 그들은 isCancelled()를 호출하여 취소되었다 예를 들어,

private void onRefreshClick(View v) { 
    if(mLastLoadItemTask != null) mLastLoadItemTask.cancel(true); 
    if(mLastLoadThumbnailTask != null) mLastLoadThumbnailTask.cancel(true); 
    mLastLoadItemTask = new LoadItems(...); 
    mLastLoadItemTask.execute(); 
} 

는 그런 다음 비동기 작업을 각각 먼저 검사의 onPostExecute에서 볼 수 있습니다. 취소 된 경우 onPostExecute 메소드가 방금 돌아와서 작동하지 않는지 확인하십시오. 예를 들어,

protected void onPostExecute(...) { 
     if(isCancelled()) return; 
     //Adding items to list 
     //Or start load thumbnail task 
    } 

당신은 onPostExecute 방법과 cancel 호출은 모든 주요 therad에서 발생하기 때문에 그 어떤 의도 나 오래된 업데이트를 방지해야 볼 수 있듯이. 마지막으로 제안 할 것은 loadThumbs 작업을 변경하여 가능한 빨리 isCancelled()를 검사하여 작업을 중단 할 수있게하는 것입니다.

관련 문제