如何在 Asynctask 中调用 Mainactivity 方法进行后台工作?

Posted

技术标签:

【中文标题】如何在 Asynctask 中调用 Mainactivity 方法进行后台工作?【英文标题】:How to call the Mainactivity method in Asynctask for background work? 【发布时间】:2020-07-31 17:38:12 【问题描述】:

我想要一个方法(在 MainActivity 中)从 MyAsynctask 类(在 MainActivity 中)的 doInBackground(File... file) 方法中调用,并且该方法必须在后台工作,因为它需要时间并且我的应用程序会暂时停止工作并且没有出现我在onPreExecute() 方法中调用的任何对话框如何解决这里的问题是我的代码它工作得很好但花费了太多时间而且我的应用程序看起来挂起但实际上并非如此。

ArrayList<HashMap<String,String>> getPlayList(File rootFolder) 
    ArrayList<HashMap<String,String>> fileList = new ArrayList<>();

    try 
        File[] files = rootFolder.listFiles();
         //here you will get NPE if directory doesn't contains  any file,handle it like this.
        if (files != null) 
            for (File file : files) 
                if (file.isDirectory() && !file.isHidden()) 
                    if (true) 
                        fileList.addAll(getPlayList(file));
                    
                    else 
                        break;
                    
                 else if (file.getName().endsWith(".pdf")) 
                    HashMap<String, String> song = new HashMap<>();
                    song.put("file_path", file.getAbsolutePath());
                    song.put("file_name", file.getName());
                    fileList.add(song);
                
            
        
        return fileList;
     catch (Exception e) 
        return null;
    

Asynctask 类在下面..

private class AsyncTaskExample extends AsyncTask<File, String, ArrayList> 


    @Override
    protected ArrayList doInBackground(File... file) 

        ArrayList<HashMap<String,String>> songList=getPlayList(folder);
        if(songList!=null)
            for(int i=0;i<songList.size();i++)
                final String fileName=songList.get(i).get("file_name");
                final String filePath=songList.get(i).get("file_path");

            //saving filePath and filName in SQLite Database..
                saveFileToDatabase(filePath, fileName);

            
        
        return songList;
    

    @Override
    protected void onPreExecute() 
        super.onPreExecute();
        p = new ProgressDialog(MainActivity.this);
        p.setMessage("Please wait...Loading..");
        p.setIndeterminate(false);
        p.setCancelable(false);
        p.show();
    

    @Override
    protected void onPostExecute(ArrayList arrayList) 
        super.onPostExecute(arrayList);
        if (mFiles != null)
        
            p.dismiss();
        
        else
        
            p.show();
        
    

如何高效地完成工作?

解决方案

问题在于下面给出的这些代码行:

AsyncTaskExample taskExample = new AsyncTaskExample();
        folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
      //I was writing this below line..
        taskExample.doInBackground(folder);

      //but it should be like in line below..
      taskExample.execute(folder);

【问题讨论】:

如果可以将 AsyncTask 替换为另一个选项(可观察、协程),那将是最明智的选择。 【参考方案1】:

我建议你定义一个回调,并在你的异步任务的构造函数中传递它,这样你就可以通知你的主要活动在需要时显示对话框。

回调

public interface AsyncTaskExampleCallback 
    public void onShowDialog();
    public void onHideDialog();

异步任务

class AsyncTaskExample extends AsyncTask<File, String, ArrayList> 

    @Nullable
    private AsyncTaskExampleCallback callback = null;

    public AsyncTaskExample(@NotNull AsyncTaskExampleCallback callback) 
        this.callback = callback;
    

    @Override
    protected ArrayList doInBackground(File... file) 

        ArrayList<HashMap<String, String>> songList = getPlayList(folder);
        if (songList != null) 
            for (int i = 0; i < songList.size(); i++) 
                final String fileName = songList.get(i).get("file_name");
                final String filePath = songList.get(i).get("file_path");

                //saving filePath and filName in SQLite Database..
                saveFileToDatabase(filePath, fileName);

            
        
        return songList;
    

    @Override
    protected void onPreExecute() 
        super.onPreExecute();
        if (callback != null) 
            callback.onShowDialog();
        
    

    @Override
    protected void onPostExecute(ArrayList arrayList) 
        super.onPostExecute(arrayList);
        if (mFiles != null) 
            if (callback != null) 
                callback.onHideDialog();
            
         else 
            if (callback != null) 
                callback.onShowDialog();
            
        
    

主要活动

public class MainActivity extends AppCompatActivity implements AsyncTaskExampleCallback 

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        new AsyncTaskExample(this).execute();
    

    @Override
    public void onShowDialog() 
        //Show dialog here
    

    @Override
    public void onHideDialog() 
        //Hide dialog here
    

【讨论】:

当我发布问题时,我在 5 分钟后通过更改一些代码自己得到了结果:D BTW 非常感谢您发表您的意见.. @MdAman 你能用最终结果编辑你的帖子吗?我只是好奇。我很快就会用一个确切的例子来编辑我的帖子。 @MdAman 我编辑了我的帖子。这是一种优雅的方式。当然有一些生命周期需要处理,但这肯定不会造成问题。

以上是关于如何在 Asynctask 中调用 Mainactivity 方法进行后台工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 AsyncTask 中调用一个返回值函数

从Asynctask ONPostExecute调用片段方法

如何在将 Tablayout 与 viewpager 一起使用时从另一个片段调用 AsyncTask?

如何从android中的自定义适配器调用Activity asynctask

如何在 doInBackground 的 AsyncTask 中显示 toast

如何管理需要由 AsyncTask 调用的不同任务