I have an application about pmt function. However there are so many conditions that need to be handled. Somehow the app will not work with having more than 12 if-else. I want to use switch case, but i still not really understand how to use switch case(been 1 and half month since my 1st try using eclipse).Any example will be highly appreciated.
here is my example code:
if(String1.toString().equals("condition1")){
//do something
if(String2.toString().equals("condition1.1")&& String3.toString().equals("condition1.2")){
//do something else
}
.
.
.
.
.
if(String2.toString().equals("condition1.##")&& String3.toString().equals("condition1.##")){
//do something else
}
}
else if(String1.toString().equals("condition2")){
//do something
if(String2.toString().equals("condition2.1")&& String3.toString().equals("condition2.2")){
//do something else
}
.
.
.
.
.
if(String2.toString().equals("condition2.##")&& String3.toString().equals("condition2.##")){
//do something else
}
}
if(String1.toString().equals("condition3")){
//do something
if(String2.toString().equals("condition3.1")&& String3.toString().equals("condition3.2")){
//do something else
}
.
.
.
.
.
if(String2.toString().equals("condition3.##")&& String3.toString().equals("condition3.##")){
//do something else
}
}
and still keep going....to handle all possibilities .I am wondering, How to do this in switch case . Or a better implementation if we have 3 times 3 conditions. For example a,b,c(suppose these three conditions can only be used once) and d,e,f and g,h,i then condition 1 is a,d,g ; condition 2 is a,d,h condition 3 is a,d,i ; condition 4 a,e,g........on so on
Note:Suppose that the API version is 8-11 (old android)
thanks
The answer is dependent on your target version of android. From KitKat and upwards (API Level 19+), Java 7's switch (String) is available. I'd also strongly suggest trying to group the subcases (condition n.x) into different methods. It just gets very unwieldly quickly, otherwise:
switch (String1.toString) {
case "condition1":
handleCase1(String2, String3);
break;
case "condition2":
handleCase2(String2, String3);
break;
}
If that still results in too complex code, you can try a lookup table together with a command pattern:
class ConditionKey {
final String String1;
final String String2;
final String String3;
public int hashCode(); // hash strings
public boolean equals(); // compare strings
}
interface ConditionCommand {
// use whatever arguments the operation needs, you can also
// add fields and initialize in the constructor
void perform(final ConditionKey key, /* [...] */);
}
Map<ConditionKey, ConditionCommand> actionMap = new HashMap<>();
actionMap.put(
new ConditionKey("condition1", "condition1.1", "condition1.2"),
new ConditionCommand() {
void perform(final ConditionKey key) {
// perform actions that need to be done
}
}
);
And then instead of the if-else or switch-case:
[...]
ConditionKey key = new ConditionKey(string1, string2, string3);
// get the action from the map
ConditionCommand command = actionMap.get(key);
// perform the command
command.perform(key);
since java 1.7 switch on string is supported.
you could annidate two switch:
switch(String1) {
case "condition1": {
switch(String2) {
case "condition1.1":
break;
// ... other cases
default:
break;
}
}
break;
// ... other cases
default break;
}
Related
With no problem, connected my app to firebase and I can test realtime database and other features, but when it comes to Phone Authentication, I am having problems. The problem is when Edittext is left empty and Button is clicked the app gets crashed. Don't know which code should be responsible for this problem.
Please help me to define it.
If you have carefully read the documentation of phone auth in firebase you will have below code:
private boolean validatePhoneNumber() {
String phoneNumber = mPhoneNumberField.getText().toString();
if (TextUtils.isEmpty(phoneNumber)) {
mPhoneNumberField.setError("Invalid phone number.");
return false;
}
return true;
Then either with if-else or switch-case
You should call this method
NOTE: onCLick method comes after btn.setOnClickListener depending upon your button id.
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button_start_verification:
if (!validatePhoneNumber()) {
return;
}
startPhoneNumberVerification(mPhoneNumberField.getText().toString());
break;
case R.id.button_verify_phone:
String code = mVerificationField.getText().toString();
if (TextUtils.isEmpty(code)) {
mVerificationField.setError("Cannot be empty.");
return;
}
verifyPhoneNumberWithCode(mVerificationId, code);
break;
case R.id.button_resend:
resendVerificationCode(mPhoneNumberField.getText().toString(), mResendToken);
break;
case R.id.sign_out_button:
signOut();
break;
}
}
Due to the codes which were not provided by you, I have written some references based on my own app. Please consider changing those and probably you wont get further crashes.
In eclipse i tried making a calculator. I had 2 separate text fields for two numbers and addition subtraction buttons. When i press add or sub button without entering values app crashes. Is there any possible way out?
public void onClick(View v) {
// TODO Auto-generated method stub
String l1= et1.getText().toString();
String l2= et2.getText().toString();
int a=0, b=0;
double result=0.0;
a=Integer.parseInt(l1);
b=Integer.parseInt(l2);
switch(v.getId())
{
case R.id.b1:
result=a+b;
break;
case R.id.b2:
result=a-b;
break;
case R.id.b3:
result = a*b;
break;
case R.id.b4:
if(b==0)
{
open("Cannot Divide By zero");
}
else result = a/b;
break;
}
et3.setText(Double.toString(result));
}
Clayton Oliveira's answer is good. It handles the empty input situation. This code handles all the cases where l1, l2 can not be parsed to integer.
try{
a=Integer.parseInt(l1);
b=Integer.parseInt(l2);
} catch(NumberFormatException e) {
Log.e("Wrong input", e.getMessage());
}
If no value was entered in the EditText, the Integer.parseInt() method will crash because the String passed is not a valid number.
a=Integer.parseInt(l1);
b=Integer.parseInt(l2);
Replace with:
if(!l1.isEmpty() && !l2.isEmpty()){
a=Integer.parseInt(l1);
b=Integer.parseInt(l2);
}else{
Toast.makeText(this,"Something is wrong!",Toast.LENGTH_SHORT).show();
}
Note: the code above only check if was entered something in the EditTexts, you should check if it's a number also. i will leave that part for you to learn ;)
You should post more detail about your code to get many support at here, but i guess you have get this problem:
Add or Sub function net two integer number to calculate but you not enter any value (number value) into Edittext (text field) and value is null or empty string so wrong.
Solution:
- You set edittext to require input number value not string
- you need check input value is empty (if true then do not something) to before calculate.
I've recently upgraded to cordova 5 and removed/recreated android platform in version 4.0.0 and uninstalled/reinstalled all plugins.
I also had to upgrade android sdk to sdk 22 instead of 21.
Since the update, I'm no more able to catch the menubutton event as described in the cordova documentation.
As it's still referenced in the edge docs, I assume it should still be working and I've seen nothing about this in the release notes.
back button is still working.
I tried to set the target-sdk to 19, it did not solve anything about the issue.
Edit:
I've dug into cordova source code and found in CordovaWebViewImpl.java I found a suspicious TODO comment :
public void setButtonPlumbedToJs(int keyCode, boolean override) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_BACK:
// TODO: Why are search and menu buttons handled separately?
if (override) {
boundKeyCodes.add(keyCode);
} else {
boundKeyCodes.remove(keyCode);
}
return;
default:
throw new IllegalArgumentException("Unsupported keycode: " + keyCode);
}
}
Well my answer would be "IT SHOULDN'T!!!!"
Cordova makes a list of keycode to handle but does not add the menu button and later on the keycode is compared to KeyEvent.KEYCODE_MENU only after the keycode has been skipped because it's not in the list.
I've tried to add a case for the menu button, but it turns out the function is only called with the code of the back button.
So now I know why it doesn't work but still not how to fix it.
Edit 02/2016:
As per latest Jira, the support of the menubutton is now fixed in java part in Cordova Android 5.1.0 but still not initialized from the javascript.
For the moment, as indicated by Jira user Keith Wong, you need to add a javascript call before you add your event listener :
document.addEventListener("deviceready", function() {
...
navigator.app.overrideButton("menubutton", true); // <-- Add this line
document.addEventListener("menubutton", yourCallbackFunction, false);
...
}, false);
clarent's answer didn't do it for me, the menu button still didn't respond.
I tried several patches, one other suggestion to disable the boundKeyCodes check completely didn't do it either, because then the backbutton behaviour would be compromised.
The clean way to get the old behaviour back should be as follows.
The boundKeyCodes check ensures, that custom behaviour is only executed when there actually is a custom event handler bound to the event. But binding an event handler to "menubutton" in your app's JS code no longer triggers the menubutton key code to be added to the boundKeyCodes list.
This is because the setButtonPlumbedToJs method is never executed for the "menubutton" handler in the first place AND even if it would, the switch statement in this method doesn't handle KEYCODE_MENU.
You can get that behaviour back quite easily, first you will have to apply the change suggested by clarent:
Handle KEYCODE_MENU
in CordovaLib/src/org/apache/cordova/CoreAndroid.java (around line 357, setButtonPlumbedToJs) add a case statement after the KEYCODE_BACK entry like this:
public void setButtonPlumbedToJs(int keyCode, boolean override) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
// TODO: Why are search and menu buttons handled separately?
if (override) {
boundKeyCodes.add(keyCode);
} else {
boundKeyCodes.remove(keyCode);
}
return;
default:
throw new IllegalArgumentException("Unsupported keycode: " + keyCode);
}
}
Then ensure that setButtonPlumbedToJs actually gets executed. You need two more changes for that.
Add framework handler
In CordovaLib/src/org/apache/cordova/CoreAndroid.java (around line 243, overrideButton) make the method look like this (add the last else-if clause):
public void overrideButton(String button, boolean override) {
if (button.equals("volumeup")) {
webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_UP, override);
}
else if (button.equals("volumedown")) {
webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_DOWN, override);
}
else if (button.equals("menubutton")) {
webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_MENU, override);
}
}
Add javascript handler call
In platform_www/cordova.js (around line 1532, bootstrap) change this line:
cordova.addDocumentEventHandler('menubutton');
to this:
var menuButtonChannel = cordova.addDocumentEventHandler('menubutton');
menuButtonChannel.onHasSubscribersChange = function() {
exec(null, null, APP_PLUGIN_NAME, "overrideButton", ['menubutton', this.numHandlers == 1]);
};
This will trigger the frameworks overrideButton method as soon as an event handler is added to "menubutton".
That should do it. I also added this solution as a comment to
https://issues.apache.org/jira/browse/CB-8921
and might be filing a pull request shortly.
Just add to function setButtonPlumbedToJs one line : case KeyEvent.KEYCODE_MENU:
public void setButtonPlumbedToJs(int keyCode, boolean override) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
So in onDispatchKeyEvent switch will work:
} else if (boundKeyCodes.contains(keyCode)) {
String eventName = null;
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
eventName = "volumedownbutton";
break;
case KeyEvent.KEYCODE_VOLUME_UP:
eventName = "volumeupbutton";
break;
case KeyEvent.KEYCODE_SEARCH:
eventName = "searchbutton";
break;
case KeyEvent.KEYCODE_MENU:
eventName = "menubutton";
break;
case KeyEvent.KEYCODE_BACK:
eventName = "backbutton";
break;
}
Now with cordova-android 5.1, the code has changed and my patch didn't work any-more (and sadly, with no patch the menu button is still not working in this version).
As I wanted to be able to upgrade the platform without having to review the code each time, I searched for a new way to get the menu button working again.
In cordova android 5.1 it turns out that everything is here in the java code for the button to be working, except that the menu button key is never added to the boundKeyCoded array.
It turns out that this array needs to be filled by a call from javascript (which is done for the back button and volume button, but neither for the search button or the menu button).
The code that is missing is something like that :
exec(null, null, APP_PLUGIN_NAME, 'overrideButton', ['menubutton' , true]);
(a js call to the java function overrideButton from CoreAndroid.java to tell to add the menu button key to the boundKeyCodes array.
I think this call should be added to platform.js, but since platform.js is used to build cordova.js during the platform add, I decided to make a after_platform_add hook that patchs the cordova.js file.
The advantage of this hook is that there's no java change and it should work even if you use a different webview like crosswalk.
So, first, in config.xml, in the android section add the hook :
<platform name="android">
....
....
<hook type="after_platform_add" src="scripts/android/patch_menubutton.js" />
....
....
</platform>
Then, in the scripts folder add the hook file patch_menubutton.js :
#!/usr/bin/env node
module.exports = function(ctx) {
var fs = ctx.requireCordovaModule('fs'),
path = ctx.requireCordovaModule('path');
var CordovaJSPath = path.join(ctx.opts.projectRoot, 'platforms/android/platform_www/cordova.js');
var data = fs.readFileSync(CordovaJSPath, 'utf8');
var result = data.replace(new RegExp("cordova\\.addDocumentEventHandler\\('menubutton'\\);", "g"), "cordova.addDocumentEventHandler('menubutton'); exec(null, null, APP_PLUGIN_NAME, 'overrideButton', ['menubutton' , true]);");
fs.writeFileSync(CordovaJSPath, result, 'utf8');
}
(it looks for the initialisation of the event handler for the menu button and appends the call to the overrideButton function, like described in the last part of FewKinG's answer)
Previously i am using if else condition for checking the edit text field its working but i need to change into switch case.I am not getting to implement switch case inside my code.please tell me how to implement that in switch case.
btnSave.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
/**
* Validation
*/
if(tvStartLocation.getText().toString().equalsIgnoreCase(""))
{
Toast.makeText(getActivity(),"Please enter start location", Toast.LENGTH_SHORT).show();
}
else if(tvEndLocation.getText().toString().equalsIgnoreCase(""))
{
Toast.makeText(getActivity(),"Please enter end location", Toast.LENGTH_SHORT).show();
}
else if(etStartOdometer.getText().toString().equalsIgnoreCase(""))
{
Toast.makeText(getActivity(),"Please enter Trip Start Odometer reading", Toast.LENGTH_SHORT).show();
}
else
{
gotonextfraggment();
}
You cannot use a switch-case construct in your case. In a switch-case, only one argument is matched with the case labels and if there is a match, that label is executed.
switch(arg) {
case "label1":
case "label2":
.
.
.
default:
}
arg is tested with label1, label2 and so on.
In your case, in every else-if, you are trying to test the equality of the text in different EditTexts with "". So your arg changes in every else-if. Even if you try to implement switch-case, the arg of your switch-case will change continuously and you'll not be able to go any further. You cannot even do this:
switch("") {
case edittext1.getText():
case edittext2.getText();
.
.
.
default:
}
Because the case labels must be literals not variable values.
So it is impossible to implement switch-case for the problem that you are facing
In fact what you've done right now is the perfect way to do it.
I have an imageview that has its imageresource set programatically. This image could have had its resource set by any of 3 drawables, which is chosen using various variables earlier in the class.
The 3 drawables are:
R.drawable.well_done
R.drawable.try_again
R.drawable.sorry_failed
When I click on this image, it could have any of these three drawables set to it, so I'm trying to run a method something along the lines of this (I know this is totally wrong, but it might help visualise what I'm trying to do)
public void game(){
//STUFF
if(result>10){
imgView.setImageResource(R.drawable.well_done);}
//MORE STUFF
}
public void results_page(){
if(imgView=R.drawable.well_done){
//DO STUFF
}
if(imgView=R.drawable.try_again){
//DO STUFF
}
//etc...
}
Here is the proper code I have. Its a little more complex than my rubbish visualisation above, but I hope you understand what I'm trying to do.
ImageView iv_i;
//...
...onCreate(Bundle savedInstanceState){
//...
result1.setOnClickListener(onClL);
result2.setOnClickListener(onClL);
}
private void game() {
//...
result1.setImageResource(R.drawable.well_done);
result1.setTag(R.drawale.well_done)
result2.setImageResource(R.drawable.try_again);
result2.setTag(R.drawable.try_again);
//...
}
private OnClickListener onClL = new OnClickListener() {
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.result1:
ic_i = result1;
iv_i.setTag(result1.getTag());
break;
case R.id.result2:
iv_i = result2;
ic_i.setTag(result2.getTag());
break;
}
gotoResource();
}
};
private void gotoResource(){
Integer integer = (Integer) iv_i.getTag();
switch(integer){
case R.drawable.well_done:
//STUFF
break;
case R.drawable.try_again:
//STUFF
break;
case R.drawable.sorry:
//STUFF
break;
}
}
When I run this, I get a nullpointerexception at the line containing iv_i.setTag(result1.getTag());
What did i go wrong? Or how do I go about doing this properly, or another way of doing it that would be easier? Maybe converting the drawable to a string, then doing an if statement for the string, like: (also know this is completely wrong, but its just for a visualisation)
String resource = imgView.getDrawable().toString();
if(resource.equals("R.drawable.well_done")){
//DO SOMETHING
}
Thanks
Instead of relying upon the exact drawable the ImageView has, I suggest setting a tag on the ImageView to indicate which state it's in. I recently used this approach on a similar issue (determining whether a button is active or not), and it works well for me.
private static enum MessageViewType { SUCCESS, TRY_AGAIN, FAILURE }
public void game(){
//STUFF
if (result > 10){
imgView.setImageResource(R.drawable.well_done);}
imgView.setTag(R.id.image_view_status, MessageViewType.SUCCESS); // define image_view_status as a resource
}
//MORE STUFF
}
...
private void gotoResource(){
MessageViewType messageType = (MessageViewType) iv_i.getTag(R.id.image_view_status);
if (messageType == MessageViewType.SUCCESS) {
//STUFF
} else if (messageType == MessageViewType.TRY_AGAIN) {
// STUFF
} else if (messageType == MessageViewType.FAILURE) {
//STUFF
}
}
You can define the image_view_status id in any resource file. I personally use a file res > values > activity_resources.xml as follows:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="image_view_status" type="id" />
</resources>