我有一個活動,它查找用戶位置(MyLocation類),然後使用地理點或沒有它,它運行一個AsyncTask連接到服務器並從我的服務器獲取城市列表。列表準備就緒後,將它們保存在ArrayList城市中。一旦城市ArrayList被填充,我希望它被保存爲好(證明配置更改)。 CityItem實現Parcelable。我將它們保存在onSaveInstanceState中並在onCreate上檢索它們。配置更改後丟失對變量的引用
現在,一切工作正常,如果任務已完成,並填寫了城市列表。然後我來回旋轉我的設備和Log.i(「StartActivity」,「城市列表下載:」+ cities.toString());被調用。
但,如果我旋轉設備被發現前的GeoPoint(或任務完成 - 很難說,因爲它發生快),然後
public void gotCities(ArrayList<CityItem> _cities){
cities = _cities;
Log.i("StartActivity", "gotCities("+cities.size()+"): "+cities.toString());
}
被調用(和城市是完全沒有在日誌中)但是當我再次旋轉它ArrayList城市似乎再次爲空。
看來,如果配置發生變化,並且savedInstanceState.cities爲空,ArrayList城市將以某種方式再次創建,它與gotCities()函數中的ArrayList不同。
我很確定這很容易,但我一直在尋找答案几個小時,我根本無法做到這一點。
代碼的活動:
public class StartActivity extends Activity {
public static final String PREFS_NAME = "PrefsFile";
MyLocation myLocationObject = null;
LatLngPoint point = null;
ArrayList<CityItem> cities = null;
FindCityTask task = null;
Activity startActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
if(savedInstanceState!=null) if(savedInstanceState.containsKey("cities")) cities = savedInstanceState.getParcelableArrayList("cities"); if(cities!=null) Log.i("Cities retrieved", cities.toString());
super.onCreate(savedInstanceState);
startActivity = this;
setContentView(R.layout.start);
//check if the configuration (orientation) has been changed
NonConfigurationObject nco = (NonConfigurationObject)getLastNonConfigurationInstance();
if(nco!=null) if(nco.myLocationObject!=null) myLocationObject = nco.myLocationObject;
if(nco!=null) if(nco.task!=null) task = nco.task;
if(cities==null){
Log.i("StartActivity", "Cities list is empty - retrieve them.");
if(myLocationObject==null){
getGeopoint();
}
} else {
Log.i("StartActivity", "Cities list downloaded:"+cities.toString());
}
}
private void getGeopoint(){
if(isOnline()){ //there is internet connection
if(myLocationObject==null){
myLocationObject = new MyLocation();
//calls function to check user location (returns false if no providers are enabled
if(!myLocationObject.getLocation(this, locationResult)){ /*TODO handle */Log.i("StartActivity", "Location providers disabled");}
}
} else { //not online - show msg
Log.i("StartActivity", "No internet connection");
}
}
//waits for user geopoint. then starts FindCityTask
LocationResult locationResult = new LocationResult(){
@Override
public void gotLocation(final Location location){
if(location!=null){
// location found
Log.i("StartActivity", "Received location: "+location.toString());
point = new LatLngPoint((float)location.getLatitude(), (float)location.getLongitude());
} else {
// location not found
Log.i("StartActivity", "No location received after 20 seconds");
point = null;
}
//RUN TASK to connect to server to get cities list (even if there's no geopoint)
task = new FindCityTask(startActivity);
task.execute(point);
}
};
public void gotCities(ArrayList<CityItem> _cities){
cities = _cities;
Log.i("StartActivity", "gotCities("+cities.size()+"): "+cities.toString());
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log.i("onSaveInstanceState", "onSaveInstanceState");
if(cities!=null) savedInstanceState.putParcelableArrayList("cities", cities);
}
@Override
public NonConfigurationObject onRetainNonConfigurationInstance() {
NonConfigurationObject nco = new NonConfigurationObject();
if(myLocationObject!=null){
nco.myLocationObject = myLocationObject;
}
if(task!=null){
nco.task = task;
}
return nco;
}
static class NonConfigurationObject{
MyLocation myLocationObject;
FindCityTask task;
}
gotCities()方法是從的AsyncTask onPostExecute稱爲:
@Override
protected void onPostExecute(Void result) {
if(this.activity!=null){
((StartActivity) activity).gotCities(cities);
}
}
但我從onSaveInstanceState回調,所以它被調用。位置獲取被移動到一個TimerTask(我的位置負責這個並將位置發送到locationResult)。我在第二個小時前找到了解決方案,但我想知道它是否正常。 – 2012-03-10 13:06:56
靜態字段沒問題。它的壽命與您的應用程序JVM一樣長,並且不受活動生命週期的影響。 – 2012-03-10 13:54:47
謝謝。但我仍然覺得我錯過了一些東西。我擔心城市變量只是被泄露。我想知道我在哪裏讓它發生。 – 2012-03-10 13:56:17