【问题标题】:How to call a method into an AsyncTask class from outside?如何从外部将方法调用到 AsyncTask 类中?
【发布时间】:2013-02-09 21:08:02
【问题描述】:

我有两个简单的类:

public class MainActivity extends Activity {
    NetworkTask task;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        [...]       
        task = new NetworkTask();
        task.execute();
    }

public void myClickHandler(View view) {
    switch(view.getId()) {
        case R.id.button1:
            // Why this line crash?
            task.connection("127.0.0.1");
        break;
        }
    }
}

public class NetworkTask extends AsyncTask<String, Void, String> {
    Socket sock;
    volatile boolean running = true;

    public int connection(String url){
        try{
            sock = new Socket(url, 4567)
        }
        catch (IOException ex){
            Logger.getLogger(NetworkTask.class.getName()).log(Level.SEVERE, null, ex);
            return -1;
        }
    }

    public String doInBackground(String... strings) {

        // If I do this, it works well
        //connection(127.0.0.1);

        while(running)
        {
            [...]
        }

        return null;
    }   
}

正如我在从 AsyncTask 方法外部调用连接方法时评论的那样,应用程序崩溃更特别是 « sock = new Socket(...) » 行。但是当在 AsynTask 方法内完成连接调用时,会创建套接字。 我不明白为什么。

发生了什么事?

谢谢。

【问题讨论】:

    标签: android sockets android-asynctask


    【解决方案1】:

    这是因为当你这样做时

    task.connection("127.0.0.1");
    

    您仍在主 (UI) 线程中工作 - 您没有正确使用 AsyncTask。相反,您可以像使用普通课程一样使用它,因此,您会在新的 Android 版本上获得 NetworkOnMainThreadException

    但是,当您从doInBackground() 调用时,这意味着您通过execute 启动了AsyncTask,并且工作在一个单独的线程中完成,让一切正常工作。

    请记住,如果您在做非网络的事情,您仍然可以从外部呼叫。但是,我建议让您的 AsyncTask 尽可能少地依赖外部,因为 AsyncTasks 只运行一次。如果你想做更多的工作,你必须创建一个新实例,这意味着如果你依赖于 setter 方法或类似的方法,你必须确保再次调用这些方法,这使得这个简单的类比需要的更复杂。

    为了说明如何使用 AsyncTask,this 是一个很好的来源。当然还有official documentation

    【讨论】:

    • 好的,谢谢,我明白了。那么如何从 AsyncTask 调用一个方法以将其运行到“好”线程中呢?
    • @Flow 您在代码中使用了task.execute()。这就是你如何以正确的方式做到这一点。 execute() 将负责在非 UI 主题中运行 AsyncTask 代码。还请记住,您可以向execute() 提供参数,这些参数将传递给doInBackground()。因此,您仍然可以从 AsyncTask 外部指定 URL。
    • 当然,但我几乎不必在主循环启动后立即进行连接...在这种情况下,我可能会在调用 execute() 后很长时间创建新套接字 while主循环正在运行。你明白我的意思了吗?
    • @Flow 不幸的是我不明白你的意思。 AsyncTasks(对我来说)意味着线性执行 - 在后台做一些事情,然后在完成后发布回 UI 线程。如果你想多线程,我会说实际上使用单独的Threads/Runnables。
    • 好吧,我明白了。其实AsyncTask并不适合我用。无论如何,非常感谢您的回复!
    猜你喜欢
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 2021-01-30
    • 2012-07-02
    • 2023-03-23
    • 1970-01-01
    • 2011-05-10
    • 1970-01-01
    相关资源
    最近更新 更多