タブレット用プログラムの書き止め

android OS & iPadOS の記録。

基礎。円形プログレスバーとThread & Runnable

2021-12-04 20:43:05 | Android studio 日記

画像切り替え、ディレクトリの移動など動作OKなので、重い処理で待機している時の円形プログレスバーを組み込みたい。

プログレス オン()
処理()
プログレス オフ()

やっちまった。
アンドロイドプログラミング初心者あるある。だそう。
OSは、マルチで動いていてもアプリはシングルらしい。
プログレスバーもメインスレッドの一部の時間を上手く使って動いてる。
処理が長時間占有するとプログレスバーは止まるという事。
プログレスバーはUIなのでメインで使うルール。
処理を別スレッドで実行させないとグルグルが回らない。

まず、円形プログレスバー。

【activity_main.xml】

    < ProgressBar
        android:id="@+id/progress_circular"
        style="@style/Widget.AppCompat.ProgressBar"
        android:layout_width="100dp"
        android:layout_height="100dp" />

大きさを変える時は、layout_width="100dp" サイズ指定。大きくしすぎるとボケる。
別デザインあり。ちょっと気に入らない。

 

要望などなど。
別スレッドを作る時に引数を渡して戻り値を受け取りたい。
メモリリークに注意する。
AsyncTask、Handlerは、非推奨になるらしい。
Thread、Runnableを使っての別スレッドを実行。

色々検索して、EventListener インターフェースを新設することで戻り値を受け取れると分かった。
スレッド内のメモリを解放、参照を切ること。

インターフェースは、これ。
テストでビットマップを受け取ってみる。

【MyEventListener.java】

public interface MyEventListener extends EventListener {
    void onMyEvent(Bitmap bitmap);
}

スレッドでの処理。

【MyRunnable.java】

public class MyRunnable implements Runnable {
    private MyMainData mainData;
    private MyEventListener mEventListener = null;
    private Bitmap mBitmap = null;

    MyRunnable(MyMainData mainData ) {
        this.mainData = mainData;
    }
    public void setEventListener( MyEventListener listener ) {
        this.mEventListener = listener;
    }
    public void removeEventListener() {
        this.mEventListener = null;
    }
    @Override
    public void run() {

        try {
            File file = new File(mainData.getTargetFilePath());
            InputStream isf1 = new FileInputStream(file);
            mBitmap = BitmapFactory.decodeStream(isf1);
            isf1.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if ( this.mEventListener != null && mBitmap != null ) {
            this.mEventListener.onMyEvent( mBitmap );
        }
        mainData = null;
        mEventListener = null;
        mBitmap = null;
    }
}

タイミング的に後始末が良いのか不安が残る。

 

イベントリスナー宣言内ではUI操作はエラーとならない。
受け取ったビットマップをコピーしてImageViewに設定している。
スレッド内で確保したビットマップをrecycle()で解放。
一時的に同じビットマップを2面利用するのが気になるが今はスルー。

【MainActivity.java】


    MyRunnable test = new MyRunnable( mainData );
    test.setEventListener( new MyEventListener() {
        @Override
        public void onMyEvent(Bitmap bitmap) {
            MyImageView view = mainData.getTargetImageView();
            view.scrollTo(0, 0);
            view.setImageBitmap( bitmap.copy( Bitmap.Config.ARGB_8888, true ) );
            mainPage.setPaddingImageView(view, bitmap.getWidth(), bitmap.getHeight());
            bitmap.recycle();
        }
    });
    Thread th = new Thread( test );
    th.start();

 

テストは動作問題なし。メモリ状況は確認できず。
どうなんだろう?