2015-06-15 10 views
22

मेरे पास मुख्य एक्टिविटी है और इसके अंदर, मैं एक टुकड़ा लोड कर रहा हूं। फ्रैगमेंट ए से, मैं startActivityforResult का उपयोग करके Google placepicker गतिविधि को कॉल कर रहा हूं।एंड्रॉइड पैरेंट एक्टिविटी शुरू होने के बाद पुन: निर्मित नहीं हो रहा है एक्टिविटीफॉर रिसेट रिटर्न

PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder(); 
Intent intent = builder.build(getActivity()); 
getActivity().startActivityForResult(intent,PLACE_PICKER_REQUEST); 

लेकिन जब मैं जगह का चयन करें, onActivityResult (या तो FragmentA या MainActivity में) कहा जाता हो रही है नहीं है। असल में, मेरा आवेदन प्रारंभ करने के बाद नष्ट हो रहा है सक्रियताफॉर रिसेट कॉल।

मेरी समझ के अनुसार, एंड्रॉइड को कॉलिंग गतिविधि को फिर से बनाना चाहिए यदि यह स्मृति में उपलब्ध नहीं है। लेकिन यह नहीं हो रहा है। यहां भी मुख्य उत्पत्ति के अंदर क्रिएट नहीं बुलाया जा रहा है।

क्या कोई मुझे इस तरह के व्यवहार के पीछे कारण बता सकता है या क्या मुझे कुछ याद आ रहा है?

अब प्लेसपिकर गतिविधि के बजाय, मैंने उसी एप्लिकेशन में एक और गतिविधि का उपयोग करने का प्रयास किया है।

मान लीजिए कि मैं MainActivityFragmentA साथ loaded.I FragmentA अब से startActivityForResult साथ SubActivity बोल रहा हूँ SubActivity, आवेदन बाहर निकलता से लौटने के दौरान की जाने वाली हैं। इस विशिष्ट परिदृश्य का परीक्षण करने के लिए मैंने अपने डिवाइस में Dont keep activities सक्षम किया है। SubActivity पर लौटने पर MainActivity नष्ट हो रहा है, लेकिन SubActivity से लौटने पर, एंड्रॉइड MainActivity (यहां तक ​​कि onCreate भी नहीं बुलाया जा रहा है। एप्लिकेशन अभी बाहर निकल रहा है)।

+0

* "मेरा आवेदन प्रारंभ करने के बाद नष्ट हो रहा है सक्रियताफॉर रिसेट कॉल।" * क्या आपका मतलब यह क्रैश हो रहा है? – codeMagic

+0

क्या आपने अपनी मेनिफेस्ट फ़ाइल में एक इरादा फ़िल्टर प्रदान किया है? यह इसलिए आवश्यक है कि अपनी गतिविधि निर्मित किया जा सकता है – Mann

+0

@codeMagic यह startActivityForResult बुला crashing.After नहीं कर रहा है, मैं MainActivity में onDestory विधि देख सकते हैं .और कहा जाता हो रही है जब मैं शुरू की गतिविधि से एक जगह का चयन करें, यह returns.But अपने आवेदन पुनः नहीं है । अगर मैं जगह को जल्दी से चुनता हूं (मेरी मुख्य क्रिया से पहले) नष्ट हो रहा है), एक्टिविटी रिसेट को सही तरीके से बुलाया जा रहा है। – Renjith

उत्तर

7

एंड्रॉइड के लिए आपके द्वारा वर्णित तरीके से एक गतिविधि को साफ करने के लिए यह काफी असामान्य लगता है, लेकिन यदि ऐसा था तो आपकी गतिविधि को अभी भी बहाल किया जाना चाहिए। एंड्रॉइड को गतिविधि को नष्ट नहीं करना चाहिए, जब तक कि आप विशेष रूप से finish() पर कॉल न करें या कुछ गतिविधि समय-समय पर समाप्त हो जाती है।

यदि आप गतिविधि जीवन चक्र आरेख का संदर्भ लें:

परिदृश्य आप वर्णित पहली गतिविधि onStop बुलाना चाहिए में, लेकिन नहीं OnDestroy, फिर जब आप दूसरी गतिविधि से लौटने यह onStart बुलाना चाहिए फिर।

मैं परिदृश्य आप वर्णित है, जो निम्नलिखित निहित परीक्षण करने के लिए एक बहुत ही सरल अनुप्रयोग बनाया:

  • 2 गतिविधियों, FirstActivity और SecondActivity
  • हैं
  • FirstActivity एक बटन है, जब बटन क्लिक किया जाता है यह है SecondActivity startActivityForResult()
  • गतिविधि जीवन चक्र की घटनाओं के लिए एक कस्टम आवेदन वर्ग
  • FirstActivity onActivityResult में अतिरिक्त एल आउटपुट में ActivityLifecycleCallbacks का उपयोग कर लॉग ऑन हैं के साथ शुरू होता

    आवेदन शुरू कर दिया है (FirstActivity बनाई गई है और शुरू कर दिया और दृश्यमान)::

    FirstActivity onCreate 
    FirstActivity onStart 
    FirstActivity onResume 
    

    मैं SecondActivity शुरू करने के लिए बटन दबाएँ: ओग जब यह

  • कहा जाता हो जाता है

यहाँ उत्पादन होता है क्या है

FirstActivity onPause 
SecondActivity onCreate 
SecondActivity onStart 
SecondActivity onResume 
FirstActivity onSaveInstanceState 
FirstActivity onStop 

नोट, ऑनस्ट्रोय को कॉल नहीं किया जाता है।

अब मैं वापस बटन दबाएँ और पहली गतिविधि पर लौटने:

SecondActivity onPause 
FirstActivity onStart 
FirstActivity onActivityResult 
FirstActivity onResume 
SecondActivity onStop 
SecondActivity onDestroy 

वापस बटन SecondActivity पर finish कॉल तो यह

अब अगर मैं प्रेस फिर से वापस FirstActivity भी समाप्त हो जाएगी नष्ट कर रहा है, onDestroy को बुलाया जा रहा है।

FirstActivity onPause 
FirstActivity onStop 
FirstActivity onDestroy 

आप देख सकते हैं कि इस उदाहरण जीवन चक्र आरेख लिए वास्तव में पालन किया गया है। बैक बटन दबाए जाने के बाद ही गतिविधियों को नष्ट कर दिया जाता है, जिससे गतिविधि finish() पर कॉल कर सकती है।

आपने बताया कि आपने डेवलपर विकल्पों में "गतिविधियों को न रखें" चालू करने का प्रयास किया है, हम उपरोक्त प्रयोग को दोहरा सकते हैं जो इस विकल्प को सक्षम करता है और देखें कि क्या होता है। दूसरी गतिविधि शुरू करने के लिए

पहली गतिविधि में बटन दबाने के बाद:: मैं बस सब कुछ ऊपर है कि दोहरा को बचाने के लिए प्रासंगिक जीवन चक्र की घटनाओं को शामिल किया है

... 
SecondActivity onResume 
FirstActivity onSaveInstanceState 
FirstActivity onStop 
FirstActivity onDestroy 

जैसी उम्मीद थी, गतिविधि इस नष्ट कर दिया गया पहर। के रूप में सिस्टम को पुनः आरंभ करने के लिए पहली गतिविधि के एक बंद कर दिया संस्करण नहीं था

SecondActivity onPause 
FirstActivity onCreate 
FirstActivity onStart 
FirstActivity onActivityResult 
FirstActivity onResume 
... 

इस बार onCreate फिर से बुलाया गया था: यह जब आप फिर से वापस पहली गतिविधि पर नेविगेट क्या होता है। इसके अलावा onActivityResult() को अभी भी कहा गया था, इस तथ्य के बावजूद कि गतिविधि को फिर से बनाया जाना था।

यह आगे समर्थन करता है कि आपकी पहली गतिविधि में कुछ finish() पर कॉल करना होगा या इसे क्रैश करना होगा। हालांकि, आपके वास्तविक कोड को देखे बिना यह अनुमान है।

अंत में, राज्य को बनाए रखने अगर अपनी गतिविधि किसी कारण से निर्मित करने के लिए की जरूरत है, तो आप onSaveInstanceState() ओवरराइड कर सकते हैं और उसके पास समूह के लिए किसी भी राज्य जानकारी जोड़ने के लिए:

protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putString(MY_STRING_KEY, "my string value"); 
} 

जब गतिविधि से निर्मित है, तो आप करेंगे

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ... 
    if (savedInstanceState != null) { 
     // Restore previous state 
    } 
} 
+0

पोस्ट करें मैं गतिविधि को दोबारा बनाने के लिए एक ही मामले का परीक्षण कर रहा हूं (मेरा संपादन देखें)। समस्या भी है, लौटने के दौरान क्रिएट विधि को कॉल नहीं किया जा रहा है। – Renjith

+2

यह स्वीकृत उत्तर क्यों है? यह सवाल आईएमओ का जवाब नहीं देता है। –

+0

कॉलिंग गतिविधि में कब ऑनस्ट्राय को बुलाया जाता है ??? –

18

यह तब हो सकता की वजह से कई कारणों से है, लेकिन उम्मीद है कि यह एक दुर्लभ घटना है: एक बंडल onCreate में वापस आ गया है, जिसमें सब कुछ शामिल करना चाहिए आप को बचाया मिलता है। ओएस संसाधनों को पुनः प्राप्त करने की आवश्यकता होने पर पृष्ठभूमि को नष्ट कर देगा, जो कम स्मृति और प्रसंस्करण शक्ति वाले उपकरणों पर होने की अधिक संभावना है।

Do not keep Activities सेटिंग का उपयोग इस परिदृश्य का परीक्षण करने का एक अच्छा तरीका है, और इस मामले में अन्य समस्याएं हैं भले ही गतिविधि/टुकड़ा फिर से बनाया जाए। इस सेटिंग को सक्षम करने के साथ, प्लेसपिकर दिखाए जाने पर गतिविधि और टुकड़ा नष्ट हो जाता है, और फिर जब onActivityResult() आता है, तो कोई वैध संदर्भ नहीं है क्योंकि गतिविधि और टुकड़ा अभी भी पुन: निर्मित होने की प्रक्रिया में हैं।

मैं इस विकलांग स्थापित करने के साथ एक नियंत्रित परीक्षण प्रदर्शन से पता चला है, और फिर सेटिंग सक्षम के साथ, और फिर परिणाम

मैं गतिविधि के लिए प्रत्येक जीवन चक्र कॉलबैक और क्रम में टुकड़ा में प्रवेश करने के रख को देखकर इन कॉलों के दौरान क्या हो रहा है इसका एक अनुमान प्राप्त करने के लिए।

यहाँ पूर्ण वर्ग मैं प्रयोग किया जाता है कि दोनों गतिविधि और टुकड़ा भी शामिल है:

public class MainActivity extends AppCompatActivity { 

    MyFragment myFrag; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     Log.d("PlacePickerTest", "Activity onCreate"); 

     myFrag = new MyFragment(); 

     setContentView(R.layout.activity_main); 
     if (savedInstanceState == null) { 
      getSupportFragmentManager().beginTransaction() 
        .add(R.id.container, myFrag) 
        .commit(); 
     } 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 

     Log.d("PlacePickerTest", "Activity onResume"); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 

     Log.d("PlacePickerTest", "Activity onPause"); 
    } 

    @Override 
    protected void onDestroy() { 
     Log.d("PlacePickerTest", "Activity onDestroy"); 
     super.onDestroy(); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.menu_main, menu); 
     return true; 
    } 

    @Override 
    public void onActivityResult (int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 

     Log.d("PlacePickerTest", "Activity onActivityResult requestCode:" + requestCode); 

     if (requestCode == 199){ 
      //process result of PlacePicker in the Fragment 
      myFrag.processActivityResult(data); 
     } 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     int id = item.getItemId(); 
     if (id == R.id.action_settings) { 
      //open PlacePicker from menu item 
      myFrag.startPlacePicker(); 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 

    /** 
    * Fragment containing a map and PlacePicker functionality 
    */ 
    public static class MyFragment extends Fragment { 

     private GoogleMap mMap; 
     Marker marker; 

     public MyFragment() { 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
           Bundle savedInstanceState) { 
      View rootView = inflater.inflate(R.layout.fragment_main, container, false); 

      Log.d("PlacePickerTest", "Fragment onCreateView"); 

      return rootView; 
     } 


     @Override 
     public void onResume() { 
      super.onResume(); 

      Log.d("PlacePickerTest", "Fragment onResume"); 

      setUpMapIfNeeded(); 
     } 

     @Override 
      public void onPause() { 
      super.onPause(); 

      Log.d("PlacePickerTest", "Fragment onPause"); 
     } 

     @Override 
     public void onDestroy() { 
      Log.d("PlacePickerTest", "Fragment onDestroy"); 
      super.onDestroy(); 
     } 

     private void setUpMapIfNeeded() { 
      // Do a null check to confirm that we have not already instantiated the map. 
      if (mMap == null) { 
       // Try to obtain the map from the SupportMapFragment. 
       mMap = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)) 
         .getMap(); 
       // Check if we were successful in obtaining the map. 
       if (mMap != null) { 
        setUpMap(); 
       } 
      } 
     } 

     private void setUpMap() { 

      // Enable MyLocation Layer of Google Map 
      mMap.setMyLocationEnabled(true); 
      mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); 
      mMap.getUiSettings().setZoomControlsEnabled(true); 
      mMap.getUiSettings().setMyLocationButtonEnabled(true); 
      mMap.getUiSettings().setCompassEnabled(true); 
      mMap.getUiSettings().setRotateGesturesEnabled(true); 
      mMap.getUiSettings().setZoomGesturesEnabled(true); 

     } 

     public void startPlacePicker(){ 
      int PLACE_PICKER_REQUEST = 199; 
      PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder(); 
      //Context context = getActivity(); 
      try { 
       Log.d("PlacePickerTest", "Fragment startActivityForResult"); 
       getActivity().startActivityForResult(builder.build(getActivity()), PLACE_PICKER_REQUEST); 
      } catch (GooglePlayServicesRepairableException e) { 
       e.printStackTrace(); 
      } catch (GooglePlayServicesNotAvailableException e) { 
       e.printStackTrace(); 
      } 
     } 

     public void processActivityResult (Intent data) { 

      if (getActivity() == null) return; 

      Log.d("PlacePickerTest", "Fragment processActivityResult"); 


      //process Intent...... 
      Place place = PlacePicker.getPlace(data, getActivity()); 
      String placeName = String.format("Place: %s", place.getName()); 
      String placeAddress = String.format("Address: %s", place.getAddress()); 

      LatLng toLatLng = place.getLatLng(); 

      // Show the place location in Google Map 
      mMap.moveCamera(CameraUpdateFactory.newLatLng(toLatLng)); 
      mMap.animateCamera(CameraUpdateFactory.zoomTo(15)); 

      if (marker != null) { 
       marker.remove(); 
      } 
      marker = mMap.addMarker(new MarkerOptions().position(toLatLng) 
        .title(placeName).snippet(placeAddress) 
        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA))); 

     } 
    } 
} 

यहाँ जिसके परिणामस्वरूप लॉग कि क्या जीवन चक्र कॉलबैक सामान्य परिस्थितियों में इस प्रक्रिया के दौरान कहा जाता है में जानकारी दे रहे हैं:

D/PlacePickerTest﹕ Activity onCreate 
D/PlacePickerTest﹕ Fragment onCreateView 
D/PlacePickerTest﹕ Activity onResume 
D/PlacePickerTest﹕ Fragment onResume 
D/PlacePickerTest﹕ Fragment startActivityForResult 
D/PlacePickerTest﹕ Fragment onPause 
D/PlacePickerTest﹕ Activity onPause 
D/PlacePickerTest﹕ Activity onActivityResult requestCode:199 
D/PlacePickerTest﹕ Fragment processActivityResult 
D/PlacePickerTest﹕ Activity onResume 
D/PlacePickerTest﹕ Fragment onResume 

तो, जैसा कि आप देख सकते हैं onDestroy() कभी नहीं कहा जाता है, और onPause() और onResume() दोनों गतिविधि और टुकड़ा पर कहा जाता है।

PlacePicker

फिर एक जगह चुनने के बाद:: फिर

place shown on map

, मैं Do not keep Activities सेटिंग में डेवलपर विकल्प के तहत सक्षम है, और एक ही परीक्षण भाग गया

यहाँ नेत्रहीन परिणाम है ।

इन जिसके परिणामस्वरूप लॉग हैं:

D/PlacePickerTest﹕ Activity onCreate 
D/PlacePickerTest﹕ Fragment onCreateView 
D/PlacePickerTest﹕ Activity onResume 
D/PlacePickerTest﹕ Fragment onResume 
D/PlacePickerTest﹕ Fragment startActivityForResult 
D/PlacePickerTest﹕ Fragment onPause 
D/PlacePickerTest﹕ Activity onPause 
D/PlacePickerTest﹕ Activity onDestroy 
D/PlacePickerTest﹕ Fragment onDestroy 
D/PlacePickerTest﹕ Activity onCreate 
D/PlacePickerTest﹕ Fragment onCreateView 
D/PlacePickerTest﹕ Activity onActivityResult requestCode:199 
D/PlacePickerTest﹕ Activity onResume 
D/PlacePickerTest﹕ Fragment onResume 

तो, आप देख सकते हैं दोनों गतिविधि और टुकड़ा नष्ट कर रहे हैं जब PlacePicker दिखाया गया है, और बाद जगह PlacePicker में उठाया जाता है, कोड निष्पादन नहीं मिला Fragment processActivityResult लॉग प्रविष्टि के लिए, और ऐप ने मानचित्र पर चुनी गई जगह कभी नहीं दिखायी।

अशक्त संदर्भ की जांच करने की वजह से है कि:

if (getActivity() == null) return; 

Log.d("PlacePickerTest", "Fragment processActivityResult"); 

//process Intent...... 
Place place = PlacePicker.getPlace(data, getActivity()); 

तो, onActivityResult() करने के लिए कॉल में आता है, लेकिन यह एक ही समय है कि गतिविधि और टुकड़ा हो रही फिर से बनाई गई हैं पर ऐसा नहीं करता है, और PlacePicker.getPlace(data, getActivity()); पर कॉल करने के लिए आपको एक वैध संदर्भ की आवश्यकता है।

अच्छी खबर यह है सबसे अंत उपयोगकर्ताओं Do not keep Activities सेटिंग सक्षम नहीं होगा कि है, और ज्यादातर समय अपनी गतिविधि ओएस द्वारा नष्ट नहीं किया जाएगा।

+0

यह तब हो सकता है जब ओएस गतिविधि एक्टिविटीफॉर रिसेट कॉलिंग गतिविधि को हटा देता है। –

+0

@JawadLeWywadi आप सही हैं, यह फिर से पढ़ने मुझे एहसास हुआ कि इस उत्तर के कुछ मुद्दों पर था। बस संपादित, मुझे लगता है कि यह अब बेहतर है। धन्यवाद! –

+0

यह सही जवाब होना चाहिए, विशेष रूप से सेटिंग्स के संकेत के लिए "गतिविधियां जिंदा न रखें" .... – Opiatefuchs

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

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