Java Android:另一个线程正在使UI无响应?
我正在从活动中启动一个新线程,该线程执行10秒的操作,然后使用Java Android:另一个线程正在使UI无响应?,java,android,android-threading,Java,Android,Android Threading,我正在从活动中启动一个新线程,该线程执行10秒的操作,然后使用runOnUiThread() 在10秒钟的操作过程中,UI将变得无响应,并且不会响应任何用户交互。在这种情况下,我试图使用工具栏中的按钮关闭活动。将抛出一个ANR错误,但在工作线程完成后将处理按钮单击 尽管如此,当线程工作时,应用程序仍然能够显示旋转的ProgressBar,如果在UI线程上完成工作,则不会出现这种情况 Profiler显示UI线程在此工作期间处于休眠状态,因此据我所知,它应该是响应的?。我试着改用AsyncTask
runOnUiThread()
在10秒钟的操作过程中,UI将变得无响应,并且不会响应任何用户交互。在这种情况下,我试图使用工具栏中的按钮关闭活动。将抛出一个ANR错误,但在工作线程完成后将处理按钮单击
尽管如此,当线程工作时,应用程序仍然能够显示旋转的ProgressBar
,如果在UI线程上完成工作,则不会出现这种情况
Profiler
显示UI线程在此工作期间处于休眠状态,因此据我所知,它应该是响应的?。我试着改用AsyncTask
,但也不起作用。无论如何,这里有一些代码:
新的线程
在窗口聚焦时启动:
活动:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus && !recyclerSetup){
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.VISIBLE);
WorkThread thread = new WorkThread();
thread.start();
}
}
private class WorkThread extends Thread {
@Override
public void run() {
getViewModelAndWords();
runOnUiThread(() -> setupRecycler());
}
}
private void getViewModelAndWords() {
viewModel = ViewModelProviders.of(this).get(WordViewModel.class);
adapter = new WordDetailedAdapter(this, viewModel, this, this, !favGroup.equals(ANY_WORD_PARAM));
allWords = viewModel.getAllWords();
}
线程:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus && !recyclerSetup){
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.VISIBLE);
WorkThread thread = new WorkThread();
thread.start();
}
}
private class WorkThread extends Thread {
@Override
public void run() {
getViewModelAndWords();
runOnUiThread(() -> setupRecycler());
}
}
private void getViewModelAndWords() {
viewModel = ViewModelProviders.of(this).get(WordViewModel.class);
adapter = new WordDetailedAdapter(this, viewModel, this, this, !favGroup.equals(ANY_WORD_PARAM));
allWords = viewModel.getAllWords();
}
我不确定viewModel
是否与此问题有关,但它是viewModel.getAllWords()
方法,它执行了一个10秒的房间数据库操作
下面是探查器的快照
显示了休眠UI线程和工作线程线程
(AsyncTask#6):
编辑:
好的,所以我认为问题在于房间数据库操作/viewModel
。将getAllWords()
的内容替换为Thread.sleep(10000)代码>释放用户交互的UI线程,因此(出于某种原因)以下代码阻止用户输入:
编辑2:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus && !recyclerSetup){
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.VISIBLE);
WorkThread thread = new WorkThread();
thread.start();
}
}
private class WorkThread extends Thread {
@Override
public void run() {
getViewModelAndWords();
runOnUiThread(() -> setupRecycler());
}
}
private void getViewModelAndWords() {
viewModel = ViewModelProviders.of(this).get(WordViewModel.class);
adapter = new WordDetailedAdapter(this, viewModel, this, this, !favGroup.equals(ANY_WORD_PARAM));
allWords = viewModel.getAllWords();
}
根据建议,我现在使用onPostExecute()
和一个接口来检索单词:
public static class GetAllWordsWithCallBackTask extends AsyncTask<Void, Void, List<Word>>{
WordViewModel.iGetWords listener;
WordDao wordDao;
public GetAllWordsWithCallBackTask(WordDao wordDao, WordViewModel.iGetWords listener) {
this.listener = listener;
this.wordDao = wordDao;
}
@Override
protected List<Word> doInBackground(Void... voids) {
return wordDao.getAllWords();
}
@Override
protected void onPostExecute(List<Word> words) {
listener.gotWords(words);
}
}
这很好,文字已成功返回到“我的活动”,但在执行操作时,UI仍然没有响应。编辑1
在异步任务上调用.get()
。调用线程等待异步任务完成。您可以实现接口回调来解决此问题
编辑2:
我仔细查看了你的代码,再次强调,你在这里发布的代码没有错误
将AsyncTask与回调一起使用是一种可能的解决方案。您的代码在后台线程中运行,结果将传递给主线程而不阻塞它
我认为您的错误在于将数据从回调传输到ViewModel或MainActivity。
解决这个问题的最好办法是使用
我试图尽可能地重建您的代码。也许这会帮助你发现错误
WordDb
@数据库(实体={Word.class},版本=3)
@类型转换器(DateConverter.class)
公共抽象类WordDb扩展了RoomDatabase{
私有静态WordDb实例;
公开摘要WordDao WordDao();
静态同步WordDb getInstance(上下文上下文传递){
if(实例==null){
INSTANCE=Room.databaseBuilder(contextPassed.getApplicationContext(),WordDb.class,“word\u db”)
.fallbackToDestructiveMigration()
.build();
}
返回实例;
}
}
WordRepo
class-WordRepo{
私密字道字道;
WordRepo(上下文应用程序上下文){
WordDb-WordDb=WordDb.getInstance(applicationContext);
wordDao=wordDb.wordDao();
}
void getAllWords(WordRepo.iGetWords侦听器){
试一试{
Log.i(“WordRepo”,String.format(“从%s调用的getAllWords()”,Thread.currentThread().getName());
新建GetAllWordsWithCallBackTask(wordDao,listener).execute();
}捕获(例外e){
e、 printStackTrace();
}
}
公共静态类GetAllWordsWithCallBackTask扩展了AsyncTask{
WordRepo.iGetWords侦听器;
字刀字刀;
GetAllWordsWithCallBackTask(WordDao WordDao,WordRepo.iGetWords侦听器){
this.listener=listener;
this.wordDao=wordDao;
}
@凌驾
受保护列表背景(无效…无效){
Log.i(“WordRepo”,String.format(“从%s调用的GetAllWordsWithCallBackTask.doInBackground()”,Thread.currentThread().getName());
返回wordDao.getAll();
}
@凌驾
受保护的void onPostExecute(列出字){
Log.i(“WordRepo”,String.format(“从%s调用的GetAllWordsWithCallBackTask.onPostExecute()”,Thread.currentThread().getName());
倾听者。gotWords(单词);
}
}
公共接口iGetWords{
无效单词(列出单词);
}
}
MainViewModel
public类MainViewModel扩展了AndroidViewModel{
MutableLiveData wordList=新的MutableLiveData();
私有静态最终字符串TAG=“MainViewModel”;
public MainViewModel(@NonNull应用程序){
超级(应用);
}
void getAllWords(){
Log.i(标记,String.format(“从%s调用的getAllWords()”,Thread.currentThread().getName());
WordRepo repo=newwordrepo(getApplication());
repo.getAllWords(新单词repo.iGetWords(){
@凌驾
公共词(列表词){
wordList.setValue(单词);
}
});
}
}
MainActivity中的getViewModelAndWords()
private void getViewModelAndWords(){
Log.i(标记,String.format(“从%s调用的getViewModelAndWords()”,Thread.currentThread().getName());
viewModel=ViewModelProviders.of(this.get)(MainViewModel.class);
viewModel.wordList.observe(这个,新的观察者(){
@凌驾
公共v