-1

我有一个方法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();
        }
    }
}

编辑:

我已将方法更改为goToNextScreensynchronized因此它应该不允许同时从其他线程访问。仍然怀疑 withs 的执行是否正确。

4

2 回答 2

1

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

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

于 2018-05-30T18:14:49.617 回答
0

到目前为止,这种通过将同步添加到在访问它的线程上共享的活动实例的方法 goToNextScreen 成员的方法已经奏效。(查看问题代码以获取解决方案)。虽然我需要添加一个看门狗,以防万一某个线程通过执行它应该只执行一次的代码。

于 2018-05-31T18:29:21.277 回答