如何在Android中管理异步任务

时间:2016-05-10 10:05:21

标签: java android multithreading

在我的活动中,我使用一个线程来调用服务器并接收我放在内部存储上的XML响应。

在此调用之后,我读取此xml文件以解析它并向用户显示有关此xml文件的信息,但是当我在InputStream中添加此文件时,此InputStream为null。

我想我的活动继续简单执行,不要等待我的线程所以当我创建我的InputStream时,我的xml文件不存在。

我使这个模式对应于我的程序的执行:

Schema here

如何让我的活动等待我的线程结束?我知道冻结主要活动并不是一件好事,但我不知道我该怎么做。 我可以在线程结束时添加一个等待进度条直到我的线程上有一个观察者吗?

PS:我的线程实现了Runnable

/ *************用解决方案编辑************* /

首先,感谢所有人的回复,这让我取得了很大的进步。

//In my Activity

MyAsyncTask asyncTask = new MyAsynctask();
asynctask.execute();

//My Async class
public class MyAsynctask extends AsyncTask<Void,Void,Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Toast.makeText(getApplicationContext(), "calling server...", Toast.LENGTH_LONG).show();
    }

    @Override
    protected Void doInBackground(Void... params) {

        //Instance of calling class
        //Method of this instance to call the server and create a file in internal storage 
        //After that my file is stored with the server response
        return null;
    }


    @Override
    protected void onPostExecute(Void result){
        super.onPostExecute(result);

        Toast.makeText(getApplicationContext(), "Data received", Toast.LENGTH_LONG).show();

        FileInputStream inputStream = null;
        inputStream = openFileInput("myFile");                     

        data=XMl.parse(inputStream);                  
    }
}

我希望这篇文章和您的回复有用。

5 个答案:

答案 0 :(得分:0)

我还认为使用AsnycTask将适合您的用例。

您可以执行AsyncTask并继续阅读并解析onPostExecute中的回复。

干杯! :d

答案 1 :(得分:0)

在您的活动(或片段或......)上使用AsyncTask,如。 我通常实现一个AsyncResponse接口,以便更容易地在不同的Activity上重用AsyncTask:

  public void CopyDataBaseFromAsset() throws IOException {
    InputStream in  = context.getAssets().open(DATABASE_NAME);
    Log.e("sample", "Starting copying");
    String outputFileName = DATABASE_PATH+DATABASE_NAME;
    File databaseFile = new File( "/data/data/*YOUR PACKGE NAME*/databases");
    // check if databases folder exists, if not create one and its subfolders
    if (!databaseFile.exists()){
        databaseFile.mkdir();
    }

    OutputStream out = new FileOutputStream(outputFileName);

    byte[] buffer = new byte[1024];
    int length;


    while ((length = in.read(buffer))>0){
        out.write(buffer,0,length);
    }
    Log.e("sample", "Completed" );
    out.flush();
    out.close();
    in.close();

}

如果你使用m.execute()而不是executeOnExecutor,并且你有多个AsyncTask同时执行,那么如果你使用执行器,它们会并行执行。做你想做或需要的事。

AsyncTask类,它可以覆盖其他方法,如onPreExecute等。

    MyAsyncTask m = new MyAsyncTask(randomparameters, new AsyncResponse(){
                @Override
                public void onSuccess(Object result) { 
                    // Success!! do what you want
                }

                @Override
                public void onError() { 
                   // Manage errors here
                }
            });
    m.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

这里是界面(当然,您可以自定义方法):

public class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {

    private AsyncResponse response;

    public MyAsyncTask(randomparameters, AsyncResponse response) {
        // Constructor
        this.response = response;
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        // Implements your async code (call your server)
    }

    @Override
    protected void onPostExecute(Boolean result) {
            if (result) {
                // Here you can return the response of the server to the activity
                response.onSuccess(response);
            } else {
                response.onError();
            }
        }
    }

所有关于AsyncResponse界面都是可选的,但我总是实现它并帮助了我很多。

答案 2 :(得分:0)

 public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            new DownloadfromInternet().execute(server_url);

        }

//异步任务类     class DownloadFromInternet扩展了AsyncTask {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Shows Progress Bar Dialog and then call doInBackground
    }

    // Download  File from Internet
    @Override
    protected String doInBackground(String... f_url) {

        try {
        //make server call and store file in local
        } catch (Exception e) {
            Log.e("Error: ", e.getMessage());
        }
        return LOCAL_FILE_NAME;
    }


    @Override
    protected void onPostExecute(String local_file_url) {
        // read local_file_url

    }
}

答案 3 :(得分:0)

让你的活动等到执行结束不是一个好主意,因为它会冻结ui线程。如果任务太长会抛出ANR。 你有两个选择:

  1. 创建执行异步任务所需的参数和条件 然后调用它,提供异步任务是你的内部类 活动,做其余的操作,这取决于你的 异步任务导致异步任务的onPostExecute回调。

  2. 创建一个具有帮助您进行通信的方法的界面     从异步任务到您的实现类的结果。这是最好的     用于测试和/或将异步任务作为外部类的方法。一世     使用这种方法很多。在您的异步任务中定义public     将侦听器设置为您的接口的方法。制作您的活动     实现界面。完成异步任务后,进入     onPostExecute,如果listener不为null,则调用接口方法。在     你在activity中实现的方法,实现与之相关的逻辑     异步任务结果。

  3. 如果要对其进行测试,设置异步任务的接口回调总是一个好主意。

答案 4 :(得分:0)

我想我的活动继续简单执行,不要等待我的线程所以当我创建我的InputStream时,我的xml文件不存在。

- 正确

我是你的情况,我建议您在发出请求时启动加载对话框。获得响应后,将结果发送到在UI线程上运行的处理程序,覆盖它的handleMessage方法,即关闭对话框并显示信息的位置。

或者,使用AsynTask,这样更方便。