savedInstanceState is not null but has no data - java

I have a fragment activity where I navigate to a search page, then back to the list with the result. Sometimes the activity needs to be re-created, so I am saving my instance data like so:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
System.out.println("Saving instance state!");
// Save the instance data
// Filter data
Intent mIntent = new Intent(this, BasicMapDemoActivity.class);
filter.addFilterToIntent(mIntent);
outState = mIntent.getExtras();
// Save date data
int year = currentDate.getYear();
int month = currentDate.getMonth();
int day = currentDate.getDay();
outState.putInt("YEAR",year);
outState.putInt("MONTH",month);
outState.putInt("DAY",day);
// Location data
double latitude = mapLocation.latitude;
double longitude = mapLocation.longitude;
outState.putDouble("LATITUDE",latitude);
outState.putDouble("LONGITUDE",longitude);
// Other
outState.putString("VIEW_MODE",viewMode.toString());
outState.putString("SORT_TYPE",sortType);
outState.putInt("ZOOM", mapZoom);
}
Then I am attempting to restore the data in onCreate, but when I get there, the bundle is not null, but it does not contain any of the data I saved to it. All of the following get functions return zero (I confirmed that the data was non-zero at the end of the above code block):
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// If we are 're-creating', then get the old instance data, otherwise set defaults
if(savedInstanceState == null)
{
// Set up default instance data
currentDate = new Date(115,4,1);
filter = new ObajoFilter();
filter.start = currentDate;
filter.end = new Date(115,4,1,23,59,0);
viewMode = ViewMode.MAP;
sortType = "Distance";
mapLocation = userLocation;
mapZoom = 16;
} else {
// Get date data
int year = savedInstanceState.getInt("YEAR");
int month = savedInstanceState.getInt("MONTH");
int day = savedInstanceState.getInt("DAY");
currentDate = new Date(year,month,day);
Any ideas on what could be emptying out the bundle? From what I understand, the savedInstanceData is only empty once the app is completely destroyed.

Because of this line outState = mIntent.getExtras();
Your outState points to different address mIntent.getExtras(), So it's empty
You should use outState.putXX directly without creating new object.

Are you storing the information that you want to retain in the onSaveInstanceState something like the following
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putParcelable("someobject", someobject);
outState.putBoolean("someboolean", someBoolean);
outState.putInt("someint", someInt);
super.onSaveInstanceState(outState);
}

Related

LinkedHashSet does not main insertion order?

I am currently building an Android app where I display quotes from famous people. I have a home screen and 2 other screens, where I am displaying all quotes and the other where I display favourite quotes.
So, when I hit the like button in the screen of AllQuotesActivity the quote and author will be saved in a LinkedHashSet, which will be saved in SharedPreferences, so my FavouriteQuotes Activity can obtain the data. I can obtain the data, but the data is mixed, even though other links say that LinkedHashSet maintains the insertion order. Maybe I did something wrong. Here are the important code snippets:
AllQuotesActivity.java:
SharedPreferences sharedPref;
Set<String> set = new LinkedHashSet();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.all_quotes);
Resources res = getResources();
Context context = getApplicationContext();
this.sharedPref = context.getSharedPreferences(
"MyPref", Context.MODE_PRIVATE);
final String[] quotesAndAuthors = res.getStringArray(R.array.quotes);
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
set.add(quotesAndAuthors[counter]);
set.add(quotesAndAuthors[counter + 1]);
}
});
}
#Override
public void onPause() {
super.onPause();
Log.d("RichQuotes", "Its paused mkay");
Editor editor = sharedPref.edit();
editor.putStringSet("quotesAndAuthors", this.set);
editor.commit();
}
}
FavouriteQuotesActivity.java:
SharedPreferences sharedPref;
Set<String> set = new LinkedHashSet();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favourite_quotes);
Resources res = getResources();
Context context = getApplicationContext();
this.sharedPref = context.getSharedPreferences(
"MyPref", Context.MODE_PRIVATE);
set = sharedPref.getStringSet("quotesAndAuthors", null);
for (Iterator<String> it = set.iterator(); it.hasNext(); ) {
String s = it.next();
Log.v("test", s);
}
I removed unnecessary code.
In the FavouriteQuotesActivity.java I am logging the set to check its values. The log-outputs and the outputs on the screen are the same, both unsorted the same way.
Set set = new LinkedHashSet();
In this line, you instantiate a new empty LinkedHashSet object. This object was then assigned to the variable named set.
set = sharedPref.getStringSet("quotesAndAuthors", null);
In this line, you reassigned the set variable to point to some other object, some Set object returned by your call to getStringSet. We do not know the concrete class of this second object that implements the Set interface. You can ask by calling getClass.
Your first set, the empty LinkedHashSet, went unused. With no other references pointing to it, that set became a candidate for eventual garbage-collection.

android SaveInstance in activity and garbage collector

Currently I am working on the second version of my vocabulary app. The first version does not provide as much documentation to expand the application. so I decided to start from the ground up.
I have an activity, every time I send it to background and then get it back to foreground, some objects became null and activity restarts. In onResume, I logged the value of the null object.
The old activity (version 1) does not have that problem.
I tried avoid that null problem whilst saving activities states and objects to SaveInstanceState and restore them. but RestoreInstance was never called.
here is my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_query);
Log.e(TAG, "onCreate");
/* Initialize DATA */
data = new DataHandler(this);
/* Initialize VIEWS */
btnPhase = findViewById(R.id.query_voc_phase);
cardPath = findViewById(R.id.query_voc_path);
queryView = findViewById(R.id.query_view);
btnShow = findViewById(R.id.query_btn_show_answer);
btnRight = findViewById(R.id.query_btn_mark_right);
btnWrong = findViewById(R.id.query_btn_mark_wrong);
btnNext = findViewById(R.id.query_btn_show_next);
}
#Override
protected void onStart() {
super.onStart();
Log.e(TAG, "onStart");
/* set OnClickListener */
btnShow.setOnClickListener(this);
btnRight.setOnClickListener(this);
btnWrong.setOnClickListener(this);
btnNext.setOnClickListener(this);
//init Variables
queryList = new ArrayList<>();
idList = new ArrayList<>();
listGroupings = new ArrayList<>();
answeredList = new ArrayList<>();
//init Preferences
preferences = PreferenceManager.getDefaultSharedPreferences(this);
//set Visibility of view items based on Preferences
if (!preferences.getBoolean(Preferences.SHOW_CARD_PATH_ENABLED, true))
cardPath.setVisibility(View.GONE);
//load preferences
userID = preferences.getInt(Preferences.CURRENT_USER, -1);
//check if flashing card is enabled and get time
flash_time = preferences.getBoolean(Preferences.FLASH_CARD_ENABLED, false) ? preferences.getInt(Preferences.FLASH_TIME, flash_time) : -1;
//get data from intent
Intent intent = getIntent();
if (intent.hasExtra(QUERY_CONTAINER_LIST)) {
//get data into the list
HashMap<String, ArrayList<Integer>> queryData = data.getCardsToQuery(intent.getStringArrayListExtra(QUERY_CONTAINER_LIST));
idList = queryData.get("iList");
listGroupings = queryData.get("listGroupings");
}
// change active Fragment to initial fragment
changeFragment(QueryViews.Simple);
}
#Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume");
Log.e(TAG, "current card is null " + (currentCard == null));
//loads a new card if there is none
if(currentCard == null) loadNext();
}
/*
InstanceState
*/
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.e(TAG, "RESTORE");
queryList = savedInstanceState.getParcelableArrayList("queryList");
idList = savedInstanceState.getIntegerArrayList("iList");
listGroupings = savedInstanceState.getIntegerArrayList("listGroupings");
answeredList = savedInstanceState.getParcelableArrayList("answeredList");
currentCard = (VocabularyCard)savedInstanceState.getSerializable("currentCard");
lastCard = (VocabularyCard)savedInstanceState.getSerializable("lastCard");
}
#Override
protected void onSaveInstanceState(Bundle outState) {
Log.e(TAG, "SAVE");
outState.putParcelableArrayList("queryList", queryList);
outState.putIntegerArrayList("idList", idList);
outState.putIntegerArrayList("listGroupings", listGroupings);
outState.putParcelableArrayList("answeredList", answeredList);
outState.putParcelable("currentCard", currentCard);
outState.putParcelable("lastCard", lastCard);
super.onSaveInstanceState(outState);
}
Spotting below error, maybe it is a typo error, but may be the culprit of your null object issue. You restore iList inside onRestoreInstanceState,
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.e(TAG, "RESTORE");
idList = savedInstanceState.getIntegerArrayList("iList");
}
But inside onSaveInstanceState, you put idList,
#Override
protected void onSaveInstanceState(Bundle outState) {
Log.e(TAG, "SAVE");
...
outState.putIntegerArrayList("idList", idList);
...
super.onSaveInstanceState(outState);
}
I found a solution. I found out that onRestoreInstanceState will called if device rotates. First of all if something became null, you should first check if the object was assigned a value. in this case i overlooked, that the object was never assigned a value.

onSaveInstanceState() - only one passes

Update: including actual code
I am using ArrayList to fill a custom adapter and it works fine on orientation change etc.:
"onCreate"
myArrayList = savedInstanceState.getParcelableArrayList(myListkey);
"onSaveInstanceState"
savedInstanceState.putParcelableArrayList(myListkey, myArrayList);
and I can get it out fine
But.. I need to pass multiple variables and then it breaks, it looks like it´s only the one inserted last that I can get.
ex.1
"onCreate"
myNameString = savedInstanceState.getString(namekey);
myArrayList = savedInstanceState.getParcelableArrayList(myListkey);
"onSaveInstanceState"
savedInstanceState.putString(listkey, myNameString);
savedInstanceState.putParcelableArrayList(myListkey, myArrayList);
Here "myArrayList" is filled, but "myNameString" is null
ex. 2
"onCreate"
myArrayList = savedInstanceState.getParcelableArrayList(listkey);
myNameString = savedInstanceState.getString(namekey);
"onSaveInstanceState"
savedInstanceState.putParcelableArrayList(listkey, myArrayList);
savedInstanceState.putString(namekey, myNameString);
Here "myNameString" is filled, but "myArrayList" is null
original code:
#Override
protected void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
_listName = savedInstanceState.getString(getApplicationContext().getResources().getString(R.string.saved_instance_list_name));
_listItems = savedInstanceState.getParcelableArrayList(getApplicationContext().getResources().getString(R.string.saved_instance_list_items_edit));
}
... more code
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString(getApplicationContext().getResources().getString(R.string.saved_instance_list_name), _listName);
savedInstanceState.putParcelableArrayList(getApplicationContext().getResources().getString(R.string.saved_instance_list_items_edit), _listItems);
}

Android ListView only shows one item at a time

My program is that when a user enteres some information and clicks the "Submit" button, this data will be stored in a separate activity's list View.I have a Shared Preferences incorporated so that the data will be stored. The problem is that only one piece of information gets stored at a time. If I enter a new piece of data, the previous one is overwritten.
public class PreviousPractices extends Activity {
int minutes,hours;
String description;
String date;
ListView practiceList;
ArrayAdapter<String> adapter;
ArrayList<String> listItems = new ArrayList<String>();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.previous_practices_layout);
practiceList=(ListView)findViewById(R.id.practiceList);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,listItems);
practiceList.setAdapter(adapter);
getIntents();
LoadPreferences();
}
public void getIntents(){
if (getIntent().getExtras() == null) {
}
else {
Bundle extras = getIntent().getExtras();
hours = extras.getInt("Hours");
minutes = extras.getInt("Minutes");
description = extras.getString("Description");
date = extras.getString("dateOfPractice");
adapter.notifyDataSetChanged();
SavePreferences("LISTS", date);
}
}
Right now I'm only working with the date to simplify things. I'm not sure what the issue is, and I'd appreciate some help.

Why doesn't my call to the Facebook Graph API display anything?

Ok, so I'm editing this to include the whole class with some new code I added over the past couple of hours. Basically, I'm looking to populate a Google Map with markers that represent a Facebook user's checkins. Unfortunately, my code has not been cooperating - I've tried reviewing the documentation that Facebook provides and searching the web for answers without coming up with anything useful. So far all I've been able to get the app to do is validate the app's permissions with Facebook and display the map, though I had tested the ability to add markers with dummy values in an earlier version of the app and that worked fine.
My earlier question dealt with why my calls to the Graph API weren't displaying anything - I had made the same call as listed in the AuthorizeListener sub-class, but was merely attempting to output the raw JSON string in a log entry instead of manipulating it. I think that whatever was the cause of that problem is probably the same cause of my current problem.
Anyway, how do I get my app to display markers for locations a user has checked in to? I think my code gets me off to a pretty good start, but there are obviously issues in my AuthorizeListener sub-class. What do you guys think?
public class FBCTActivity extends MapActivity {
public static Context mContext;
List<Overlay> mapOverlays;
FBCTMarkerOverlay markerLayer;
ArrayList<OverlayItem> overlays = new ArrayList<OverlayItem>();
// Facebook Application ID
private static final String APP_ID = "";
Facebook mFacebook = new Facebook(APP_ID);
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.main);
// Set up Facebook stuff
mFacebook.authorize(this, new String[]{"user_checkins", "offline_access"}, new AuthorizeListener());
// Set up map stuff
MapView mMapView = (MapView)findViewById(R.id.map);
mMapView.setSatellite(true);
MapController mMapController = mMapView.getController();
mMapController.animateTo(getCurrentLocation());
mMapController.setZoom(3);
// Set up overlay stuff
mapOverlays = mMapView.getOverlays();
Drawable drawable = this.getResources().getDrawable(R.drawable.icon);
markerLayer = new FBCTMarkerOverlay(drawable);
// markerLayer is populated in the AuthorizeListener sub-class
mapOverlays.add(markerLayer);
}
/**
* Determines the device's current location, but does not display it.
* Used for centering the view on the device's location.
* #return A GeoPoint object that contains the lat/long coordinates for the device's location.
*/
private GeoPoint getCurrentLocation() {
LocationManager mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Criteria mCriteria = new Criteria();
mCriteria.setAccuracy(Criteria.ACCURACY_COARSE);
mCriteria.setPowerRequirement(Criteria.POWER_LOW);
String mLocationProvider = mLocationManager.getBestProvider(mCriteria, true);
Location mLocation = mLocationManager.getLastKnownLocation(mLocationProvider);
int mLat = (int)(mLocation.getLatitude()*1E6);
int mLong = (int)(mLocation.getLongitude()*1E6);
return new GeoPoint(mLat, mLong);
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private class AuthorizeListener implements DialogListener {
public void onComplete(Bundle values) {
new Thread() {
#Override
public void run() {
try {
String response = mFacebook.request("me/checkins"); // The JSON to get
JSONObject jObject = Util.parseJson(response);
JSONArray jArray = jObject.getJSONArray("data"); // Read the JSON array returned by the request
for (int i = 0; i < jArray.length(); i++) { // Iterate through the array
JSONObject outerPlace = jArray.getJSONObject(i); // The outer JSON object
JSONObject place = outerPlace.getJSONObject("place"); // Second-tier JSON object that contains id, name, and location values for the "place"
String placeName = place.getString("name"); // The place's name
JSONObject placeLocation = place.getJSONObject("location"); // Third-tier JSON object that contains latitude and longitude coordinates for the place's "location"
int lat = (int) (placeLocation.getDouble("latitude")*1E6); // The place's latitude
int lon = (int) (placeLocation.getDouble("longitude")*1E6); // The place's longitude
String date = outerPlace.getString("created_time"); // Timestamp of the checkin
overlays.add(new OverlayItem(new GeoPoint(lat, lon), placeName, "Checked in on: " + date)); // Add the place's details to our ArrayList of OverlayItems
}
mFacebook.logout(mContext); // Logout of Facebook
for (int i = 0; i < overlays.size(); i++) {
markerLayer.addOverlayItem(overlays.get(i));
}
} catch(IOException e) {
Log.v("FBCTActivity", e.getMessage());
} catch(JSONException e) {
Log.v("FBCTActivity", e.getMessage());
}
}
}.start();
}
public void onFacebookError(FacebookError e) {
Log.w("FBCTActivity", e.getMessage());
// TODO: Add more graceful error handling
}
public void onError(DialogError e) {
Log.w("FBCTActivity", e.getMessage());
}
public void onCancel() {
// TODO Auto-generated method stub
}
}
}
It might not be the reason but you haven't defined your app ID:
private static final String APP_ID = "";
Also, you have to override the onActivityResult in the activity where you call the mFacebook.authorize, so add this to your code:
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
mFacebook.authorizeCallback(requestCode, resultCode, data);
}
If you don't do so, your app won't get the token for the Graph and your connection will return a JSON error msg.

Categories

Resources