Saving state causes app to crash - android

Log is saying activity cant be paused, and a number format exception, I'm trying to save state of two edit texts that hold numbers,but both can be empty or one can be empty
In my activity there are two edit texts the user can either enter numbers manually and move to the next step or open a calculator to add up some numbers, and set the total to one of the edit texts, i want to save the state so if he needs to fill both edit text using the calculator, the first number he set will still be there when they come back with the second number.
I don't know to deal with this, here is the last bit of code i tried.
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
double length =Double.parseDouble(edtNumber1.getText().toString());
double height = Double.parseDouble(edtNumber2.getText().toString());
outState.putDouble("LENGTH", length);
outState.putDouble("HEIGHT", height);
}
And in onCreate
if (savedInstanceState != null) {
double hght = savedInstanceState.getDouble("LENGTH");
double lnth = savedInstanceState.getDouble("LENGTH");
if (savedInstanceState.containsKey("LENGTH")); {
edtNumber1.setText(Double.toString(lnth));
}
if(savedInstanceState.containsKey("HEIGHT")); {
edtNumber2.setText(Double.toString(hght));
}
}

Try to call super.onSaveInstanceState(outState); at the end of the method and make sure your editText contain numbers.
Thus, change
double hght = savedInstanceState.getDouble("LENGTH");
by
double hght = savedInstanceState.getDouble("HEIGHT");
And delete your ; in if (savedInstanceState.containsKey("LENGTH")); and if (savedInstanceState.containsKey("HEIGHT"));

IT means that one (or both) of the text fields don't have a number. You need to catch that exception around ParseDouble and deal with it somehow (probably by using a default).

You have extraneous semi-colons after your "if" statements, turning them into no-ops and causing the blocks that follow to always be executed.

Related

Is it possible to see which functions are called in Logcat?

I know, there is a way to see which functions are called in log-cat is to write a log message on top for every function like this
#Override
protected void onDestroy() {
super.onDestroy();
Log.d("myTag","onDestroy function is called!");
// some logic
}
But it becomes irritating when you have more function.
So, I wonder if there is a way to see which functions are called in adb-logcat without writing log messages for every function.
I hope they can be fetched from somewhere in the stack but I couldn't find it.
You can try Hugo. In that case you have to annotate your methods with #DebugLog only. Then Hugo will generate logs for you (and will print out arguments and return value!). Example from GitHub:
#DebugLog
public String getName(String first, String last) {
SystemClock.sleep(15); // Don't ever really do this!
return first + " " + last;
}
And log output:
V/Example: ⇢ getName(first="Jake", last="Wharton")
V/Example: ⇠ getName [16ms] = "Jake Wharton"
Instead of printing log in every function. I (or most of the people) would suggest you to put debug.
To use debug first create breakpoints inside every function you want to check. To apply breakpoints simply left click in the area to the left of your code (refer image the pink circle represents a break-point).
Then to use Debug you have to press this button after successfully running your application.
As soon as the first method is called your application will pause at the break-point, then you can use F8 (or F6 if you are using eclipse settings) to move to next line, to move to next break-point you can press F9(or F8 if you are using eclipse settings). this way to can check all the functions being called.
This break-point method is really helpful if you just want to make sure that a particular function is being called.
Other than this if you still insist to know the details of all the functions you can store the stacktrace.
final StackTraceElement[] trace = new Throwable().getStackTrace())
StackTraceElement STrace = trace[1];
String className = STrace.getMethodName();

EditText not automatically saved on screen orientation change

I read that Android automatically saves the content of EditText objects when an application is about to be stopped or killed. However, in my app the content of an EditText is lost when screen orientation changes.
Is it normal behaviour? Do I then have to manually save/restore its content with onSaveInstanceState/onRestoreInstanceState? Or is there an easier method to tell Android to save it end restore it?
Edit:
I create the EditText object programmatically, not in XML. This turns out to be related to the problem (see accepted answer below).
This is not normal behavior.
First and foremost, ensure that you have IDs assigned to your EditText controls in the layout XML.
Edit 1: It just needs an ID, period. If you're doing this programmatically, it will lose state unless it has an ID.
So using this as a quick & dirty example:
// Find my layout
LinearLayout mLinearLayout = (LinearLayout) findViewById(R.id.ll1);
// Add a new EditText with default text of "test"
EditText testText = new EditText(this.getApplicationContext());
testText.setText("test");
// This line is the key; without it, any additional text changes will
// be lost on rotation. Try it with and without the setId, text will revert
// to just "test" when you rotate.
testText.setId(100);
// Add your new EditText to the view.
mLinearLayout.addView(testText);
That will solve your problem.
Should that fail, you'll need to save and restore state yourself.
Override onSaveInstanceState like so:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("textKey", mEditText.getText().toString());
}
And then restore in OnCreate:
public void onCreate(Bundle savedInstanceState) {
if(savedInstanceState != null)
{
mEditText.setText(savedInstanceState.getString("textKey"));
}
}
Also, please don't use android:configChanges="orientation" to try to accomplish this, it's the wrong way to go.
could you use android:freezesText="true" in the xml layout?
The easiest way I found to save an object on onSaveInstanceState is to implement serializable and put in bundle
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("myObj", myObj);
}
where myObj class implements serializable and in onCreate() method
if (savedInstanceState != null && savedInstanceState.getSerializable("myObj") != null) {
myObj = ((MyObj) savedInstanceState.getSerializable("myObj"));
}
One possible cause is that you override onSaveInstanceState but you forget to call the same for super class
super.onSaveInstanceState(outState);
State of all views in activity is auto saved UNLESS you override this functionality. Even if this is obvious, mistakes are possible.
You just need UNIQUE ID for the edit text. Make sure if you dynamically add edit text, chances of having same id can cause not restoring the text.
Same way if you add in xml, use unique id. Hope it will help someone.
FYI: EditText by default having setFreezesText as true

Issue with Android fragments: getView() returns null

Our app has several fragments. In one of them user fills several TextEdit fields. When he finishes he presses a button in the ActionBar to save the data. The Action just calls a private method named "saveData" that fetches all data from the fields and submit it to our server.
We have many stack traces from our users showing that getView() returns null in method saveData, but for just a small part of them. For most of them there is no problem at all. We cant reproduce the problem and we cant understand what might be causing it. The code is pretty simple:
View vw = this.getView();
EditText et;
et = (EditText)vw.findViewById(R.id.editEmail);
String email = et.getText().toString().trim();
et = (EditText)vw.findViewById(R.id.editPassword);
String password = et.getText().toString().trim();
The action is added in osResume, see below:
public void onResume() {
super.onResume();
MainActivity act = (MainActivity)this.getActivity();
act.bar.removeAllActions();
act.bar.addAction(new SaveAction());
}
Any ideas? How can we reproduce it?
Can you tell from your logs whether the problem is always for the same users / devices ?
I see from the code that you have submitted that the view is in the same fragment - is that actually the case ?
It's POSSIBLE that a fragment no longer in view can have their view destroyed in order to free up resources. e.g.
getView() returns null
If I suspected that this might be the case then I would attempt to recreate the problem on a phone / tablet / emulator with limited resources.
Good luck !

How to prevent user from proceeding without entering value in edittext in android app?

I am new to android and programming. I am writing an app for calculating BMI. It works fine but there is a problem. The basic structure is:
Weight: "Edittext"
Height: "Edittext"
Reset Calculate <--- buttons
The app hangs whenever the user presses calculate button without entering a value (Height or weight). thats happening because a mathematical calculation is taking place without any values. how can i prevent the calculation from taking place when there are no values?????
Thankyou in advance
In the onClick function for the calculate button, check to see if the values make sense. If they don't, then don't do anything...
prior to any operation check for null values .
onCkick(View V)
{
if(editWeight.getText() != null or editHeight.getText() != null)
{
//do operation
}
}

how to increment a variable in first activity depending on the TextView values in second activity

hi all I have a variable in first activity i need to add values returned from second activity and store it in this variables. Switching between activities happens multiple times.... Any ideas..?
here is a piece of code which stores current value each time and not the Sum of it...
double quantity = Double.parseDouble(s1[1]);
double amount = Double.parseDouble(s1[2]);
if(s1[3].equals(""))
{
totalint = (quantity*(amount));
Log.d("hitherebbbbbbb",((Double)totalint).toString());
grandTotal =+totalint;
}
else
{
deduction = Double.parseDouble(s1[3]);
totalint = ((quantity*(amount-deduction*amount/100)));
Log.d("hitherebbbbbbb",((Double)totalint).toString());
grandTotal =+totalint;
}
If the amount of variables stays the same you could always use sharedpreferences. They are super simple to use and you can add a sharedpreference listener to update your activity when a value is changed. If the amount of variables changes (eg you have 3 integers at one time but maybe your user can change it so you need 5) then I would do something a little more complex that may not be the best option but I like it because I find it more simple than a database. Let me know which scenario best describes your situation and I'll get you more documentation.
You probably want to return the values from the second activity through its return intent and do a startActivityForResult() in the first activity.
you would do this by creating an intent in your second activity, setting any relevant return data, and calling
setResult(Activity.RESULT_OK, returnIntent);
finish();
You will be called back in the onActivityResult() method when the second activity is finished. You would then extract the values from the return intent and update your local storage.

Categories

Resources