前提・実現したいこと
ダイアログ内に設置したsurfaceviewで描画処理を行うコードを書いております。
ダイアログは枠外をタップすることで閉じるようにしており、
アクティビティレイアウトに設置したボタンを押すことで再度ダイアログを表示できるようにしてあります。
しかしダイアログを開く、閉じるを繰り返すうちに表示が重くなります。
そこでandroidProfilerでメモリをしらべたところ、生成したsurfaceviewのインスタンスが積み重なっていることに気づいたのですが
①なぜインスタンスがGCされずに積もるのか
②解消するにはどうすべきか
を教えていただきたいと思っております。
簡易レイアウト
該当のソースコード
java
1public class BaseActivity extends AppCompatActivity { 2 private DialogFragment dialogFragment; 3 private FragmentManager flagmentManager; 4 static DetailSurfaceView DetailSurfaceView; 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_base); 9 } 10 public static class AlertDialogFlagment extends DialogFragment{ 11 private AlertDialog dialog1; 12 private AlertDialog.Builder builder; 13 SurfaceView sv; 14 @Override 15 public Dialog onCreateDialog(Bundle savedInstanceState){ 16 builder =new AlertDialog.Builder(getActivity()); 17 View alertView =getActivity().getLayoutInflater().inflate(R.layout.detail,null); 18 builder.setView(alertView); 19 dialog1 =builder.create(); 20 this.setCancelable(true); 21 dialog1.show(); 22 return dialog1; 23 24 } 25 @Override 26 public void onStart(){ 27 super.onStart(); 28 29 sv=dialog1.findViewById(R.id.surface); 30 detailSurfaceView= new DetailSurfaceView(getContext(),sv); 31 } 32 @Override 33 public void onStop(){ 34 super.onStop(); 35 detailSurfaceView=null; 36 sv=null; 37 } 38 39 } 40 //ボタンID:showButtonからの呼び出し 41 public void showDialog(View view){ 42 flagmentManager = getSupportFragmentManager(); 43 dialogFragment = new AlertDialogFlagment(); 44 dialogFragment.show(flagmentManager,"test"); 45 } 46}
java
1public class DetailSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable { 2 static SurfaceHolder surfaceHolder; 3 Thread thread; 4 static int screen_width; 5 static int screen_height; 6 static long t; 7 public static final int FLAME =20; 8 public DetailSurfaceView(Context context,SurfaceView sv){ 9 super(context); 10 surfaceHolder =sv.getHolder(); 11 surfaceHolder.addCallback(this); 12 paint = new Paint(); 13 } 14 @Override 15 public void surfaceCreated(SurfaceHolder holder){ 16 if(thread == null){ 17 thread= new Thread(DetailSurfaceView.this); 18 } 19 thread.start(); 20 } 21 @Override 22 public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){ 23 screen_width=width; 24 screen_height=height; 25 } 26 @Override 27 public void surfaceDestroyed(SurfaceHolder holder){ 28 thread.interrupt(); 29 } 30 @Override 31 public void run(){ 32 t=0; 33 while(!thread.isInterrupted()){ 34 final long startTime = System.currentTimeMillis(); 35 final SurfaceHolder holder = surfaceHolderresult; 36 final Canvas canvas =holder.lockCanvas(); 37 if(canvas!=null){ 38 try{ 39 t++; 40 41 //描画処理 42 43 }finally { 44 holder.unlockCanvasAndPost(canvas); 45 } 46 } 47 final long elapsed =System.currentTimeMillis() - startTime; 48 final long wait = FLAME - elapsed; 49 if(0 < wait){ 50 try{ 51 Thread.sleep(wait); 52 }catch (final InterruptedException e){ 53 break; 54 } 55 } 56 } 57 thread=null; 58 } 59}
試したこと
onStop()を上書きしてdetailsurfaceview=null を実施しましたが、ダイアログを開いた数だけインスタンスが
残っているようです。(インスタンスが25あるということ以外、この画面の調べ方・使い方は存じ上げておりません。)
補足情報
実際のコードは変数名も読み手の方にとって煩わしい部分もございましたので質問用に変更しております。
私が現在心得ている(つもりになっている)のは、
・参照が切れないとGCされない
・インスタンスはnullを代入すると参照が切れる
の2点です。
ダイアログを開く回数を重ねるごとに重くなるのは、GCされていないことにあるのだと考えておりますが、
ダイアログを閉じる(キャンセルする)ごとに、中に設置しているsurfaceviewもきれいさっぱり無くすことが解決かと思っております。
そこで、これらdialogと、surfaceviewのコードの書き方に原因が見いだせずにおりますので、ご教授お願いいたします。
あなたの回答
tips
プレビュー