Android Access来自不同线程的活动的相同实例方法,无需锁定。添加了同步方法

时间:2018-05-28 20:19:56

标签: android android-asynctask synchronized android-thread

我有一个方法goToNextScreen(),它检查3个不同的异步过程,所以当所有过程完成后,验证将改变活动(是一种Splash活动)

我的示例代码从3个不同的结果回调访问活动的方法goToNextScreen(),更新每个进程的标志值并验证其中的其他标志。

到目前为止,这种方法有效,但我有下一个问题:

这种方法有效吗?是否存在某种死锁的风险?所有线程/回调都不会同时碰撞访问该方法导致错误的验证?

class LoadingActivity extends Activity{

  public boolean isFetchDone, isAnimationDone, isServiceDone, watchDog;

  Presenter presenter;

  protected void onCreate(@Nullable Bundle savedInstanceState) {

    presenter(this);
    runAnimation();
    presenter.runGetXService();
    runFetchFromDB();
  }

  //do some generic isAnimationDone
  private void runAnimation(){

    //animator set and animation assumed to be correct...
    //...

    animatorSet.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
        // do anything before animation start
    }

    @Override
    public void onAnimationEnd(Animator animation) {
       isAnimationDone = true;
       goToNextScreen();
    }

    @Override
    public void onAnimationCancel(Animator animation) {
      // do something when animation is cancelled (by user/             developer)
    }

    @Override
    public void onAnimationRepeat(Animator animation) {
       // do something when animation is repeating
    }
});
  }

//Some example function to fetch data from x DB
  private void runFetchFromDB() {
        final Realm realm = RealmProvider.getInstance();
        final ThingDB db = new ThingDBImpl(realm);

        realm.beginTransaction();

        db.getData(10L)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<XData>() {
                    @Override
                    public void onCompleted() {
                        isFetchDone = true;
                        goToNextScreen();
                    }

                    @Override
                    public void onError(Throwable e) {
                        //we dont care about the result
                        isFetchDone = true;
                        goToNextScreen();
                    }

                    @Override
                    public void onNext(XData dataSaved) {
                        //Should i update isFetchDone here?
                });

        realm.cancelTransaction();
    }

    private synchronized void goToNextScreen(){
      if(!watchDog) return;

      if(isFetchDone && isAnimationDone && isServiceDone){
        changeActivityFaded(this, SomeOtherActivity);
        finish();
        watchDog = true;
      }
    }
}

class Presenter {

  Activity activity;

  Presenter(Activity activity){
    this.activity = activity;
  }

  public void runGetXService(){
    new Presenter.GetServiceAsyncTask().execute();
  }

  private class GetServiceAsyncTask extends AsyncTask<Void, Void, Response> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //do preparation for service response, etc, asumme all correct
        }

        @Override
        protected XResponse doInBackground(Void... voids) {
            try {
                return //Assume correct behaviour...
            } catch (NetworkConnectionException e) {
                return null;
            }
        }

        @Override
        protected void onPostExecute(XResponse xResponse) {
            super.onPostExecute(xResponse);
            ((LoadingActivity)activity).isServiceDone = true;
            ((LoadingActivity)activity).goToNextScreen();
        }
    }
}

修改

我已将方法goToNextScreen更改为synchronized,因此它不应允许同时访问其他线程。如果执行是正确的,仍然有疑问。

2 个答案:

答案 0 :(得分:1)

是的,使方法同步意味着它不能同时执行多次。如果第二个线程在它仍在执行时调用它,则第二个线程将阻塞,直到释放同步锁。

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

答案 1 :(得分:0)

到目前为止,这种方法通过将synchronized添加到访问它的线程上共享的活动实例的方法goToNextScreen成员到目前为止已经工作。 (查看解决方案的问题代码)。虽然我需要添加一个看门狗,以防一些线程传递执行它应该执行一次的代码。