【问题标题】:Android Async Task not executing when creating New object创建新对象时未执行Android异步任务
【发布时间】:2016-03-18 15:58:16
【问题描述】:

单击复选框时,我的应用程序会执行异步任务。我不能让它多次记录一条消息。它在第一次点击时会发生,但不会再次发生。在环顾其他问题后,我确定我必须构建一个自定义类,当然还要调用 new MyAysncTask (我已经在做),但它仍然无法正常工作。

这是单击复选框时执行的代码。

cbJoining.setOnClickListener(new OnClickListener()
{
    public void onClick(View v)
    {
        new MyAsyncTask(EventID, cbJoining.isChecked(), URL_Race, sDates, sState ).execute();
    }
});

这是自定义类

class MyAsyncTask extends AsyncTask<Void, Void, Void>{  

    public String EventID;
    public boolean bJoin;
    public String URL_Race;
    public String sDates;
    public String sState;

    public MyAsyncTask( String myEventID, boolean mybJoin, String myURL_Race, String mysDates, String mysState){
        super();
        EventID = myEventID;
        bJoin = mybJoin;
        URL_Race = myURL_Race;
        sDates = mysDates;
        sState = mysState;
    }

    protected void onPreExecute() { 
    };

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

        //Looper.prepare();

        API oAPI = new API();
        oAPI.Join(mPrefs, EventID, bJoin, URL_Race, sDates, sState);

        Log.d("ASYNCTASK", URL_Race);

        //Looper.loop();

        return null;
    }

    protected void onPostExecute(Void result) {
        Log.d("ASYNCTASK", "Finished");
    };
}

这是一个例外: 07-16 12:45:10.286:E/AndroidRuntime(28309):致命异常:AsyncTask #2

07-16 12:45:10.286: E/AndroidRuntime(28309): java.lang.RuntimeException: 执行 doInBackground() 时出错

07-16 12:45:10.286: E/AndroidRuntime(28309): 在 android.os.AsyncTask$3.done(AsyncTask.java:299)

07-16 12:45:10.286: E/AndroidRuntime(28309): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)

07-16 12:45:10.286: E/AndroidRuntime(28309): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)

07-16 12:45:10.286: E/AndroidRuntime(28309): at java.util.concurrent.FutureTask.run(FutureTask.java:239)

07-16 12:45:10.286: E/AndroidRuntime(28309): 在 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)

07-16 12:45:10.286: E/AndroidRuntime(28309): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)

07-16 12:45:10.286: E/AndroidRuntime(28309): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)

07-16 12:45:10.286: E/AndroidRuntime(28309): at java.lang.Thread.run(Thread.java:856)

07-16 12:45:10.286: E/AndroidRuntime(28309): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

07-16 12:45:10.286: E/AndroidRuntime(28309): 在 android.os.Handler.(Handler.java:197)

07-16 12:45:10.286: E/AndroidRuntime(28309): 在 android.os.Handler.(Handler.java:111)

07-16 12:45:10.286: E/AndroidRuntime(28309): 在 android.app.Activity.(Activity.java:759)

07-16 12:45:10.286: E/AndroidRuntime(28309): at com.chartermatrixllc.motocrossmatrix.API$FB.(API.java:88)

07-16 12:45:10.286: E/AndroidRuntime(28309): at com.chartermatrixllc.motocrossmatrix.API.Join(API.java:125)

07-16 12:45:10.286:E/AndroidRuntime(28309):在 com.chartermatrixllc.motocrossmatrix.Race$MyAsyncTask.doInBackground(Race.java:207)

07-16 12:45:10.286: E/AndroidRuntime(28309): at com.chartermatrixllc.motocrossmatrix.Race$MyAsyncTask.doInBackground(Race.java:1)

07-16 12:45:10.286: E/AndroidRuntime(28309): 在 android.os.AsyncTask$2.call(AsyncTask.java:287)

07-16 12:45:10.286: E/AndroidRuntime(28309): at java.util.concurrent.FutureTask.run(FutureTask.java:234)

07-16 12:45:10.286: E/AndroidRuntime(28309): ... 4 更多

【问题讨论】:

  • 我不确定这是否是您的问题,但从这段代码中我看不出需要Looper.prepare()Looper.loop()。如果您确实需要它,那么您应该在某处致电Looper.quit()

标签: android android-asynctask


【解决方案1】:

你可能在 Android 4+ 上工作,从那个版本开始,AsyncTask 只有一个线程,你用

阻止了它
    Looper.prepare();

    Log.d("ASYNCTASK", "Clicked");

    Looper.loop();

所以现在你有几个选择:

1) 使用方法AsyncTask.executeOnExecutor 并为您自己的执行程序提供一定数量的线程,例如Executors.newCachedThreadPool()

2) 停止阻塞AsyncTask 线程

【讨论】:

  • 假设我想做更多而不是 Log,比如下载一些 JSON,我怎样才能停止阻塞线程?当我删除 Looper.prepare 和 Looper.loop() 时,在执行下载数据等长任务时出现异常,告诉我必须包含 looper.prepare()
  • 如果你只想做一个长时间运行的任务,你不需要调用Looper.prepare(); Looper.loop();。只需为此任务编写代码即可。
  • 我认为但是没有它我在第一次调用它时会得到这个异常:无法在没有调用 Looper.prepare() 的线程内创建处理程序我只是想将一些数据发布到服务器不止一次
  • 为什么要在AsyncTask里面创建一个Handler?
  • 我不确定为什么它甚至会抛出该错误。我没有创建处理程序
【解决方案2】:

由于多种原因,Looper 不应附加到 AsyncTask 中的工作线程,其中主要的两个原因是:

  1. 如果调用Looper.loop(),则工作线程将忙于处理和等待传入的消息,即阻塞线程,以便无法执行其他任务。这总是一件坏事,但它是 API 级别 11 之后的应用程序性能杀手,AsyncTask.execute() 按顺序处理任务,使连续的任务等待阻塞任务完成。
  2. 即使只调用Looper.prepare(),工作线程也与消息队列相关联。这只能执行一次,因此第二次执行任务并再次调用Looper.prepare(),会抛出RuntimeException。因此,AsyncTask 只能执行一次。

从代码示例中不清楚为什么您需要在工作线程上使用Looper,但如果这是必需的,则不应使用AsyncTask,而应使用HandlerThreadHandlerThread 是一个带有Looper 的后台线程。缺点是您必须自己处理 UI 线程和后台线程之间的消息传递。

【讨论】:

  • 我添加了 Looper.loop(),因为当我在没有它的情况下运行应用程序时出现异常,指出 无法在未调用 Looper.prepare() 的线程内创建处理程序 我只是想多次向服务器发布一些数据。
  • Handler 是在哪里创建的?在您的代码或平台/库代码中?
  • 我很抱歉,处理程序线不应该在那里。我最初是从另一个可以运行的应用程序中的代码开始的,但我认为新 API 的更改已经破坏了它。我花了很多时间尝试了多种我在网上找到的解决方案,但都没有成功,并且其中一个测试留下了 Handler 行。现在我正在按照您的建议调查 HandlerThread。我显然一无所知,并且可能对各种 API 级别的众多示例感到困惑。
  • 从您添加的堆栈跟踪中,创建 Handler 的是 motocrossmatrix-library,这就是为什么要求后台线程具有 Looper 的原因。这将由 HandlerThread 解决,在 API 级别之间保持不变。
【解决方案3】:

试试这个,

runOnUiThread(new Runnable() {
            @Override
            public void run() {
        new MyAsyncTask(EventID, cbJoining.isChecked(), URL_Race, sDates, sState ).execute();
            }
        });

对于任何其他与 AsyncTask 相关的疑问,您可以参考, https://stackoverflow.com/a/36078608/2249287

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多