map-fragment
map-fragment copied to clipboard
Leaking map activity / problems with the back button
Hi Inazaruk!
Based on your code I combined the two Fragment classes into one and based it off my own custom Fragment:
public abstract class ActivityHostFragment<T> extends ContentFragment<T> {
private static final String KEY_STATE_BUNDLE = "localActivityManagerState";
private static final String ACTIVITY_TAG = "hosted";
private View activityView;
private LocalActivityManager localActivityManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle state = null;
if (savedInstanceState != null) {
state = savedInstanceState.getBundle(KEY_STATE_BUNDLE);
}
localActivityManager = new LocalActivityManager(getActivity(), true);
localActivityManager.dispatchCreate(state);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
View fragmentView = super.onCreateView(inflater, container, state);
ViewGroup containerView = getContainerView(fragmentView);
activityView = startActivityAndGetView();
containerView.addView(activityView);
return fragmentView;
}
@Override
public void onDestroyView() {
ViewGroup containerView = getContainerView(getView());
containerView.removeAllViews();
activityView = null;
super.onDestroyView();
}
private ViewGroup getContainerView(View fragmentView) {
int containerId = getActivityContainerView();
View containerView = fragmentView.findViewById(containerId);
checkArgument(containerView != null, "container with ID " + containerId + " not found");
checkArgument(containerView instanceof ViewGroup, "container with ID " + containerId + " is not a viewGroup");
return (ViewGroup) containerView;
}
protected View startActivityAndGetView() {
Intent intent = new Intent(getActivity(), getActivityClass());
Window window = localActivityManager.startActivity(ACTIVITY_TAG, intent);
View view = window != null ? window.getDecorView() : null;
if (view != null) {
ViewParent parent = view.getParent();
if (parent != null) {
ViewGroup v = (ViewGroup) parent;
v.removeView(view);
}
view.setVisibility(View.VISIBLE);
view.setFocusableInTouchMode(true);
if (view instanceof ViewGroup) {
((ViewGroup) view).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
}
}
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBundle(KEY_STATE_BUNDLE, localActivityManager.saveInstanceState());
}
@Override
public void onResume() {
super.onResume();
localActivityManager.dispatchResume();
}
@Override
public void onPause() {
super.onPause();
localActivityManager.dispatchPause(getActivity().isFinishing());
}
@Override
public void onStop() {
super.onStop();
localActivityManager.dispatchStop();
}
@Override
public void onDestroy() {
super.onDestroy();
localActivityManager.dispatchDestroy(getActivity().isFinishing());
}
/**
* Returns the view instance that has been embedded into this fragment's
* view
*
* @return
*/
public View getActivityView() {
return activityView;
}
/**
* Returns the class of the activity that should be "hosted" in this
* fragment
*
* @return
*/
protected abstract Class<? extends Activity> getActivityClass();
/**
* Returns the ID of the container that is part of the layout defined in
* {@#getLayout()} in which the activity view should be
* loaded into
*
* @return
*/
protected abstract int getActivityContainerView();
}
This works all fine as is, just that I encounter two major problems:
- when my fragment is dismissed, recreated and then dismissed again Android's
StrictMode
tells me that I'm leaking my MapActivity that I return asgetActivityClass()
in a derived class; what is weird about that is that I could only reproduce it to leak up to 3 or 4 instances of the activity, so it seems to be cleaned, but at least two instances still remain (verified with HPROF dump in MAT) - the
BACK
button does not seem to work properly any longer. It takes sometimes up to five clicks on it to actually make it call myonBackPressed()
handler in my main activity. I get many log messages from theInputEventConsistencyVerifier
telling me aboutACTION_UP but key was not down
, originating fromandroid.widget.ZoomButtonsController
Have you experienced anything like this in the past?
I know that there is a new API finally available, but I read of problems with it on older devices (< 3.0), so we decided to stick to the v1 API for now.
Thanks in advance! Thomas.
Ok, actually forgot the second issue. I tracked it down being a problem with MapView.displayZoomControls(true);
that I used previously to permanently show the zoom controls. This puts the focus on the zoom controls which seem to have their own key event handling as it seems. Removing that makes the BACK
button work instantly as it is supposed to work.
Still, the activity leaking is immanent...