Это может произойти из-за многих причин, но мы надеемся, что это редкое явление. ОС будет уничтожать Activity, если это необходимо, для восстановления ресурсов, что, скорее всего, произойдет на устройствах с меньшей памятью и вычислительной мощностью.
Использование параметра Do not keep Activities
- хороший способ протестировать этот сценарий, и в этом случае возникают другие проблемы, даже если активность/фрагмент действительно воссоздаются. Если этот параметр включен, активность и фрагмент будут уничтожены, когда будет показан PlacePicker, а затем, когда появится 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()
призваны как активность и фрагмент.
Вот результат визуально:
Затем после выбора места:
Затем я включил 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
Таким образом, вы можете увидеть, как активность и Fragment разрушаются, когда PlacePicker показано, и после того, как место выбрали в PlacePicker, выполнение кода никогда не к записи журнала Fragment processActivityResult
, и приложение никогда не показывало выбранное место на карте.
То есть из-за нулевой проверки Context:
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
, и большую часть времени ваша деятельность не будет уничтожена ОС.
* «Мое приложение уничтожается после вызова startActivityForResult.» * Вы имеете в виду, что он сбой? – codeMagic
Вы предоставили фильтр намерений в файле манифеста? Это необходимо, чтобы ваша деятельность могла быть воссоздана. – Mann
@codeMagic. Это не сбой. После вызова startActivityForResult я могу увидеть метод onDestory в вызове MainActivity. И когда я выбираю место из запущенного действия, он возвращается. Но мое приложение не воссоздает , если я выберем место достаточно быстро (до того, как моя MainActivity) будет уничтожено), onActivityResult будет вызван правильно. – Renjith