2012-11-21 4 views
0

내 응용 프로그램은 API 레벨 10 (진저 브레드) 이상을 지원합니다. 그 중 하나는 이후 버전에서 완벽하게 작동하는 차트를 그리지 만 레벨 10 에뮬레이터를 실행하면 잘못된 캔버스 ID로 View.onDraw에 대한 추가 호출이 발생하며 이로 인해 화면이 공백이됩니다. (에뮬레이터뿐만 아니라 진저 브레드 폰에서 실행되는 누군가가 문제를보고 한 것입니다.)View.onDraw가 잘못된 캔버스로 호출되었습니다.

정상적인 작동은 onDraw를 두 번 호출하는 것입니다. 프레임 워크에서 처음으로 캔버스 ID를 가져오고, 두 번째로 내 호출에서 동일한 캔버스 ID를 전달하는 invalidate()를 호출합니다. 이 두 번의 호출은 레벨 10 에뮬레이터에서 발생하지만 다른 캔버스 ID가있는 세 번째 호출이 있습니다. 즉, 뷰에 속하지 않는 것이므로이 호출은이를 비 웁니다.

활동은 SherlockActivity에서 파생되어 작업 표시 줄을 제공하며, 이것이 문제의 원인이라고 생각합니다. 내 활동 클래스

관련 코드 :

public class Chart extends SherlockActivity implements OnGestureListener, OnDoubleTapListener, OnScaleGestureListener 
{ 
    public static boolean mDataSet = false; 

    private ChartView    mView; 
    private Menu     mMenu; 
    private GestureDetector  mDetector; 
    private ScaleGestureDetector mScaleDetector; 
    private ActionBar    mActionBar; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     mDataSet = false; 

     mActionBar = getSupportActionBar(); 
     mActionBar.setHomeButtonEnabled(true); 
     mActionBar.setDisplayHomeAsUpEnabled(true); 
     mActionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE); 

     mView = new ChartView(this, mCentreLat, mCentreLong, mRadius); 
     setContentView(mView); 
     setTitle(""); 

     Context context = getApplicationContext(); 

     mDetector = new GestureDetector(context, this); 
     mScaleDetector = new ScaleGestureDetector(context, this); 
    } 

    @Override 
    public void onConfigurationChanged(Configuration config) 
    { 
     super.onConfigurationChanged(config); 
     mDataSet = false; 
    } 

    // Menu handling 
    @Override 
    public boolean onCreateOptionsMenu(Menu menu) 
    { 
     mMenu = menu; 
     MenuInflater inflater = getSupportMenuInflater(); 
     inflater.inflate(R.menu.chart_menu, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) 
    { 
     boolean handled = true; 

     switch (item.getItemId()) 
     { 
     case android.R.id.home: 
     finish(); 
     break; 

     case R.id.viewOptions: 
      mDataSet = false; 
      Intent i = new Intent(getBaseContext(), ChartSettings.class); 
      startActivity(i); 
      break; 

     // Other menu options here... 

     default: 
      handled = false; 
     } 
     return handled; 
    } 

관련 코드 내보기 클래스 : 세 번째 호출이 진저 브레드 에뮬레이터 (또는 전화)로 발생하는 이유

public class ChartView extends View 
{ 

    public ChartView(Context context, float centreLat, float centreLong, float radius) 
    { 
     super(context); 
     mContext = context; 
     mCentreLat = centreLat; 
     mCentreLong = centreLong; 
     mRadius = radius; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) 
    { 
     // First time 
     // (We pick up the canvas id mCanvas from the parameter.) 
     // (Nothing much else relevant here, except this is where stuff 
     // gets initialized, then in setDataInfo(), mDataSet is set true 
     // and invalidate() is called at the end.) 
     if (!Chart.mDataSet) 
     { 
      setBackgroundColor(Color.WHITE); 
      mCanvas = canvas; 
      initPaint(); 
      setDataInfo();  // invalidate() called at end 
     } 
     else 
     { 
      // Second call to onDraw() with same canvas id comes here, 
      // then an unwanted third call with a different canvas id, only 
      // with the Level 10 (Gingerbread) emulator. 

      // This is where the various lines and shapes are plotted 
      // on the canvas (mCanvas) 
      plotLinesAndShapes(); 
     } 

사람이 설명 할 수주십시오? 효과는 화면이 비어 있음 (완전히 흰색 임)입니다.

이 함수에 도달하면 너무 늦어서 호출을 무시할 수 없습니다. 호출 스택이 unwind되면 화면이 공백이됩니다.

사용자가 메뉴에서보기 옵션을 선택한 다음 즉시 차트로 돌아가고 다시 그려지고 정상적으로 작동합니다.

답변

4

문제는 사용자가 매개 변수로받는 Canvas에 대한 참조를 유지하고 있다는 것입니다. 현재 프레임이 완료된 후이 Canvas 인스턴스가 유효하다는 보장은 없습니다. 예를 들어, 모든 프레임마다 다른 Canvas 인스턴스를받을 수 있습니다. 보기가 비트 맵 (예 : View.setDrawingCacheEnabled())으로 렌더링 될 때 일반적으로 다른 캔버스를받습니다.

mCanvas에서 참조를 유지하는 대신받은 캔버스를 plotLinesAndShapes()로 전달하면됩니다.

+0

Brilliant! 그것은 그것을 고쳤다. 문제는 내가 잘못된 문제를보고 있다는 것이 었습니다! 진저 브레드 버전에서 다른 캔버스를 사용하여 여분의 가짜 호출을 얻는 것이 문제라고 생각했지만 실제 문제는 onDraw에 대한 추가 호출을 허용해야한다는 것이 었습니다. 어떤 이유로 든 캔버스를 사용했습니다. 많은 감사합니다! 편집 : 사실, 내가 예제로 plotLinesAndShapes()로 주었던 것은 사실 여러 루틴에 대한 호출 이었기 때문에 모든 호출에 대해 매개 변수를 전달하지 않도록 mCanvas를 업데이트했습니다. 그래도 같은 효과. –

관련 문제