Issue
I have a method goToNextScreen()
which does a check for 3 different asynchronous process, so when all process are done the validation will changes activity (Is kind of a Splash activity)
My example code access from 3 different result callbacks to the activity's method goToNextScreen() updating the flag value for each process and to validate other flags inside.
So far this approach works but i have the next questions:
Is this approach valid? Does it have a risk for some kind of deadlock? all threads/callbacks won't collide accessing the method at the same time causing wrong validations?
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();
}
}
}
EDIT:
I have changed the method goToNextScreen
to synchronized
so it supposed to not allow access from others threads at the same time. Still have doubts if withs the execution will be right.
Solution
Yes, making the method synchronized means it cannot be executed multiple times simultaneously. If a second thread calls it while it is still executing, the second thread will block until the synchronization lock is released.
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Answered By - nasch
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.