Android 谷歌地图v2从堆栈中弹出其片段后会延迟
我有一个带有Android 谷歌地图v2从堆栈中弹出其片段后会延迟,android,android-fragments,android-maps-v2,Android,Android Fragments,Android Maps V2,我有一个带有映射片段的活动,我使用片段事务以编程方式将其添加到活动: private static final String MAP_FRAGMENT_TAG = "map"; private MapFragment mapFragment = null; ... protected void onCreate(Bundle savedInstanceState) { ... mapFragment = (MapFragment) getFragmentManager()
映射片段的活动
,我使用片段事务
以编程方式将其添加到活动
:
private static final String MAP_FRAGMENT_TAG = "map";
private MapFragment mapFragment = null;
...
protected void onCreate(Bundle savedInstanceState) {
...
mapFragment = (MapFragment) getFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG);
if (mapFragment == null) {
mapFragment = MapFragment.newInstance();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.fragment_wrapper, mapFragment, MAP_FRAGMENT_TAG);
fragmentTransaction.commit();
}
...
}
标准方式。然后我从mapFragment
获取GoogleMap
实例,设置它的设置,设置监听器,用它做一些事情。一切正常
然后,当用户完成映射时,将触发一个异步任务
,以显示一个进度对话框
,执行一些操作,将不同的片段放入片段包装器
,并再次关闭进度对话框
:
private class GetFlightsTask extends AsyncTask<Double, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// the activity context has been passed to the AsyncTask through its constructor
loadingFlightsSpinner = new ProgressDialog(context);
// setting the dialog up
loadingFlightsSpinner.show();
}
@Override
protected String doInBackground(Double... params) {
// some pretty long remote API call
// (loading a JSON file from http://some.website.com/...)
}
@Override
protected void onPostExecute(String flightsJSON) {
super.onPostExecute(flightsJSON);
// here I do stuff with the JSON and then I swtich the fragments like this
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
FlightsFragment fragment = new FlightsFragment();
fragmentTransaction.replace(R.id.fragment_wrapper, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
loadingFlightsSpinner.dismiss();
}
私有类GetFlightsTask扩展异步任务{
@凌驾
受保护的void onPreExecute(){
super.onPreExecute();
//活动上下文已通过其构造函数传递给AsyncTask
LoadingFlightsPinner=新建进度对话框(上下文);
//设置对话框
加载FlightsPinner.show();
}
@凌驾
受保护的字符串背景(双参数){
//一些相当长的远程API调用
//(从加载JSON文件)http://some.website.com/...)
}
@凌驾
受保护的void onPostExecute(字符串flightsJSON){
super.onPostExecute(flightsJSON);
//在这里,我使用JSON做一些事情,然后像这样切换片段
FragmentTransaction FragmentTransaction=getFragmentManager().beginTransaction();
FlightsFragment片段=新的FlightsFragment();
fragmentTransaction.replace(R.id.fragment\u包装,fragment);
fragmentTransaction.addToBackStack(空);
fragmentTransaction.commit();
加载FlightsPinner.Disclose();
}
一切仍然正常。用户在飞行片段中做了一些事情,然后可能决定返回地图。按下后退按钮,地图再次弹出。这时地图变得滞后。地图上的国家/城市名称加载非常缓慢,移动地图时严重滞后…我不知道为什么,我不知道o任何关于弹出MapFragment
的内容
有趣的是,它得到了修复,例如按下主页按钮,然后再次返回应用程序
我做错了什么
谢谢你的建议。只有按“后退”按钮才会延迟吗
如果这是问题所在,请尝试阻止后退按钮或使其退出应用程序,尝试以下代码:
@Override
public void onBackPressed(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("You wanna leave the aplication?").setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
}
或者试试这段代码,这是一种将地图片段放入另一个片段(嵌套地图片段)的方法,它在一周前为我工作:
Java类:
public class Yourfragment extends Fragment {
private MapView mMapView;
private GoogleMap mMap;
private Bundle mBundle;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflatedView = inflater.inflate(R.layout.map_fragment, container, false);
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
// TODO handle this situation
}
mMapView = (MapView) inflatedView.findViewById(R.id.map);
mMapView.onCreate(mBundle);
setUpMapIfNeeded(inflatedView);
return inflatedView;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBundle = savedInstanceState;
}
private void setUpMapIfNeeded(View inflatedView) {
if (mMap == null) {
mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap();
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onDestroy() {
mMapView.onDestroy();
super.onDestroy();
}
}
XML:
并在oncreateview上调用assynctask
试试这个:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Call assyncTask
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBundle = savedInstanceState;
}
private void setUpMapIfNeeded(View inflatedView) {
if (mMap == null) {
mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap();
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onDestroy() {
mMapView.onDestroy();
super.onDestroy();
}
private class GetFlightsTask extends AsyncTask<Double, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// if I remove the next line, everything gets fixed
loadingFlightsSpinner.show();
}
@Override
protected String doInBackground(Double... params) {
// some pretty long remote API call
// (loading a JSON file from http://some.website.com/flights?...)
// works fine
String flightsJSON = loadJSON("flights?flyFrom=CZ&to=...");
}
@Override
protected void onPostExecute(String flightsJSON) {
super.onPostExecute(flightsJSON);
loadingFlightsSpinner.dismiss();
// here I do stuff with the JSON and then replace the fragment
dohardwork()
}
public view dohardwork(){
View inflatedView = inflater.inflate(R.layout.map_fragment, container, false);
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
// TODO handle this situation
}
mMapView = (MapView) inflatedView.findViewById(R.id.map);
mMapView.onCreate(mBundle);
setUpMapIfNeeded(inflatedView);
return inflatedView;
}
创建视图时的公共视图(布局、充气机、视图组容器、捆绑包保存状态){
//呼叫assyncTask
}
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mBundle=savedInstanceState;
}
需要专用void setupMapiFneed(视图膨胀视图){
如果(mMap==null){
mMap=((MapView)inflatedView.findviewbyd(R.id.map)).getMap();
如果(mMap!=null){
setUpMap();
}
}
}
私有void setUpMap(){
mMap.addMarker(新的MarkerOptions().position(新的LatLng(0,0)).title(“Marker”);
}
@凌驾
恢复时公开作废(){
super.onResume();
mMapView.onResume();
}
@凌驾
公共无效暂停(){
super.onPause();
mMapView.onPause();
}
@凌驾
公共空间{
mMapView.onDestroy();
super.ondestory();
}
私有类GetFlightsTask扩展异步任务{
@凌驾
受保护的void onPreExecute(){
super.onPreExecute();
//如果我删除下一行,一切都会得到修复
加载FlightsPinner.show();
}
@凌驾
受保护的字符串背景(双参数){
//一些相当长的远程API调用
//(从加载JSON文件)http://some.website.com/flights?...)
//很好
字符串flightsJSON=loadJSON(“flights?flyFrom=CZ&to=…”;
}
@凌驾
受保护的void onPostExecute(字符串flightsJSON){
super.onPostExecute(flightsJSON);
加载FlightsPinner.Disclose();
//在这里,我使用JSON进行填充,然后替换片段
做苦工
}
公众视野工作(){
视图充气视图=充气器。充气(R.layout.map\u碎片,容器,假);
试一试{
初始化(getActivity());
}捕获(谷歌PlayServicesNotAvailableException){
//如何处理这种情况
}
mMapView=(MapView)充气视图.findViewById(R.id.map);
mMapView.onCreate(mBundle);
需要设置地图(充气视图);
返回充气视图;
}
我运行了一个简单的测试:
public class MapFragmentOnBackStackExample extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_fragment_on_back_stack_example);
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.fragment_container);
if (f == null) {
f = SupportMapFragment.newInstance();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.fragment_container, f);
transaction.commit();
}
}
public void onAddFragmentClick(View view) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.fragment_container, new MyFragment());
transaction.addToBackStack(null);
transaction.commit();
}
public static class MyFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setText("MyFragment: " + hashCode());
return textView;
}
}
}
看不出有什么问题
当注释if(f==null){
让它总是在旋转时创建新片段时,我可以看到问题,这显然是错误的,但这会引起一些怀疑
您可以同时在内存中看到多个MapFragment吗?请尝试使用Eclipse内存分析器(MAT)。我已通过取消AsyncTask
的doInBackground()
方法末尾的ProgressDialog
而不是onPostExecute()
方法开头的来修复它
这有点奇怪,因为我实际上认为我不应该在doInBackground()中的UI中触摸东西
方法…如果有人想详细说明一下,我很乐意了解它为什么会这样。首先,感谢您的回答。按“后退”按钮结束应用程序不是一个选项。当显示FlightsFragment
并且用户按“后退”按钮时,我需要返回地图。至于第二个建议的解决方案-我已经很快尝试过了,它似乎奏效了。每次碎片从堆栈中弹出时,地图都会重新加载,不再延迟。但它会丢失相机位置、缩放、标记等。我想如果我实现保存这些东西并在
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Call assyncTask
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBundle = savedInstanceState;
}
private void setUpMapIfNeeded(View inflatedView) {
if (mMap == null) {
mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap();
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onDestroy() {
mMapView.onDestroy();
super.onDestroy();
}
private class GetFlightsTask extends AsyncTask<Double, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// if I remove the next line, everything gets fixed
loadingFlightsSpinner.show();
}
@Override
protected String doInBackground(Double... params) {
// some pretty long remote API call
// (loading a JSON file from http://some.website.com/flights?...)
// works fine
String flightsJSON = loadJSON("flights?flyFrom=CZ&to=...");
}
@Override
protected void onPostExecute(String flightsJSON) {
super.onPostExecute(flightsJSON);
loadingFlightsSpinner.dismiss();
// here I do stuff with the JSON and then replace the fragment
dohardwork()
}
public view dohardwork(){
View inflatedView = inflater.inflate(R.layout.map_fragment, container, false);
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
// TODO handle this situation
}
mMapView = (MapView) inflatedView.findViewById(R.id.map);
mMapView.onCreate(mBundle);
setUpMapIfNeeded(inflatedView);
return inflatedView;
}
public class MapFragmentOnBackStackExample extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_fragment_on_back_stack_example);
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.fragment_container);
if (f == null) {
f = SupportMapFragment.newInstance();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.fragment_container, f);
transaction.commit();
}
}
public void onAddFragmentClick(View view) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.fragment_container, new MyFragment());
transaction.addToBackStack(null);
transaction.commit();
}
public static class MyFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setText("MyFragment: " + hashCode());
return textView;
}
}
}