2011-05-09 4 views
0

안녕하세요, 주위를 둘러 본 후 publishProgress()를 사용하면 더 긴 계산을 위해 UI를 업데이트 할 수 있습니다. 나는이 코드를 실행할 때 ANR을 얻었 기 때문에 이것을 잘못 구현 한 것처럼 보인다. 왜 그 이유를 이해하도록 도와 주실 수 있습니까? http://pastebin.com/zQNhkDJ9AsyncTask에서 UI 업데이트

http://pastebin.com/HcNZtAsx

+0

코드에서 AsyncTask를 만들고 실행하는 곳을 어디에도 알 수 없습니다. 다른 파일에서 그런 일이 발생 했습니까? – BigFwoosh

+0

네, 게시 할 필요가 없다고 생각했습니다. – Cody

답변

1

귀하에 문제가 doInBackground 기능은 단지 publishProgress를 호출하는 것이 아마도 :

여기 내 코드입니다. 모든 작업은 UI 스레드에서 실행되는 publishProgress에서 수행되므로 여전히 ANR 방식으로 진행됩니다. doInBackground 내에서 무거운 작업을 수행해야하며 처리가 완료되면 UI 스레드를 업데이트 할 수 있습니다.

+0

내 UI의보기가 어떤 색으로 표시되어야하는지 계산하는 것은 어려운 일입니다. 그렇다면 UI를 손상시키지 않으려면 어떻게해야합니까? – Cody

+0

맞습니다.하지만 onProgressUpdate 함수 내부에서 계산을하고있는 중입니다.doInBackground 내부에서 수행해야하며 onProgressUpdate 내에서 새 값으로 색상을 업데이트해야합니다. – BigFwoosh

0

AsyncTask를 정적 내부 클래스로 만들어야하고 Activity에 대한 참조 인 속성이 있어야합니다. 그런 다음 UIupdate()처럼 직접 Activity에서 메서드를 호출 할 수 있습니다.

onPause 콜백에서 Activity에 대한 참조를 지우려면 매우 조심해야한다는 점에 유의해야합니다. 그렇지 않으면 순환 참조가 설정되어 메모리 누수가 발생합니다.

내 패턴은 또 하나의 기본 Java 객체를 갖습니다.이 객체는 Activity에서 "StateHolder"라고 부르는 다른 개인 정적 클래스와 AsyncTask 객체를 처리하기위한 내 게이트웨이 (예 : 초기화 및 NULL (NULL로 설정))를 가지고 있습니다.) 및 회전 변경 중에 진행중인 작업 취소. "onRetainNonConfigurationInstance"에 대한 콜백에서 StateHolder를 마샬링 된 객체로 사용할 수 있습니다. 여기

약간 거친 코드 :

개인 정적 클래스 GetConnectionsStatusTask은 AsyncTask를 { 개인 BoothActivity mActivity을 확장; 개인 예외 mReason;

public GetConnectionsStatusTask(BoothActivity activity) { 
    super(); 
    mActivity = activity; 
} 

public void setActivity(BoothActivity activity) { 
    mActivity = activity; 
} 

@Override 
protected void onPreExecute() { 
    if(mActivity != null) { 
     mActivity.startProgressBar("Loading", "Please wait"); 
    } 
} 

@Override 
protected Connections doInBackground(Void... values) { 
    try { 
     App app = (App)mActivity.getApplication(); 
     return(app.getApp().userConnections()); 
    }catch(Exception e) { 
     mReason = e; 
     return(null); 
    } 
} 

@Override 
protected void onPostExecute(Connections status) { 
    super.onPostExecute(status); 
    if(mActivity != null) { 
     mActivity.completedConnectionsStatusCheck(status, mReason); 
    } 
}  
} 

개인 정적 클래스 StateHolder { 개인 GetConnectionsStatusTask connectionsTask; 당신이 그렇게처럼 StateHolder를 다시 팽창 할 수

 if(mStateHolder != null) { 
      mStateHolder.cancelTasks(); 
     } 

그리고에서 onCreate에서 :

Object retained = getLastNonConfigurationInstance(); 
    if(retained != null && retained instanceof StateHolder) { 
     mStateHolder = (StateHolder) retained; 
     mStateHolder.setActivityForTasks(this); 
    } else { 
     mStateHolder = new StateHolder(); 
    } 

이 또한 StateHolder를 다시 초기화합니다 onPause에서 다음

public void cancelTasks() { 
     if (connectionsTask != null) { 
      connectionsTask.setActivity(null); 
      connectionsTask.cancel(true); 
      connectionsTask = null; 
     } 
} 
    public void setActivityForTasks(BoothActivity activity) { 
     if (connectionsTask != null) { 
      connectionsTask.setActivity(activity); 
     } 
} 

    public void startConnections(BoothActivity activity) { 
     if(mIsConnectionsChecking == false) { 
      mIsConnectionsChecking = true; 
      connectionsTask = new GetConnectionsStatusTask(activity); 
      connectionsTask.execute();    
     } 
    } 
    } 

나는 같은 코드가 현재 진행 상태와 함께 진행 막대 업데이트와 같은 UI 위젯을 다시 설정할 수 있습니다.

이 패턴을 사용하면 실제로 비동기 작업을 실행하고 진행 막대가 다시 초기화되어 회전 변경을 처리 할 수 ​​있습니다.