6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

概要

ViewModel が導入される前は、Activity や Fragment に通信処理や色々な処理を実装していました。
別クラスに分離して、処理を分けたとしてもUIに情報を通知するためにコールバックをひたすら実装することが多かったです。
ViewModel が導入され、UIと切り離して実装でき、通知も LiveData を使うことで楽に実装出来るようになったので、サンプルを記載したいと思います。

ViewModel 導入前

例えば、AsyncTask で、UIと重い処理をクラスで分けた場合、下記のような実装するかと思います。
UIで、CallBackを受け取って、UI操作をします。

public class MainTask extends AsyncTask<Void, Void, Long> {

  private Callback callback;
  public MainTask(CallBack callBack) {
    this.callback = callBack;
  }

  @Override
  protected Long doInBackground(Void... params) {
      // 重い処理
      if (ok) {
          return 0L;
      } else {
          return -1L;
      }
  }

  @Override
  protected void onPostExecute(Long result) {
    if (result == 0) {
      callback.onComplete();
    } else {
      callback.onError();
    }
  }

  public interface CallBackTask {
    public void onComplete();

    public void onError();
  }
}

ViewModel 導入後

LiveData を postValue することで、UI に通知することが可能です。
導入前と比較するため同様な記載をしていますが、MutableLiveData<Long> として、値を渡せますので、resultの結果を渡せばいいことになります。そのため、本来なら onError は不要かと思います。

public class MainViewModel extends ViewModel {
    private final MutableLiveData<Long> onComplete = new MutableLiveData<>();
    private final MutableLiveData<Long> onError = new MutableLiveData<>();

    public MainViewModel() {
        new MainTask().execute();
    }

    public LiveData<Long> getComplete() {
        return onComplete;
    }

    public LiveData<Long> getError() {
        return onError;
    }
    
    private class MainTask extends AsyncTask<Void, Void, Long> {

        @Override
        protected Long doInBackground(Void... params) {
            // 重い処理
            if (true) {
                return 0L;
            } else {
                return -1L;
            }
        }

        @Override
        protected void onPostExecute(Long result) {
            if (result == 0) {
                onComplete.postValue(result);
            } else {
                onError.postValue(result);
            }
        }
    }
}

UI側は、observe することで、変化があるたびに onChanged が呼ばれますので、それに適したUIを操作するだけになります。

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        mViewModel.getComplete().observe(this, new Observer<Long>() {
            @Override
            public void onChanged(Long result) {
                // UI操作
            }
        });
        mViewModel.getError().observe(this, new Observer<Long>() {
            @Override
            public void onChanged(Long result) {
                // UI操作
            }
        });
    }

今までは、必要なコールバックを interface で定義して、都度渡す必要がありましたが、ViewModel 側でUIに通知したい場合は、postValue する。
UI側は、observe で変化が合った場合にUIを操作するだけになります。

おまけ

ここまで対応すると、もう kotlin で実装した方がすごく楽になります。皆さんも kotlin を使っていきましょう。

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.1'
class MainViewModel : ViewModel(), CoroutineScope {

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    private val job = Job()

    val data = MutableLiveData<Long>()

    fun getData() {
        launch {
            // 重い処理
            if (true) {
                data.postValue(0)
            } else {
                data.postValue(-1)
            }
        }
    }
}
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        viewModel.data.observe(this, Observer {
            // UI操作
            if (it == 0L) {

            } else {

            }
        })
    }
6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?