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

android OS & iPadOS の記録。

ProgressBar【基礎】グルグル ⑵ Fragment部分

2022-11-23 13:01:06 | Android studio 日記

とりあえずざっくり。後で無駄を削ぐ。
グルグル表示中は専用フラグを立ててUI操作が発生してもスルーさせる。念のために。

ワーカースレッド処理用のデータクラス作成。
ワーカースレッド内でtry/catchを使い例外発生を認知。
ワーカースレッドは停止するけどメインは引き釣られず動く事もあるのでエラー確認はきっちりと。

グルグル表示遅延スイッチONの場所は、一本の流れで分岐が無ければ直前でなくても良い。

MyMainModel と MainViewModel 見間違いそうで失敗した。いつかクラス名の変更をしよう。
あと、RecyclerViewのアクセスはメインスレッドでないと例外でるので一時移動。最後にメインに戻って設定もアリだけど、できるかどうか試した。


public class DirectoryFragment extends Fragment {
    private MainViewModel mViewModel;
    private RecyclerView mRecyclerView = null;

    private ImageView mButton = null;
    private View.OnClickListener mButtonClick;

    private MyAdaptrData aData = null;

    // 省略

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 省略

        mViewModel = new ViewModelProvider((ViewModelStoreOwner) requireContext()).get(MainViewModel.class);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_directory, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // 省略

        mButtonClick = v -> {
            if (mViewModel.getValueAllWaitFlag()) return;// UI操作をスルーさせる

            // 省略
        };

        mButton = view.findViewById(R.id.button);
        mButton.setOnClickListener(mButtonClick);

        // 省略

        mRecyclerView = view.findViewById(R.id.directory_recyclerview);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setVerticalScrollBarEnabled(false);
        mRecyclerView.setLayoutManager(
                new LinearLayoutManager( requireContext(), RecyclerView.VERTICAL, false ));

        File file;
        // 省略

        aData = new MyAdaptrData(
                mViewModel,
                mRecyclerView,
                // 省略
        );
        new MyTask_onViewCreated(aData).execute();
    }


    private static class MyAdaptrData {
        MainViewModel mViewModel = null;
        RecyclerView mRecyclerView = null;
        // 省略

        public MyAdaptrData(
            MainViewModel viewModel,
            RecyclerView rv,
            // 省略
        ) {
            mViewModel = viewModel;
            mRecyclerView = rv;
            // 省略
        }
        public MainViewModel getMainViewModel() { return mViewModel;}
        public RecyclerView getRecyclerView() { return mRecyclerView;}
        // 省略

        public void finish() {
            mViewModel = null;
            mRecyclerView = null;
            // 省略
        }
    }

    private static class MyTask_onViewCreated {
        ExecutorService executorService;
        MyAdaptrData aData_OVC;
        MyMainModel mMainModel;
        MyFileList_Directory fList;
        int pos = 0;

        public MyTask_onViewCreated(MyAdaptrData data) { // インスタンス時にデータを渡す場合
            super();
            aData_OVC = data;
            executorService = Executors.newSingleThreadExecutor();
            mMainModel = aData_OVC.getMainViewModel().getValueMyMainModel();
        }

        class Run_onViewCreated implements Runnable {//ワーカースレッド
            @Override
            public void run() {
                try {
                    fList = new MyFileList_Directory(aData_OVC.getFile());

                    // 省略 RecyclerView().scrollToPosition()設定用の位置算出部分
                    aData_OVC.getRecyclerView().post(new Runnable() {//メインスレッドのRecyclerViewにアクセス
                        @Override
                        public void run() { // ここだけメインスレッド
                            aData_OVC.getMainViewModel().setFileList_directory(fList);
                            aData_OVC.getRecyclerView().setAdapter(
                                    new MyDirectoryListAdapter( aData_OVC.getMainViewModel() )
                            );
                            aData_OVC.getRecyclerView().scrollToPosition( pos );
                        }
                    });

                } catch (Exception e) { /* 例外発生は起こりやすいのでキャッチする */;}

               new Handler(Looper.getMainLooper())
                       .post(MyTask_onViewCreated.this::onPostExecute); // メインスレッドに戻る
            }
        }

        void execute() { // execute(List<> list)とか、ここでデータを渡す事もOK。参照か、複製かを考える事
            onPreExecute();
            executorService.submit(new Run_onViewCreated());//ワーカースレッドへ移行
        }

        void onPreExecute() {//メインスレッド
            aData_OVC.getMainViewModel().setAllWaitFlag(true);//UI操作待機フラグON
            mMainModel.setProgressBarSW_ON();// ぐるぐる表示 遅延スイッチ
        }

        void onPostExecute() {//メインスレッド
            aData_OVC.getDirectoryName().setText(
                      aData_OVC.getMainViewModel().getValueFileList_directory().getTargetDirAbsolutePath());
            aData_OVC.getMainViewModel().setAllWaitFlag(false);//UI操作待機フラグOFF
            mMainModel.hideProgressCircle();// ぐるぐる非表示
        }
    }
    // 省略

}

 


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ProgressBar【基礎】グルグル ⑴ ON-OFFスイッチ部分

2022-11-23 12:55:05 | Android studio 日記

レイアウトは割愛。コードの工夫のみ。
グルグル表示の説明は表示のみが多く実際の稼働は思うように動作しない。初心者にはハードル高い。

グルグルを表示(ProgressBar.VISIBLE)して
ワーカースレッドで(処理)する。
処理後にメインスレッドに戻って
グルグルを非表示(ProgressBar.INVISIBLE)にする。

こんな回答で詳細はこちらへどうぞ。とリンク…。リンクをクリックする気は無い私^^;

いつも通り試行錯誤。
要領は、代替えAsyncTaskに割り当てる。
単純には動かない。

よくあるトラブルを潰す。
データの受け渡しを明確に記述して思い通りに手順が進んでいるか確認をしていく。
コード内容(綺麗?簡潔?)は気にしない。
動くかどうか。後でまとめれば良い。

という事で処理に必要なデータをまとめてクラスを作る。
場合によって、参照型か複製型でワーカースレッド処理へ渡す。
参照型は処理中にデータ元で変数の値の更新が発生すると問題が起こる場合がある。
そういう時は複製で渡す。


class test {
    ArrayList< String> buff;
    int index;
    
    public test( ArrayList< String> buf, int no ) {
        例/buff = buf; // 参照
        例/buff = new ArrayList<>(buf); // 複製

        index = no; // 複製

    }
    // 省略

    public void finish() { // 複製時は 念のため後処理。参照時clear()実行すると元データ消去されるので注意
        buff.clear();
    }
}


グルグルを表示のON-OFFだと短時間の時にグルグルフラッシュで気になる。
遅延実行とフラグを組み合わせて設定時間より早く処理完了なら表示はしない工夫。

public class MyMainModel {
    public MyMainModel(Context context) {
        mContext = context;
    }

    private Context mContext = null;
    public Context getContext() { return mContext;}

    // 省略

    public static boolean ON = true;
    public static boolean OFF = false;
    private boolean mProgressBarSW = false;

    public boolean getProgressBarSW() {
        return mProgressBarSW;
    }
    public void setProgressBarSW(boolean sw) {
        mProgressBarSW = sw;
    }
    public void setProgressBarSW_ON() {//スイッチON
        mProgressBarSW = ON;
        showProgressCircle();
    }

    private ProgressBar mProgressBar = null;
    public void setProgressCircle( ProgressBar pb ) {// レイアウト情報をセット
        mProgressBar = pb;
    }

    public void showProgressCircle() { // 0.1秒後でも処理が終わらずフラグがONなら表示する
        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                if ( getProgressBarSW() == ON )
                    mProgressBar.setVisibility(ProgressBar.VISIBLE);
            }
        },100);
    }

    public void hideProgressCircle() { // ワーカースレッド処理後に呼ぶ。非表示、スイッチOFFを実行
        mProgressBar.setVisibility(ProgressBar.GONE);
        setProgressBarSW(OFF);
    }


    public void finish() {
        mContext = null;
        mProgressBar = null;
        // 省略
    }

}

グルグルスイッチ小細工完了。

 


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする