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

android OS & iPadOS の記録。

代替え AsyncTask 【基礎】 ワーカースレッド。その弐。

2022-11-14 00:43:46 | Android studio 日記

ExecutorService のルールが良く分からない。迷走中。

スレッドプールを利用するときの宣言は1つのアプリで1回が望ましいらしい。
今使うのはシングルワーカースレッドなので使用場所で宣言でも良いのかもしれない。
実際に数十のワーカーを作っても1スレッドで順番に処理をしている。
特に不具合は感じられない。

ただ、これからスレッドプールを使ってワーカーの複数並列処理をしようとした時に癖で利用する場所で宣言してしまうかもしれない。もの凄く悪影響が出るので注意とデベロッパーサイトに記載されていた。
なので、Executor も一ヵ所で管理させる癖を付ける事にする。

複数のフラグメントで呼び出せるのでViewModelで宣言させる。(良いのかな?)

 

mViewModel.getValueExecutorService() 初回に呼んだ時にExecutorServiceを取得する。

public class MyViewModel extends ViewModel {

    private MutableLiveData< ExecutorService> executorService = null;
    public MutableLiveData< ExecutorService> getExecutorService() {
        if ( executorService == null ) {
            executorService = new MutableLiveData< ExecutorService>(Executors.newSingleThreadExecutor());
        }
        return executorService;
    }
    public ExecutorService getValueExecutorService() {
        return getExecutorService().getValue();
    }

    //省略
}


MainActivityで実体を作成する。

public class MainActivity extends AppCompatActivity {

    private MyViewModel mViewModel = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mViewModel = new ViewModelProvider(this).get(MyViewModel.class);
    }

    //省略
}


フラグメントでViewModelを呼び出しワーカースレッドへ渡す。

public class MainFragment extends Fragment {

    private MyViewModel mViewModel;


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

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

    }

    private void test() {

        //省略

        MyAsyncTask2 mAsyncTask = new MyAsyncTask2( mViewModel, null, index );
        mAsyncTask.execute( /* 引数 */ );

    }
    //省略

    @Override
    public void onDestroy() {
        super.onDestroy();

        mViewModel = null;
        //省略
    }
}


ワーカースレッド。一部分整理して簡潔に書き直し。

public class MyAsyncTask2 {

    private MyViewModel mViewModel;
    private RecyclerView mRecyclerView;
    private final int vID;
    //省略

    public MyAsyncTask2(MyViewModel data, RecyclerView rv, int id ) {
        super();

        mViewModel = data;
        mRecyclerView = rv ;
        vID = id;

        //省略

    }

    private class TaskRunnable implements Runnable {

        private String targetPath = "";
        public TaskRunnable(String param) { targetPath = param; }

        @Override
        public void run() {
            //省略。処理内容。

            new Handler(Looper.getMainLooper())
                    .post(() -> onPostExecute(retult));
        }
    }

    public void execute(String param) {
        mViewModel.getValueExecutorService().submit(new TaskRunnable(param));
    }

    void onPostExecute(int result) {

        if ( mRecyclerView == null ||
                mRecyclerView.getAdapter() == null ||
                mViewModel.getValueRecyclerView() == null ||
                mViewModel.getValueRecyclerView().getAdapter() == null ||
                !mRecyclerView.getAdapter().equals(mViewModel.getValueRecyclerView().getAdapter())//整理した
        ) {
            finish();
            return;
        }

        switch ( result ) {
            case 0:
                if ( vID < mRecyclerView.getAdapter().getItemCount() ) {
                        mRecyclerView.getAdapter().notifyItemChanged(vID);
                }
                break;
            //省略
        }

        finish();
    }
    private void finish() {
        mRecyclerView = null;
        mViewModel = null;
    }
}


【旧クラス】
public class MyAsyncTask2 {

    ExecutorService executorService;
    //省略

    public MyAsyncTask2(MyViewModel data, RecyclerView rv, int id ) {
        super();

        executorService  = Executors.newSingleThreadExecutor();

        //省略

    }

    private class TaskRunnable implements Runnable {

        @Override
        public void run() {
            //省略

            new Handler(Looper.getMainLooper())
                    .post(() -> onPostExecute(retult == 0));
        }
    }

    public void execute(String param) {
        targetPath = param;
        executorService.submit(new TaskRunnable());
    }

    void onPostExecute(boolean result) {

        //省略
    }
}