我创建了一个生成带谷歌地图的用户界面并显示用户位置的活动,该活动的开头为:
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();
}
如果无法做到这一点,我可以通过某种方式在内容加载时显示屏幕吗?
答案 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()将对后台线程的引用传递给应用程序的新实例,以便后台任务可以不间断地继续工作。