如何从后台线程加载数据,异步更新UI

时间:2014-07-09 02:40:43

标签: java android multithreading android-asynctask lazy-loading

我在asyncTask类中创建了一个类FragmentActivity

    class aysncTask extends AsyncTask<Void, Void, Void>
    {
            @Override
            protected Void doInBackground(Void... params) {
                    assert(filterfiles != null);
                    while( !searchDone.getValue() )
                    {
                            filterfiles.searchTargetFile(android.os.Environment.getExternalStorageDirectory()+ "/");
                            publishProgress();      //Doesn't work here.
                    }
                    return null;
            }

            @Override
            protected void onProgressUpdate(Void... params)
            {
                    UpdateUI();                     //Only executes as the search is done.
            }

            @Override
            protected void onPostExecute(Void result)
            {
            }
    }

filterfiles.searchTargetFile(~)函数搜索本地数据,将其添加到ArrayList: cachedData。但我不能等待搜索完成然后更新UI。用户将等待太久。 但我不知道在哪里放置更新的UI代码。 它不能在方法onPostExecute(Void result)内,因为我仍然需要等待搜索完成。

它也可以在方法onProgressUpdate(Void params)内,因为一旦我调用filterfiles.searchTargetFile(~),它将搜索本地系统中的匹配文件。只有在搜索完成后,它才会调用publishProgress()

我想到的是创建另一个观察cachedData的线程,一旦找到文件,我将添加文件并更新UI。

但我不知道该怎么办?这是一个好习惯吗? 请提供一些建议的解决方案我在这个问题上花了两天时间。

更新     我设计了一种机制来实现加载数据和异步更新UI。当前 searchTargetFile代码:

 public void searchTargetFile(String path)
    {   
            File dirRoot= new File( path );  
            File[] dirOrFile= dirRoot.listFiles();

            if( dirOrFile == null) return;
            for( File f : dirOrFile )
            {   
                    if( f.isDirectory() )
                    {   
                            searchTargetFile( f.getAbsolutePath() );
                    }   
                    else                        
                    {   
                            for(String extName: filterFileExt)
                            {   
                                    if( f.getName().endsWith(extName) )
                                    {   
                                            newDisplayFile= new DisplayFile(new String( f.getAbsolutePath() ), f.length());
                                            this.searchedDisplayFile.add(newDisplayFile);
                                    }   
                            }   
                    }   
            }   
            this.searchDone.setValue(true); 
    }   

其中 newDisplayFile 该项目将被插入 searchingDisplayFile

*问题:

  1. 如何通过采用线程重写搜索代码,以便我可以pauseresumewait()notify()会有效吗?

  2. 应将wait()notify()代码放在 aysncTask 类的哪个位置?

  3. 赞赏任何其他更好的方法!!!

2 个答案:

答案 0 :(得分:0)

因此,我会在此处添加我的回答以供您发表评论,因为评论无法显示代码段。

因为我不知道您的数据是什么样的,所以让我们假设您有一个索引数据库,并且您希望搜索整个数据库,获取它们的列表。分页的想法是搜索有限的项目,保存偏移量以备将来使用,同时使用搜索到的项目更新列表。例如(伪代码):

int max_items = 10;
int offset = 0;
while(searchable) {
    List<Items> items_ = searchFromOffset(offset); // this will return up to 10 items each time
    update(items_); // call the progressUpdate here
    offset += items_.size(); // next time you will search from next "page"
    searchable = checkForFinish(); // return a boolean value showing if the searching is finish or not
}

真正的问题可能更复杂,但总体思路如上所示。这也有助于您为每个查询节省内存。

希望这有帮助。

答案 1 :(得分:0)

我使用 onProgressUpdate(progressValue); 而不是发布进度。这对我很有用。