I have an app where in the mainActivity the user has about 5 options to choose from. Clicking one of them opens a new activity but essentially all 5 opens up identical activities with different headings. In the newly opened activities, users use multiple rating bars to delegate points to some specified attributes. Using SharedPreference, can I save the entire activity so when I back out, click on the same option everything isn't gone? Or do I need to save let's say, the individual rating bar values using the SharedPreference?
Here is some code for one of the activities that opens from a button click. Something is terribly wrong because it is crashing now. Any suggestions?
public class MageSkillScreen extends AppCompatActivity
{
public float skillPoints = 10;
public float strengthRating;
public float intellectRating;
public float wisdomRating;
public float dexterityRating;
public float totalSkill;
public float mageStrength;
public float mageDexterity;
public float mageIntellect;
public float mageWisdom;
public RatingBar strengthBar;
public RatingBar intellectBar;
public RatingBar wisdomBar;
public RatingBar dexterityBar;
Button submit;
//preferences
SharedPreferences magePref;
boolean rememberRatings = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mage_skill_screen);
strengthBar = (RatingBar) findViewById(R.id.mageStregth);
intellectBar = (RatingBar) findViewById(R.id.mageInt);
wisdomBar = (RatingBar) findViewById(R.id.mageWisdom);
dexterityBar = (RatingBar) findViewById(R.id.mageDext);
submit = (Button) findViewById(R.id.submit);
}
#Override
public void onPause()
{
SharedPreferences.Editor edit = magePref.edit();
edit.putFloat("strengthPts", strengthBar.getRating());
edit.putFloat("dexterityPts", dexterityBar.getRating());
edit.putFloat("intellectPts", intellectBar.getRating());
edit.putFloat("wisdomPts", wisdomBar.getRating());
//edit.putString("pointsLeft", ptsRemaing.getText().toString());
edit.commit();
super.onPause();
}
#Override
public void onResume()
{
super.onResume();
rememberRatings = magePref.getBoolean("mageRatings", true);
mageStrength = magePref.getFloat("strengthPts", 0.0f);
mageDexterity = magePref.getFloat("dexterityPts", 0.0f);
mageIntellect = magePref.getFloat("intellectPts", 0.0f);
mageWisdom = magePref.getFloat("wisdmPts", 0.0f);
}
}
update view activity in function onResume
#Override
protected void onResume() {
super.onResume();
//load SharedPreferences again and update view
}
Okay, let's go step by step.
So I have an app where in the mainActivity the user has about 5
options to choose from.
Okay, sounds good, so you have 5 buttons in MainActivity for users.
Clicking one of them opens a new activity but essentially all 5 opens
up identical activities with different headings.
Can, you please be more specific here, click on one button should launch one single activity not all 5. And this is not possible at a time only one activity exists for the user to view or interact with. Others, goes in the backstack.
Please read about activity lifecycle for the same.
https://developer.android.com/guide/components/activities/activity-lifecycle.html
Using SharedPreference, can I save the entire activity so when I back
out, click on the same option everything isn't gone?
No, you can't save the whole activity inside Sharedpreference. SharedPref is used to store key value pairs, like hashMap and only primitive values, you can store activities and you should never do it.
https://developer.android.com/reference/android/content/SharedPreferences.html
Now, coming back to the solution for the same.
It totally depends on the usecase you are trying to implement, if you are launching different activities on each button click and want to persist some data across other activities, store the primitive values in sharedpref
and then access it in other activities.This also holds, true if you want to persist the same data in app re-launch.
If not, then you can have a singleton object and modify it and access it, across other activities, make sure to make it null to avoid memory leak.
I hope it clears your doubt.
Cheers..!!
Related
Please give me a hand with an issue I am having with a ListView and its related data in my android development project.
I have an activity called OrderForm that gets started by an Intent from the activity UserProfile as such:
In UserProfile
Intent intent = new Intent(this, OrderForm.class);
startActivity(intent);
Then in OrderForm there is an EditText and an add button to add String items to an ArrayList, and the UI gets populated accordingly.
When I click the back button (back to UserProfile) and go via the Intent to OrderForm again, the UI does not show the list items, why is that?
I realize I can use Room for persistence and even SharedPreferences, but
I wanted to see if there is cleaner, more efficient method, otherwise the less code the better.
Also, maybe I'm not understanding them correctly, but I tried onSaveInstanceState and onRestoreInstanceState and they don't work for me.
Thanks in advance.
Here is part of the code from OrderForm
public class OrderForm extends AppCompatActivity {
ArrayList<String> list;
ListView itemList;
ArrayAdapter<String> arrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_form);
itemList = findViewById(R.id.itemList);
itemText = findViewById(R.id.item);
linearLayout = findViewById(R.id.no_items_container);
orderContainer = findViewById(R.id.orderContainer);
list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(this,
R.layout.list_item,R.id.rowItem, list)
{
#Override
public View getView(int position,
View convertView,
ViewGroup parent) {
// some custom stuff here
}
}
public void addItem(View view)
{
String item = itemText.getText().toString().trim().toLowerCase();
if(!item.isEmpty() && list.indexOf(item) == -1) {
arrayAdapter.add(item);
}
}
You need to understand how Activity lifecycles work.
https://developer.android.com/guide/components/activities/activity-lifecycle.html
Your issue is that when pressing the back button, your OrderForm Activity is destroyed and effectively your arraylist/list view is destroyed. To avoid this problem, you'll have to store the values somewhere for example SharedPreferences, create a text file holding your strings and store it, or return the arraylist back to the UserProfile class where you'll store/handle them (to do that use startActivityForResult() instead of startActivity())
When I click the back button (back to UserProfile) and go via the Intent to OrderForm again, the UI does not show the list items, why is that?
In your onCreate() method, you have this:
list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(..., list)...
Unless you persist your data in some way, list is always going to be empty when your activity starts up.
I realize I can use Room for persistence and even SharedPreferences, but I wanted to see if there is cleaner, more efficient method, otherwise the less code the better.
Exactly what you need to store will help define the best way to store it. For a simple list of strings, probably SharedPreferences is the simplest solution.
Also, maybe I'm not understanding them correctly, but I tried onSaveInstanceState and onRestoreInstanceState and they don't work for me.
These methods are used to store data when an activity is destroyed and then recreated, which commonly happens when the user rotates the device (but can also happen for various other reasons). When you exit your activity (by pressing back to UserProfile), these methods aren't triggered.
I have searched through StackOverflow, but have not found a proper answer yet.
I have created a ListView (iteration of a checkbox + itemview) and populated it through my customAdapter (which extends BaseAdapter).
I have a button which takes the values and print it on the screen via a Toast.
So far, so good.
Next step, I still have the button in the MainActivity, but the ListView is now in a child activity that I reach by clicking an image (ImageView placed in the MainActivity). I can still check the checkboxes, but I face two issues:
I am still not able to pass the values to the MainActivity, where they will be printed on screen (or manipulated)
As soon as I press the back button to go back to the MainActivity and I press again the image, every CheckBox that was checked is not checked anymore (they came back to default state)
I don't think that code is needed, as it comes from a standard implementation (ListView - customAdapter with ViewHolder implementation, ...), but in case just let me know.
Thanks a lot in advance!
You can put which checkboxes are checked into sharedpreferences. Then move the listview initialization code to Activity's onResume method.
Sample class to handle sharedpreferences data:
class DataHandler {
private final SharedPreferences dataStore;
DataHandler(Context mContext) {
dataStore = mContext.getSharedPreferences("appname", Context.MODE_PRIVATE);
}
int which() {
return dataStore.getInt("some_key",0);
}
void setCheckedItem(int itemwhat) {
dataStore.edit().putInt("some_key",itemwhat).apply();
}
}
For multiple values, you can put them into an array then convert them to string using toString() method and save. And, to get the values:
String x = "2,3,4,5"; //assume
String[] y = new String[]{x};
int checkablepositions = Integer.parseInt(y[0]); // y[0]....y[y.length-1]
Now, at MainActivity's onResume(), Assume that you have initialized ListView as 'mainList'.
CheckBox x1y2z3 = (CheckBox)mainList.getChildAt(new DataHandler(getBaseContext).which());
x1y2z3.setChecked(true);
And for Saving item,
I would recommend you to show them in an alert-dialog instead of in a Toast. Then set a Positive button to get the values from below code and save them.
Or, if you directly save the values from listview onClick :
mainList.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
new DataHandler(getBaseContext()).setCheckedItem(position);
}
});
That's it. I'm really new at programming (as you can see my StackOverFlow rep) but hope it will be able to help you.
The main concept is to : store the value → get the value → parse the value → show it on UI.
I have a problem. I have 3 activities (MainActivity, DetailsActivity, SettingsActivity) and in SettingsActivity I have a Togglebutton "Nightmode". What I want is, when the button is changed, change background of all three activities on gray color.
public class SettingsActivity extends AppCompatActivity {
//This is SettingsActivity(not Main one)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
TextView SettingsTitle = (TextView) findViewById(R.id.SettingsTitle);
TextView NightText = (TextView) findViewById(R.id.NightmodeText);
ToggleButton toggleNightMode = (ToggleButton) findViewById(R.id.toggleNightmode);
final RelativeLayout NightBG = (RelativeLayout) findViewById(R.id.NightBG);
final LinearLayout DetailsBG = (LinearLayout) findViewById(R.id.mainBG);
final LinearLayout HomeBG = (LinearLayout) findViewById(R.id.HomeBG);
toggleNightMode.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NightBG.setBackgroundColor(Color.parseColor("#545657"));
HomeBG.setBackgroundColor(Color.parseColor("#545657"));
DetailsBG.setBackgroundColor(Color.parseColor("#545657"));
}
});
NightBG is in the same activity as that java file (SettingsActivity). But HomeBG is in MainActivity and DetailsBG is in the DetailsActivity. Everytime I start the app, and press on that button, app craches. If I delete HomeBG and DetailsBG from this file, it works just fine with changing current layout's color to gray. Please help me.
One easy way to store little settings like this across multiple activities that may not be open/active at the time of the button click would be to use SharedPreferences.
It might be a little overkill for such a simple piece of code but you can always give it a try if you don't find anything else.
Your code could look something like this:
toggleNightMode.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Set the color of this activity
int color = Color.parseColor("#545657")
View view = SettingsActivity.this.getWindow().getDecorView();
view.setBackgroundColor(color);
// Save color preference
SharedPreferences sharedPref = SettingsActivity.this.getSharedPreferences("bgColorFile",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("color", color);
editor.apply();
}
});
And then when you open your activities you place something like this in the onStart() or onCreate() method of your activity:
// Get the color preference
SharedPreferences sharedPref = getSharedPreferences("bgColorFile",Context.MODE_PRIVATE);
int colorValue = sharedPref.getInt("color", 0);
View view = this.getWindow().getDecorView();
view.setBackgroundColor(colorValue);
So what you're actually doing is storing the background color as persistent data and fetching it once you reopen/open the activity that you want to have the color on. The benefit of this method is that whenever you close your app the preferred background color will be remembered. I hope this helps.
Change background for current activity in the same activity. Since DetailsActivity is not running, you can't do that, it gives you null pointer. Is kind of you are trying to eat 3 apples and you have just one. After current activity is started, change background.
Update:
You can do that in current activity and just in current activity:
findViewById(android.R.id.content).setBackground(getColor(R.color.your_color));
Don't try to call this in other activities that are not running.
setBackground()
or
setBackgroundColor()
If your other activities are open, you should send a message to the other activities by using an Intent.
How to send string from one activity to another?
When you receive the Intent you could then set the background of the activity.
If your other activities are not open yet, you will not be able to send an Intent to them. In this case you could have each Activity reference a static value in your main activity that could contain the current background color. You would want to reference that value on the other activities on create functions.
Here is an example on how to reference a variable from another activity.
How do I get a variable in another activity?
This might not be the most pretty way to handle it but it should work.
as Ay Rue said you have 2 options: use static variable for that button, and then in onResume of each activity, check the value of the static variable (true or false). or you can save a private variable nightMode and then pass this value in the intent when you need to move to the other two activities.
don't set the background color if you already set before and have an updated background color.
Below is the code which I'm using to return a number which should be 1 when the button is clicked. However when I try to get that number from another class, it always stays 0.
As you might recognize, I tried to change the number in the onClickListener and returned it below.
I also tried to use the onPause command so that it will return the number onPause but it still doesn't work.
public class MainActivity extends Activity {
public int number;
Button btnAngled;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
btnAngled = (Button) findViewById(R.id.btnAngled);
final Intent intent = new Intent(this, angledForeheadActivity.class);
btnAngled.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
number = 1;
startActivity(intent);
}
});
}
#Override
protected void onPause() {
super.onPause();
}
public int getNumber() {
return number;
}
}
I try to get the code in another class with:
MainActivity a = new MainActivity();
int number = a.getNumber();
Sorry for the noob question..
declare the variable as static variable. Then you can simply obtain the result you want since there is only one copy of that variable. If you want to pass the value using intent, you can call putExtra() of intent to carry information to another activity.
Intent reference page
What you actually want is getting the number from another Class. Don't mix the job with button click together. You should setup the concept of model to store data and seperate UI and data, UI just change/get the data.
I suggest you either of the two ways
Store the number in some global model, then you can get the number from another Class.
User Android Broadcast to transfer the data
Use static variable in Activity is not a good idea, it may cause memroy leak, though it can solve your problem.
I am new to android and am working on a fairly basic android application where users are able to create items that are added to a ListView. On creation of each item I create a instance of the 'clicker' class which keeps track of each items name/tick count/other statistics.
when on of the items in the list are clicked it launches a general activity, used by all of the items. I pass the 'clicker' class object to the activity so that it may construct initialize the textviews.
This is what happens when a list item is clicked (the clicker instances are created in a hashmap named clickers, so I first retrieve the key, then call clickers.get(key))
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// pass along some ID so that the new activity can retrieve info
String clickedName = clickerListItems.get(arg2);
Intent intent = new Intent(MainActivity.this, ClickerActivity.class);
intent.putExtra("clickerName", clickers.get(clickedName));
startActivity(intent);
}
This is how the general activity receives the info
public class ClickerActivity extends Activity {
protected Clicker currentClicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clicker);
Intent i = getIntent();
currentClicker = (Clicker) i.getSerializableExtra("clickerName");
TextView clickerHeader = (TextView) findViewById(R.id.clickerHeader);
clickerHeader.setText(currentClicker.getName());
final TextView countDisplay = (TextView) findViewById(R.id.countText);
countDisplay.setText(Integer.toString(currentClicker.getCount()));
final Button incrementButton = (Button) findViewById(R.id.incrementButton);
final Button resetButton = (Button) findViewById(R.id.resetButton);
(continues)
here's what the general activity looks like to add some perspective. It's fairly plain right now seeing as I am just starting out.
The issue is that say I click on item A of the ListView and increment it's counter (one of the stats) and then press the back button to return to the List Activity. Now if I click on the same listitem to reload the activity none of the data seems to have been saved. Is the clicker class instance not actually being altered? How do I save the info or restore the info? I would do something onRestoreInstanceState but since this is an activity that may be loaded by any item in the list that wouldn't work, right?
If there any clarification is required please let me know, thank you.
You can use shared preferences, to preserve those values.
http://developer.android.com/reference/android/content/SharedPreferences.html
By using this, none of your data will be lost. Just make sure that when you are starting the app again after killing it, you reset the values stored, so that your values are saved for activity relaunch, but not for app relaunch (unless you want it for that too).
EDIT: You can also put all your main code into an Asynctask(), so that processing would be done in the background and it would be kept alive even when you come out of the app.