Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android:另一个线程正在使UI无响应?_Java_Android_Android Threading - Fatal编程技术网

Java Android:另一个线程正在使UI无响应?

Java Android:另一个线程正在使UI无响应?,java,android,android-threading,Java,Android,Android Threading,我正在从活动中启动一个新线程,该线程执行10秒的操作,然后使用runOnUiThread() 在10秒钟的操作过程中,UI将变得无响应,并且不会响应任何用户交互。在这种情况下,我试图使用工具栏中的按钮关闭活动。将抛出一个ANR错误,但在工作线程完成后将处理按钮单击 尽管如此,当线程工作时,应用程序仍然能够显示旋转的ProgressBar,如果在UI线程上完成工作,则不会出现这种情况 Profiler显示UI线程在此工作期间处于休眠状态,因此据我所知,它应该是响应的?。我试着改用AsyncTask

我正在从活动中启动一个新线程,该线程执行10秒的操作,然后使用
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