Android 从不同线程访问 activity 上的相同实例方法,无需锁定。添加同步方法
Android Access Same instance method on activity from different threads without locking. Added synchronized method
我有一个方法 goToNextScreen()
可以检查 3 个不同的异步进程,所以当所有进程完成后,验证将更改 activity(有点像 Splash activity )
我的示例代码从 3 个不同的结果回调访问 activity 的方法 goToNextScreen() 更新每个进程的标志值并验证内部的其他标志。
到目前为止这种方法有效,但我有下一个问题:
这种方法有效吗?它是否存在某种僵局的风险?所有 threads/callbacks 不会同时访问该方法而导致验证错误?
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
所以它应该不允许同时从其他线程访问。仍然怀疑执行是否正确。
是的,使方法同步意味着它不能同时执行多次。如果第二个线程在它仍在执行时调用它,第二个线程将阻塞直到释放同步锁。
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
到目前为止,这种通过将同步添加到在访问它的线程上共享的 activity 实例的方法 goToNextScreen 成员的方法到目前为止已经奏效了。 (查看问题代码以获取解决方案)。尽管我需要添加一个看门狗以防万一某些线程传递来执行它应该只执行一次的代码。
我有一个方法 goToNextScreen()
可以检查 3 个不同的异步进程,所以当所有进程完成后,验证将更改 activity(有点像 Splash activity )
我的示例代码从 3 个不同的结果回调访问 activity 的方法 goToNextScreen() 更新每个进程的标志值并验证内部的其他标志。
到目前为止这种方法有效,但我有下一个问题:
这种方法有效吗?它是否存在某种僵局的风险?所有 threads/callbacks 不会同时访问该方法而导致验证错误?
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
所以它应该不允许同时从其他线程访问。仍然怀疑执行是否正确。
是的,使方法同步意味着它不能同时执行多次。如果第二个线程在它仍在执行时调用它,第二个线程将阻塞直到释放同步锁。
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
到目前为止,这种通过将同步添加到在访问它的线程上共享的 activity 实例的方法 goToNextScreen 成员的方法到目前为止已经奏效了。 (查看问题代码以获取解决方案)。尽管我需要添加一个看门狗以防万一某些线程传递来执行它应该只执行一次的代码。