我有一个Activity
和一个MapFragment
,我使用FragmentTransaction
以编程方式添加到Activity
:
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
实例并设置它的设置,设置侦听器,用它做一些事情。一切正常
当用户完成映射时,AsyncTask
被触发以显示ProgressDialog
,执行一些操作,将不同的片段放入fragment_wrapper
并再次解散ProgressDialog
:
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();
}
一切都很好。用户在FlightsFragment
中做了一些事情,然后可能决定返回地图。按返回按钮,地图再次弹出。这就是地图延迟的时候。上面的国家/城市名称加载非常慢,在移动地图时严重滞后…我不知道为什么,我不做任何弹出MapFragment
回来。
有趣的是,它得到修复,例如按home按钮,然后再次返回到应用程序…
我做错了什么?
谢谢你的建议
我运行了一个简单的测试:
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) {
离开它总是创建新的片段旋转,这显然是错误的,但这带来了一些怀疑。
你能同时在内存中看到1个以上的MapFragment吗?尝试使用Eclipse内存分析器(MAT)。
只有按下后退键才会延迟?
如果这是问题,尝试阻止后退按钮或使其退出应用程序试试下面的代码:
@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: <com.google.android.gms.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
把这段代码放在post execute上:
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;
并在oncreateview
上调用asynctask 试试这个:
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;
}
我已经通过在AsyncTask
的doInBackground()
方法的末尾而不是在onPostExecute()
方法的开始驳回ProgressDialog
来修复它。
这有点奇怪,因为我实际上认为我不应该在doInBackground()
方法中触摸UI中的东西…如果有人想详细说明一下,我很乐意知道为什么它是这样工作的。