AsyncTask中的Android执行方法

时间:2012-06-09 15:21:59

标签: android android-asynctask loading

我创建了一个生成带谷歌地图的用户界面并显示用户位置的活动,该活动的开头为:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.map_display);

    Button myLocationBtn = (Button)findViewById(R.id.myLocationBtn);
    Button searchRequest = (Button)findViewById(R.id.searchRequest);
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    myLocationBtn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            touched = false;
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
        }
    });
    searchRequest.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            locationManager.removeUpdates(locationListener);
            onSearchRequested();
        }
    });
    initialiseMapView();
  }

此屏幕需要一段时间才能加载,我认为这是实际调用和运行地图信息并获取用户位置的结果,该位置在我的方法initialiseMapView();中运行。所以我试着按如下方式介绍AsyncTask:

private class loadMap extends AsyncTask<String, Integer, String>{

    @Override
    protected String doInBackground(String... params) {
        initialiseMapView();
        return null;
    }
}

我在原始代码中更改的所有内容是我更改了initialiseMapView();到新的loadMap()。execute();.每当我尝试运行此活动时应用程序崩溃,我相信它是因为initialiseMapView方法不在loadMap类中,但我不确定。

请帮助:(


这是initialiseMapView方法:

private void initialiseMapView() {

      mapView = (MapView) findViewById(R.id.mapView);
      mapController = mapView.getController();

      locationListener = new GPSLocationListener();
      locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);

      mapView.setBuiltInZoomControls(true);
      mapView.setSatellite(false);

      GeoPoint startPoint = new GeoPoint((int)(51.500152 * 1E6), (int)(-0.126236 * 1E6));
      mapController.setCenter(startPoint);

      mapController.setZoom(mapView.getZoomLevel());

      mapController.setZoom(14);

      mapFromQuery("london");

      mapView.invalidate();
  }

如果无法做到这一点,我可以通过某种方式在内容加载时显示屏幕吗?

3 个答案:

答案 0 :(得分:1)

你不能打电话

  

initialiseMapView();

在doInBackground()方法中,因为它在与UI线程不同的线程上运行。

答案 1 :(得分:0)

你不能在initialiseMapView中做任何work related to UI,因为它是从doInBackground调用的,所以请确认一样............

答案 2 :(得分:0)

要扩展其他人所说的内容,您的AsyncTask子类应实现以下内容:

onPreExecute()在后台任务启动之前在UI线程上执行。这可能是初始化mapview的理想场所。

doInBackground()在后台执行,不得尝试执行任何UI功能。这是进行网络呼叫和下载地图数据的理想场所。

如果要从后台任务更新UI,请调用publishProgress(),这将导致在UI线程中调用onProgressUpdate()。

示例代码:

  class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
      protected Long doInBackground(URL... urls) {
      int count = urls.length;
      long totalSize = 0;
      for( int i = 0; i < count; ++i) {
          totalSize += Downloader.downloadFile(urls[i]);
          publishProgress((int)((i/(float)count)*100));
      }
      return totalSize;
      }

      protected void onProgressUpdate(Integer... progress) {
      setProgressPercent(progress[0]);
      }

      protected void onPostExecute(Long result) {
      showDialog("Downloaded " + result + " bytes");
      }
  }

  ...

  new DownloadFilesTask().execute(url1, url2, url3);

ETA:还有几件事需要考虑。每当你在后台运行一个线程时,你必须考虑前台任务可能随时消失的可能性。例如,如果用户在数据仍在加载时退出应用程序,或者用户甚至旋转设备。

如果onProgressUpdate()方法引用myMapView,请考虑myMapView可能不再是有效的MapView对象。 (我假设Android框架知道忽略不再相关的View对象的更新,否则应用程序将无处不在。)

如果你的后台任务是cpu密集型的,你可以考虑调用cancel()(例如在onStop()中),告诉后台任务放弃它的工作。或者更好的是,使用onRetainNonConfigurationInstance()将对后台线程的引用传递给应用程序的新实例,以便后台任务可以不间断地继续工作。