2013-03-20 3 views
1

배경 작업이 많은 앱이 있습니다. 내 UI를 유지하려면 (그리고 ANR을 피하기 위해) 배경 작업 전에 표시하고 완료 할 때 숨기는 불확실한 ProgressBar가 있습니다. 내가 전에 내 배경 작업 후 가시성을 전환Indeterminate ProgressBar로 인해 백그라운드 스레드가 실제로 느려짐

<ProgressBar 
    style="?android:attr/progressBarStyleHorizontal" 
    android:layout_width="match_parent" 
    android:indeterminate="true" 
    android:visibility="gone" /> 

:

this.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     Activity.this.progress.setVisibility(View.VISIBLE); 
    } 
}); 

this.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     Activity.this.progress.setVisibility(View.GONE); 
    } 
}); 

을 내 작업의 생성자에 :

이 내 진행률 표시 줄이 내 활동의 XML로 선언하는 방법입니다

this.progress = (ProgressBar) findViewById(R.my_activity.progress_id); 

내 배경 작업이 너무 무거워 (기본 전화 포함), 새로운 작업을 수행 할 수있는 Runnable.

문제는 progressBar를 사용하면 백그라운드 스레드 마무리 시간이 초당 약 300ms 가량 늘어납니다. 트레이스 뷰를 실행하면 ProgressBar가 새로 고침 될 때마다 뷰를 업데이트하기 위해 백그라운드 스레드가 중지된다는 것을 알 수 있습니다. MAX_PRIORITY에 백그라운드 스레드의 우선 순위를 설정

  1. :

    나는 두 가지 방법을 시도했다.
  2. 새로 고침 빈도가 300ms 인 사용자 지정 애니메이션 만들기 (기본값은 50ms 임).

이 둘을 결합하면 내 작업 시간이 5900ms에서 4700ms로 증가하지만 재생 빈도가 낮을수록 진행률 막대가 부드럽지 않고 백그라운드 스레드 우선 순위를 MAX로 설정하는 것이 두려워요. 안전하지 않습니다.

내가 할 수있는 것 이상의 것이 있습니까?


편집 :

AsyncTask를 이제 리팩토링 정말 불가능하다. 척 노리스의 솔루션

내 업데이트 된 코드는 :

Activity.this.getHandler().sendEmptyMessage(
      MyMessages.SHOW_PROGRESS_BAR); 


Activity.this.getHandler().sendEmptyMessage(
      MyMessages.HIDE_PROGRESS_BAR); 

private Handler handler = new Handler() { 
    @Override 
    public void handleMessage(android.os.Message msg) { 

     switch (msg.what) { 
     case MyMessages.SHOW_PROGRESS_BAR: 
      Activity.this.progress.setVisibility(View.VISIBLE); 
      break; 
     case MyMessages.HIDE_PROGRESS_BAR: 
      Activity.this.progress.setVisibility(View.GONE); 
      break; 
     default: 
      break; 
     } 

    }; 
}; 

이 정말 내 응용 프로그램을 개선하고 더 이상 최대로 스레드 우선 순위를 설정할 필요가 없습니다, 그리고이었다 내 목표 중 하나.

하지만 여전히 애니메이션을 Android의 기본값 (ProgressBar를 50ms마다 새로 고침 함)으로 되돌리고 싶습니다. 그렇게하면 벤치 마크 작업에서 1 초를 잃습니다.

내 벤치 마크 : 동일한 작업의

평균 시간 : 핸들러와 안드로이드의 기본 진행 표시 줄과 함께 5.1s

  • : 핸들러와 안드로이드의 기본 진행 표시 줄없이

    1. 4.기가 (MAX에 스레드 우선 순위 같은 결과) 핸들러 모든 300ms를 새로 고침 사용자 지정 애니메이션
    2. : 3.8s

    어떤 생각 : 모든 150ms의 상쾌한 핸들러와 3.5 초

  • 및 사용자 지정 애니메이션을?

  • +0

    설명은 전체를 제어 할 수 AsyncTask를 사용하지 않을 이유가 있나요입니까? –

    +0

    리펙터를 수행하는 앱의 크기와 작업량이 크기 때문입니다. 벌써 예정되어 있지만, 지금 당장 할 시간이 없습니다. 그러나이 문제를 해결하기 위해 AsyncTasks를 만드는 것은 해결 될 것입니까? 나는 오늘 POC를 만들려고 노력할 것이다 –

    +0

    그래, 나는 onPreExecute에서 진행 막대를 시작하고 onPostExecute를 멈추면 당신이 묘사하는 행동을 표시하지 않을 것이라고 기대할 것이다 ... 확실히 가치있는 테스트 –

    답변

    1

    onClickListener처럼 활동에서 중간 진행률 표시 줄을 켜 봅니다. 그것을 끄기 위해서도 똑같이하십시오.

    새로운 스레드를 할당하고 시작하는 데 더 많은 시간이 걸릴 수 있습니다. 이것이 진행 막대를 제어하는 ​​새로운 Runnable()을 사용하여 수행하는 작업입니다.

    진행 표시 줄을 자체 스레드에서 제어하지 마십시오.

    +0

    나는 대신에 핸들러를 사용하려고 시도했다. 새로운 Runnable을 실행하면 정말 빠르게 실행됩니다. 너무 많지는 않지만 평균 400ms 더 빠릅니다. –

    1

    있도록 AsyncTask는 허용 작업의 종류를 실행하기위한 메커니즘이

    public class MyActivity extends Activity { 
        ProgressBar mProgressBar = (ProgressBar) findViewById(R.my_activity.progress_id); 
        DoTheWorkClass myInstanceOfClassThatDoesTheWork = new Object(); 
    
        class MyAsyncTask extends AsyncTask<Void, Void, Integer> { 
    
    
         @Override 
         protected void onPreExecute() { 
          mProgressBar.setVisibility(View.VISIBLE); 
         } 
    
         @Override 
         protected void onPostExecute(Integer result) { 
          mProgressBar.setVisibility(View.GONE); 
         } 
    
         @Override 
         protected Integer doInBackground(Void... params) { 
          return myInstanceOfClassThatDoesTheWork.doTheWork(); 
         } 
    
        } 
    } 
    
    관련 문제