2015-01-16 15 views
5

से लौटने पर बेहद कमजोर है। मैं एक ऐसे ऐप पर काम कर रहा हूं जो v2 MapFragment का उपयोग करता है, और मैं बहुत अजीब व्यवहार में भाग रहा हूं। मैंने कुछ कस्टम व्यवहार को संभालने के लिए MapFragment का उप-वर्ग बनाया है (Marker एस हैंडलिंग, मेनू विकल्प tweaking, आदि), और पहले लोड पर यह सब खूबसूरती से काम करता है। मैं फिर अपनी गतिविधि में एक नया टुकड़ा एम्बेड करता हूं, कस्टम MapFragment को बैकस्टैक पर दबाता हूं। जब मैं बैकस्टैक से मानचित्र वापस करता हूं, हालांकि, चीजें अजीब होती हैं; नक्शा पॅनिंग बेहद लगी (हम ~ 1 एफपीएस बात कर रहे हैं) मैन्युअल ड्रैगिंग/ज़ूमिंग और पिन पर क्लिक करके एनिमेशन के लिए दोनों बन जाते हैं। और फिर, अगर मैं ओवरफ़्लो मेनू के किसी भी हिस्से से सहभागिता करता हूं, यहां तक ​​कि इसे खोलने और इसे फिर से खारिज करने के लिए, अंतराल तुरंत साफ़ हो जाता है। इसे ठीक करने के लिए कुछ और नहीं लगता है (ऐप को बंद/दोबारा खोलने से कम); गैर-ओवरफ्लो मेनू आइटम और नेविगेशन ड्रॉवर के साथ बातचीत करने में मदद करने के लिए कुछ भी नहीं है। मैंने कभी ऐसा कुछ नहीं देखा है, न ही मैं किसी को भी ढूंढ सकता हूं जिसने पहले इसी तरह की समस्या का वर्णन किया है। किसी भी विचार, सुझाव, और/या फिक्स का स्वागत किया जाएगा।Google मानचित्र v2 मैपफ्रैगमेंट बैकस्टैक

कुछ सवालों के जवाब के लिए इससे पहले कि वे पूछे जाते:

  • हाँ, मैं सभी के जीवन चक्र के तरीकों में से super संस्करणों फोन कर रहा हूँ मैं ओवरराइड (onCreate(), onCreateView() [मैं भी लौट कर रहा हूँ क्या सुपर रिटर्न उस के लिए], और onDestroyView())।
  • जहां तक ​​मैं कह सकता हूं, मैं मानचित्र को ठीक से साफ कर रहा हूं। हर बार जब मैं पिन को रीफ्रेश करता हूं, तो मैं उनमें से प्रत्येक पर remove() पर कॉल कर रहा हूं और फिर clean() मानचित्र पर ही हूं, और मैं onDestroyView() में भी ऐसा करता हूं।

और अंत में, संदर्भ के लिए, इस कोड है कि नए टुकड़ा कहते है:

getFragmentManager().beginTransaction().replace(R.id.main_content_container, new JoinGroupFragment()).addToBackStack(null).commit(); 

और जब मैं इसे पूरा कर लेने, मैं सिर्फ फोन:

getFragmentManager().popBackStack(); 

संपादित करें: मुझे यकीन नहीं है कि यह कितनी मदद करेगा, लेकिन यहां कस्टम MapFragment:

public class CustomMapFragment extends MapFragment { 

    private static final String DIALOG_TAG = "CUSTOM_MAP_FRAGMENT_DIALOG"; 
    private static final int DEFAULT_ZOOM = 14; 
    private static final int MARKER_ZOOM = 15; 
    private static final int DEFAULT_PADDING = 80; 
    private static final int ORANGE_THRESHOLD_MINUTES = 7; 
    private static final int BLUE_THRESHOLD_MINUTES = 20; 

    public static final String KEY_GROUP_NAME = "GROUP_NAME"; 
    public static final String KEY_GROUP_ID = "GROUP_ID"; 

    private TextView mGroupNameOverlay; 
    private GoogleMap mMap; 
    private ArrayList<Marker> mMarkers; 
    private Marker mSelectedMarker; 
    private ArrayList<Group> mAllGroups; 
    private Group mCurrentGroup; 
    private ArrayList<Location> mAllLocations; 
    private boolean mMapReady; 
    private String mUsername; 
    private boolean mCenterOnUser; 

    public CustomMapFragment() { 

    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setHasOptionsMenu(true); 

     mMarkers = new ArrayList<>(); 
     mAllLocations = new ArrayList<>(); 

     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); 
     mUsername = prefs.getString(PreferenceUtils.KEY_USERNAME, null); 
     mCenterOnUser = prefs.getBoolean(PreferenceUtils.KEY_CENTER_ON_ME, false); 
     mSelectedMarker = null; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     ViewGroup view = (ViewGroup)super.onCreateView(inflater, container, savedInstanceState); 

     if (view != null) { 
      // View should never be null; MapFragments have a FrameLayout as their top level parent 
      mGroupNameOverlay = (TextView)inflater.inflate(R.layout.group_name_overlay, view, false); 
      view.addView(mGroupNameOverlay); 
     } 

     Bundle results = ((MainActivity)getActivity()).getFragmentResults(); 
     if (results != null) { 
      String name = results.getString(KEY_GROUP_NAME); 
      String id = results.getString(KEY_GROUP_ID); 
      if (!StringUtils.isNullOrEmpty(name) && !StringUtils.isNullOrEmpty(id)) { 
       mCurrentGroup = new Group(name, id); 
       mAllGroups.add(mCurrentGroup); 
      } 
     } 

     if (mCurrentGroup != null) { 
      updateGroupNameOverlay(mCurrentGroup.getGroupName()); 
     } 

     getMapAsync(new OnMapReadyCallback() { 
      @Override 
      public void onMapReady(GoogleMap googleMap) { 
       mMap = googleMap; 
       mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { 
        @Override 
        public boolean onMarkerClick(Marker marker) { 
         mSelectedMarker = marker; 
         getActivity().invalidateOptionsMenu(); 
         return false; 
        } 
       }); 
       mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() { 
        @Override 
        public void onMapClick(LatLng latLng) { 
         mSelectedMarker = null; 
         getActivity().invalidateOptionsMenu(); 
        } 
       }); 
       populateMap(true, false); 
      } 
     }); 

     GetGroupsRequest request = new GetGroupsRequest(); 
     request.setListener(new GetGroupsRequestListener()); 
     RequestProcessor.getInstance(getActivity()).queueRequest(request); 

     return view; 
    } 

    @Override 
    public void onDestroyView() { 
     mSelectedMarker = null; 
     for (Marker marker : mMarkers) { 
      marker.remove(); 
     } 
     mMarkers.clear(); 
     mMap.clear(); 
     mMap = null; 
     mMapReady = false; 
     super.onDestroyView(); 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     if (mSelectedMarker == null) { 
      inflater.inflate(R.menu.menu_map, menu); 
     } 
     else { 
      inflater.inflate(R.menu.menu_marker, menu); 
     } 
     super.onCreateOptionsMenu(menu, inflater); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.map_menu_refresh_pins: 
       performLocationsRequest(false); 
       return true; 
      case R.id.map_menu_recenter_zoom: 
       populateMap(true, true); 
       return true; 
      case R.id.map_menu_select_group: 
       DialogFragment selectDialog = new DialogFragment() { 

        @Override 
        public Dialog onCreateDialog(Bundle savedInstanceState) { 
         String[] groups = new String[mAllGroups.size()]; 
         for (int i = 0; i < groups.length; i++) { 
          groups[i] = mAllGroups.get(i).getGroupName(); 
         } 
         return new AlertDialog.Builder(getActivity()) 
           .setItems(groups, new DialogInterface.OnClickListener() { 
            @Override 
            public void onClick(DialogInterface dialog, int which) { 
             if (!mAllGroups.get(which).equals(mCurrentGroup)) { 
              mCurrentGroup = mAllGroups.get(which); 
              updateGroupNameOverlay(mCurrentGroup.getGroupName()); 
              performLocationsRequest(true); 
             } 
            } 
           }) 
           .create(); 
        } 
       }; 
       selectDialog.show(getFragmentManager(), DIALOG_TAG); 
       return true; 
      case R.id.map_menu_join_group: 
       getFragmentManager().beginTransaction().replace(R.id.main_content_container, new JoinGroupFragment()).addToBackStack(null).commit(); 
       return true; 
      case R.id.map_menu_create_group: 
       CreateDialogFragment createDialog = new CreateDialogFragment(); 
       createDialog.show(getFragmentManager(), DIALOG_TAG); 
       return true; 
      case R.id.map_marker_zoom: 
       if (mSelectedMarker != null) { 
        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mSelectedMarker.getPosition(), MARKER_ZOOM)); 
       } 
       return true; 
      default: 
       return super.onOptionsItemSelected(item); 
     } 
    } 

    private void performLocationsRequest(boolean autoZoom) { 
     GetLocationsRequest request = new GetLocationsRequest(mCurrentGroup.getGroupId()); 
     request.setListener(new GetLocationsRequestListener(autoZoom)); 
     RequestProcessor.getInstance(getActivity()).queueRequest(request); 
    } 

    private void updateGroupNameOverlay(final String groupName) { 
     if (mGroupNameOverlay != null) { 
      getActivity().runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        if (groupName == null) { 
         mGroupNameOverlay.setText(R.string.map_group_overlay_no_group); 
        } 
        else { 
         mGroupNameOverlay.setText(getString(R.string.map_group_overlay_group, groupName)); 
        } 
       } 
      }); 
     } 
    } 

    private void populateMap(boolean zoom, boolean animate) { 
     if (!mMapReady) { 
      mMapReady = true; 
     } 
     else { 
      CameraUpdate update = null; 
      mSelectedMarker = null; 
      for (Marker marker : mMarkers) { 
       marker.remove(); 
      } 
      mMarkers.clear(); 
      mMap.clear(); 
      if (mAllLocations.size() == 1) { 
       Location location = mAllLocations.get(0); 
       mMarkers.add(addMarker(location)); 
       update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), DEFAULT_ZOOM); 
      } 
      else if (mAllLocations.size() > 1) { 
       LatLngBounds.Builder builder = new LatLngBounds.Builder(); 
       for (Location location : mAllLocations) { 
        mMarkers.add(addMarker(location)); 
        if (mCenterOnUser) { 
         if (location.getUsername().equals(mUsername)) { 
          update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), DEFAULT_ZOOM); 
         } 
        } 
        else { 
         builder.include(new LatLng(location.getLatitude(), location.getLongitude())); 
        } 
       } 
       if (!mCenterOnUser) { 
        update = CameraUpdateFactory.newLatLngBounds(builder.build(), DEFAULT_PADDING); 
       } 
      } 

      if (update != null && zoom) { 
       if (animate) { 
        mMap.animateCamera(update); 
       } 
       else { 
        mMap.moveCamera(update); 
       } 
      } 
     } 
    } 

    private Marker addMarker(Location location) { 
     String timestamp; 
     long minutesOld = (new Date().getTime() - location.getLastReported())/60000; 
     float hue = BitmapDescriptorFactory.HUE_RED; 
     if (minutesOld < 1) { 
      timestamp = getString(R.string.map_timestamp_just_now); 
     } 
     else if (minutesOld < 2) { 
      timestamp = getString(R.string.map_timestamp_one_minute); 
     } 
     else { 
      timestamp = getString(R.string.map_timestamp_n_minutes, minutesOld); 
      if (minutesOld >= ORANGE_THRESHOLD_MINUTES) { 
       hue = BitmapDescriptorFactory.HUE_ORANGE; 
      } 
      if (minutesOld >= BLUE_THRESHOLD_MINUTES) { 
       hue = BitmapDescriptorFactory.HUE_BLUE; 
      } 
     } 
     LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); 
     return mMap.addMarker(new MarkerOptions() 
       .position(latLng) 
       .icon(BitmapDescriptorFactory.defaultMarker(hue)) 
       .title(location.getUsername()) 
       .snippet(timestamp)); 
    } 

    private class GetGroupsRequestListener extends RequestListener<GetGroupsResponse> { 

     public GetGroupsRequestListener() { 
      super(getActivity()); 
     } 

     @Override 
     protected void onRequestComplete(GetGroupsResponse response) { 
      mAllGroups = response.getGroups(); 
      if (mAllGroups.size() > 0) { 
       if (mCurrentGroup == null) { 
        mCurrentGroup = mAllGroups.get(0); 
        updateGroupNameOverlay(mCurrentGroup.getGroupName()); 
       } 
       performLocationsRequest(true); 
      } 
     } 
    } 

    private class GetLocationsRequestListener extends RequestListener<GetLocationsResponse> { 

     private boolean mmAutoZoom; 

     public GetLocationsRequestListener(boolean autoZoom) { 
      super(getActivity()); 
      mmAutoZoom = autoZoom; 
     } 

     @Override 
     protected void onRequestComplete(GetLocationsResponse response) { 
      mAllLocations = response.getLocations(); 
      getActivity().runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        populateMap(mmAutoZoom, false); 
       } 
      }); 
     } 
    } 
} 

पीएस मुझे एहसास है कि शायद हाइजैक व्यू सृजन को हल करने और अपने स्वयं के ओवरले को इंजेक्ट करने का सबसे अच्छा अभ्यास नहीं है, लेकिन इसके लायक होने के लिए, मैंने उस हिस्से को टिप्पणी करने की कोशिश की और समस्या को हल नहीं किया, इसलिए मुझे संदेह है यह संबंधित है।

+0

http://stackoverflow.com/questions/21815818/map-of-mapfragment-gets-loaded-with-lag-when-returning-from-another-activity और http://stackoverflow.com/questions/16265346/google-maps-v2-lag-after-popping-their-fragment-back-from-stack आपको मदद करेगा यदि आप इस तरह से हैंडलिंग कर रहे हैं। चूंकि आपने कोड पोस्ट नहीं किया है, इसलिए सटीक परिदृश्य को समझना थोड़ा मुश्किल होगा – EagleEye

+0

मैंने पोस्ट पोस्ट करने से पहले उन दोनों प्रश्नों को देखा और विशेष रूप से सहायक नहीं पाया। पहला एक अलग मुद्दा है (प्रारंभिक नक्शा भार में देरी हो रही है) और दूसरा स्पष्ट रूप से वूडू जादू के माध्यम से हल किया गया था। अधिक कोड पोस्ट करने के लिए, मैं कर सकता हूं; मुख्य कारण यह नहीं था क्योंकि मुझे नहीं पता था कि वास्तव में कौन से हिस्से उपयोगी होंगे। – Alex

उत्तर

2

मुझे इसी तरह की समस्या का सामना करना पड़ा है। मान लें कि मेरे पास बच्चे SupportMapFragment के साथ FragmentA है। नेविगेशन ड्रॉवर मेनू के माध्यम से मैं दिखाए जाने के लिए एक संवाद का आह्वान करता हूं। इस बिंदु पर FragmentA में बाल मानचित्र कुछ "पृष्ठभूमि मोड" पर जाता है - यह लगभग दो बार अपडेट होता है (मेरे पास इस मानचित्र पर एनिमेटेड मार्कर हैं, इसलिए यह व्यवहार मुझे अच्छी तरह से जाना जाता है)। ओवरले के साथ कोई तत्व दिखाकर यह "पृष्ठभूमि" मोड चालू है, f.e. संवाद या ऐपबार मेनू, और उस तत्व को छुपाए जाने पर बंद है।

संवाद में मेरे पास वस्तुओं के साथ सूची है, जो क्लिक होने पर खंड को प्रतिस्थापित कर रहे हैं। इस बिंदु पर FragmentA को FragmentB द्वारा प्रतिस्थापित किया जा रहा है। यहाँ OnClickListener के कोड का टुकड़ा है:

final SmartFragment fragment = new SmartFragment(); 
FragmentManager supportFragmentManager = getActivity().getSupportFragmentManager(); 
supportFragmentManager 
     .beginTransaction() 
     .replace(R.id.fragment_container, fragment, SmartFragment.FRAGMENT_TAG) 
     .addToBackStack(null) 
     .commit(); 
dismiss(); 

लेकिन उसके बाद मैं backstack, नक्शा है, जो बनाए रखा गया था से FragmentA पर लौटने, कि "पृष्ठभूमि मोड" में रहता है फिर भी संवाद अब मौजूद नहीं है।लेनदेन से पहले विघटन() कथन को स्थानांतरित करने में मदद नहीं मिलती है, यह सभी कोड निष्पादित होने तक संवाद को समाप्त नहीं किया जाता है। तो एकमात्र उचित समाधान (सीधे "नक्शा खंड" पर "पृष्ठभूमि मोड" को चालू करने के अलावा, जो मुझे नहीं मिल सकता है) जब तक संवाद वास्तव में खारिज नहीं किया जाता है तब तक खंड लेनदेन में देरी होती है। जैसा कि मैंने पहले माना था, ऐसा तब होता है जब ऑनक्लिक (जो कि संवाद का हिस्सा है) में सभी कोड निष्पादित किए जाते हैं, इसलिए हमें एक उदाहरण पर लेनदेन नहीं किया जाना चाहिए, लेकिन थोड़ी देर बाद, इसे रननेबल में रखा गया:

dismiss(); 
final SmartFragment fragment = new SmartFragment(); 
Handler handler = new Handler(); 
final FragmentManager supportFragmentManager = getActivity().getSupportFragmentManager(); 
handler.post(new Runnable() { 
    @Override 
    public void run() { 
     supportFragmentManager 
       .beginTransaction() 
       .replace(R.id.fragment_container, fragment, StopsSmartFragment.FRAGMENT_TAG) 
       .addToBackStack(null) 
       .commit(); 
    } 
}); 

इसके लिए हमें अपना टुकड़ा और समर्थन बनाने की आवश्यकता है फ्रैगमेंट मैनेजर फाइनल। अब सबकुछ काम करता है, मानचित्र का "पृष्ठभूमि मोड" बंद हो जाता है, और यदि आप बैकस्टैक से फ्रैगमेंट ए में वापस आते हैं, तो नक्शा काम करता है जैसा कि करना चाहिए।

अगर किसी को पता है कि नक्शा खंड में सीधे "पृष्ठभूमि मोड" को बंद करना है, तो कृपया बताएं, मुझे सुनकर खुशी होगी।

संबंधित मुद्दे