【问题标题】:Android - do something in MainActivity after AsyncTask is doneAndroid - 在 AsyncTask 完成后在 MainActivity 中做一些事情
【发布时间】:2014-05-08 12:46:33
【问题描述】:

我有一个AsyncTask class,它将执行HttpGet-request。我想在 AsyncTask 完成后做点什么,但在我的 MainActivity 内。

这是我的TaskGetAPI class

public class TaskGetAPI extends AsyncTask<String, Void, String>
{
    private TextView output;
    private Controller controller;

    public TaskGetAPI(TextView output){
        this.output = output;
    }

    @Override
    protected String doInBackground(String... urls){
        String response = "";
        for(String url : urls){
            HttpGet get = new HttpGet(url);
            try{
                // Send the GET-request
                HttpResponse execute = MainActivity.HttpClient.execute(get);

                // Get the response of the GET-request
                InputStream content = execute.getEntity().getContent();
                BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
                String s = "";
                while((s = buffer.readLine()) != null)
                    response += s;

                content.close();
                buffer.close();
            }
            catch(Exception ex){
                ex.printStackTrace();
            }
        }
        return response;
    }

    @Override
    protected void onPostExecute(String result){
        if(!Config.LOCALHOST)
            output.setText(result);
        else
            controller = Controller.fromJson(result);
    }

    public Controller getController(){
        return controller;
    }

这是我的 MainActivity 中我使用此类的方法:

private void sendGetRequest(){
        ...

        // Web API GET-request
        if(!get_url.equals("") && get_url != null){
            TaskGetAPI task = new TaskGetAPI(output);
            task.execute(new String[] { get_url });

            // TODO: When AsyncTask is done, do:
            controller = task.getController();
            Log.i("CONTROLLER", controller.toString());
        }
    }

如您所见,我在AsyncTaskonPostExecute-method 中设置了稍后使用的Controller

由于这与Async tasks 的全部目的背道而驰,我首先想到删除extends AsyncTask 并只为我的HttpGet 创建一个常规类和方法,但后来我得到一个android.os.NetworkOnMainThreadException,这意味着我需要使用一个AsyncTask(或类似的东西)在与我的MainThread不同的thread中使用HttpGet

那么,有人知道我应该在// TODO 上放什么吗?

我确实尝试使用getterboolean field (isDone) 添加到TaskGetAPI 类,然后使用:

while(true){
    if(task.isDone()){
        Controller controller = task.getController();
        Log.i("CONTROLLER", controller.toString());
    }
}

但随后会发生以下步骤:

  1. TaskGetAPI 类的doInBackground 已经完成。
  2. 现在我们被困在这个while(true)-loop..

并且永远不会调用将isDone 设置为trueonPostExecute

【问题讨论】:

    标签: android http asp.net-web-api android-asynctask get


    【解决方案1】:

    当任务完成时,它会调用 onPostExecute,所以你可以使用 LocalBroadcast 将广播消息发送到主活动。您可以使用使用异步方式的 sendBroadcast,即一次向所有侦听器发送广播,而不是 sendOrderedBroadcast。

    【讨论】:

    【解决方案2】:

    假设您只在 Activity 中使用 TaskGetAPI,您可以将 TaskGetAPI 定义为内部类,如 https://developer.android.com/guide/components/processes-and-threads.html#AsyncTask 中的示例

    public class MainActivity extends Activity {
    
        public class TaskGetAPI extends AsyncTask<String, Void, String> {
            /*
             * This object is instanced inside the MainActivity instance,
             * so it has access to MainActivity methods and members
             * (including private ones).
             * Remember to only access to UI elements like views from the main thread,
             * that is, only from onPreExecute, onProgress or onPostExecute
             * In this class "this" makes reference to the TaskGetAPI instance,
             * if you need a refeence to the MainActivity instance, use MainActivity.this
             * 
             */
    
            protected String doInBackground(String... urls){ ... }
    
            protected void onPostExecute(String result){
                mMyTextView.setText(result);
            }
        }
    
        private TextView mMyTextView;
        public void onCreate(Bundle savedInstanceState) {
    
            setContentView(R.layout.main);
            mMyTextView = (TextView) findViewById(R.id.view);
    
            new TaskGetAPI().exec();
        }
    
    }
    

    如果您需要使用TaskGetAPI,您可以在MainActivity外部定义它并定义一个子类作为MainActivity的内部类。

    还有其他选项,例如定义侦听器(如 onClickListeners)并在 onPostExecute 中调用它们,但这过于复杂。

    【讨论】:

      【解决方案3】:

      您可以发送带有来自 onPostExecute 的结果的广播以及响应。 Activity 会监听它并执行你想要的代码。

      while(true) 绝不是一个好主意,尤其是在电池寿命很重要的手机上。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-27
        • 2023-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-09
        • 2020-10-06
        相关资源
        最近更新 更多