我正在从我的活动中启动一个新线程,该线程执行 10 秒操作,然后向 UI 报告runOnUiThread()
在 10 秒的操作期间,UI 变得无响应并且不响应任何用户交互。在这种情况下,我试图使用工具栏中的按钮关闭活动。引发ANR错误,但在工作线程完成后处理按钮单击。
虽然,当线程工作时,应用程序仍然能够显示旋转ProgressBar
,如果工作在 UI 线程上完成,则不会发生这种情况。
显示Profiler
UI 线程在此工作期间处于休眠状态,所以据我了解它应该是响应式的?我尝试过使用AsyncTask
,但这也不起作用。无论如何,这里有一些代码:
Thread
当窗口成为焦点时开始新的:
活动:
@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 秒 Room db 操作的方法。
这是Profiler
显示睡眠UI 线程和工作线程Thread
(AsyncTask #6)的快照:
编辑:
好的,所以我认为问题在于房间数据库操作 / viewModel
。getAllWords()
用释放的 UI 线程替换内容以Thread.sleep(10000);
进行用户交互,因此以下代码(出于某种原因)阻止了用户输入:
编辑2:
正如建议的那样,我现在使用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);
}
}
get()
已被删除,我只是执行任务,传入listener
处理回调:
public void getAllWordsWithCallBack(WordViewModel.iGetWords listener) {
try {
new GetAllWordsWithCallBackTask(wordDao, listener).execute();
} catch (Exception e) {
Crashlytics.log("Getting all words exception: "+e.getMessage());
e.printStackTrace();
}
}
这很好用,单词成功返回到我的活动,但在执行操作时UI 仍然无响应。