【问题标题】:AsynchTask:Only one Looper may be created per threadAsynchTask:每个线程只能创建一个 Looper
【发布时间】:2016-02-07 11:40:29
【问题描述】:

我的应用在每 4-5 次调用时崩溃。它向我展示了以下异常。

10-14 14:00:30.651: E/AndroidRuntime(25035): FATAL EXCEPTION: AsyncTask #1
10-14 14:00:30.651: E/AndroidRuntime(25035): java.lang.RuntimeException: An error occured while executing doInBackground()
10-14 14:00:30.651: E/AndroidRuntime(25035):    at android.os.AsyncTask$3.done(AsyncTask.java:299)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at java.lang.Thread.run(Thread.java:838)
10-14 14:00:30.651: E/AndroidRuntime(25035): Caused by: java.lang.RuntimeException: Only one Looper may be created per thread
10-14 14:00:30.651: E/AndroidRuntime(25035):    at android.os.Looper.prepare(Looper.java:80)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at android.os.Looper.prepare(Looper.java:75)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at com..SplashActivity$LocationUpdator.doInBackground(SplashActivity.java:118)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at com..SplashActivity$LocationUpdator.doInBackground(SplashActivity.java:1)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
10-14 14:00:30.651: E/AndroidRuntime(25035):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)  

这是我的代码。

public class LocationUpdator extends AsyncTask<Void, Void, Location> {
 Location location123 = null;



@Override
protected Location doInBackground(Void... arg0) {

    Looper.prepare();
    mThreadLooper = Looper.myLooper();          
    locationListener = new LocationListener() 
     {
     private String subLocality;
    @Override 
     public void onLocationChanged(Location location1) { 


         if(mThreadLooper != null)
            mThreadLooper.quit();
         //Stopping Request for Location
         if(manager!=null)
             manager.removeUpdates(locationListener);
     } 

    String status="success";


        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            // if GPS provider is not enable then popup alertbox
            buildAlertMessageNoGps();
        } else {        
            // if gps is one then start searching                    
            status = "networkandgps";
            manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000,1000,  locationListener); 
        }
    }

        manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Log.i("TEST","Starting Network Provider");
        manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 10,locationListener);
        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            //buildAlertMessageNoGps();
            ;
        } else {
            manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100000,100000,locationListener);               
        }
    } else {           

        manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 10,locationListener);            
    }

     Looper.loop();
    return location123;
}

@Override
protected void onPostExecute(Location result) {


    //progressDialog.dismiss();
    if(result!=null)
    {               
        Log.i("TESTING SPLASH","Lat3 "+userLocationLat);
        Log.i("TESTING SPLASH ","Long3 "+userLocationlong);

        startApplication();         

    }           

} }

我也尝试在 onstop 方法中退出循环。但没有帮助。我知道在异步任务中使用 looper 很奇怪,但是还有其他方法可以在异步任务的 doInBackground 方法中使用位置侦听器。

请提示我为什么会收到此错误。

【问题讨论】:

  • 从逻辑上讲,您不应该在 AsyncTaskdoInBackground 中使用 Loopers。如果你这样做了,那么你真的需要重新考虑AsyncTask 的设计。否则它会破坏使用这个复杂类的目的。

标签: android android-asynctask looper


【解决方案1】:

它崩溃是因为 AsyncTask 的线程被用作 ThreadPool (这意味着它是相同的 4 或 5 个线程使用和重复使用。说答案的第一部分是:

不!你不能在 AsyncTask 中使用 Looper,因为Only one Looper may be created per thread

再想一想,你为什么还要使用这个 Looper?它在您的代码中没有做任何事情。如果您认为因此在后台线程中调用了侦听器,那么我有一个坏消息。它不是!侦听器将在它想要调用的任何线程中被调用,通常是 UI 线程。如果要避免 UI 线程中长时间运行的进程(例如网络),则应从 public void onLocationChanged(Location) 方法启动一个新线程(或新的 AsyncTask)。将 Listener 代码放在 protected Location doInBackground(Void... arg0) 中只会使您的代码阅读起来非常混乱,而在实际执行中没有任何区别。

希望对你有帮助。

编辑:

在 Android 4.0(或 3.0,不确定)及更高版本中,它是一个 SingleThreadPool,这使得 Loopers 的混乱更加紧张。

【讨论】:

    猜你喜欢
    • 2016-03-19
    • 2012-01-16
    • 2011-04-22
    • 2014-05-27
    • 2019-05-05
    • 2019-01-22
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多