【发布时间】:2022-12-14 16:47:27
【问题描述】:
我是多线程概念的新手,也是 RxJava 的新手。我想我在我的 Android 项目中遇到了竞争条件。 为了能够更好地演示它,我下载了 google codelabs 示例 RoomWithAView 并实现了与我自己的项目中相同的竞争条件。
WordDao
@Dao
public interface WordDao {
@Insert()
void insert(Word word);
@Query("SELECT EXISTS(SELECT word FROM WORD_TABLE WHERE word = :word)")
Single<Integer> wordExists(String word);
}
词库
class WordRepository {
private WordDao mWordDao;
private boolean mWordRedundant;
private final CompositeDisposable mCompositeDisposable = new CompositeDisposable();
WordRepository(Application application) {
WordRoomDatabase db = WordRoomDatabase.getDatabase(application);
mWordDao = db.wordDao();
}
void insert(Word word) {
WordRoomDatabase.databaseWriteExecutor.execute(() -> {
mWordDao.insert(word);
});
}
public boolean isWordRedundant(String word) {
mCompositeDisposable.add(
mWordDao.wordExists(word)
.subscribeOn(Schedulers.computation())
.subscribe(integer -> mWordRedundant = integer == 1));
return mWordRedundant;
}
WordViewModel
public class WordViewModel extends AndroidViewModel {
private WordRepository mRepository;
public WordViewModel(Application application) {
super(application);
mRepository = new WordRepository(application);
}
public boolean isWordRedundant(String word) {
return mRepository.isWordRedundant(word);
}
public void insert(Word word) {
mRepository.insert(word);
}
}
新词活动
public class NewWordActivity extends AppCompatActivity {
public static final String EXTRA_REPLY = "com.example.android.wordlistsql.REPLY";
private EditText mEditWordView;
private WordViewModel mWordViewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_word);
mWordViewModel = new ViewModelProvider(this).get(WordViewModel.class);
mEditWordView = findViewById(R.id.edit_word);
final Button button = findViewById(R.id.button_save);
button.setOnClickListener(view -> {
Intent replyIntent = new Intent();
if (TextUtils.isEmpty(mEditWordView.getText())) {
System.out.println("Word empty");
setResult(RESULT_CANCELED, replyIntent);
}
// possible race condition?
else if (mWordViewModel.isWordRedundant(mEditWordView.getText().toString())) {
System.out.println("Word redundant");
setResult(RESULT_CANCELED, replyIntent);
}
else {
String word = mEditWordView.getText().toString();
System.out.println("Word acceptable");
replyIntent.putExtra(EXTRA_REPLY, word);
setResult(RESULT_OK, replyIntent);
}
finish();
});
}
}
在我的例子中,方法isPlayerNameRedundant()总是返回false。我在 App Inspection 中测试了 SQL 查询,它返回 1,所以 isPlayerNameRedundant() 方法应该返回 true。
我怀疑因为我在存储库中使用了Schedulers.computation(),所以查询是在后台线程上执行的,并且在该线程完成其任务之前,主线程返回mWordRedundant。
那是对的吗?
如果是这样,解决这个问题的方法是什么?
先感谢您。
【问题讨论】:
标签: java android rx-java rx-android