getting a result from startActivityForResult - java

i've a code that will get a image from the gallery and then set a gridSize with it.
the main code that will send android to the SizeSelection class.
PuzzleAcitivity:
if( resultCode == RESULT_OK) {
Intent gridSizeIntent = new Intent();
gridSizeIntent.setClass(this, SizeSelection.class);
startActivityForResult(gridSizeIntent, GRIDSIZE_VALUE_SELECT);
createGameBoard(SizeSelection.getGridSize(this));
}
but this is where the trouble kicks in: SizeSelection, when I hit the buttons that should activate and set a gridSize nothing happends. I think the problem is in getting the data from the SizeSelection to the main PuzzleActivity class.
sizeSelection:
protected static short getGridSize(Context content) {
if ( mIbtn3x3 == view) {
short gridSize = 3;
return gridSize;
}else if (mIbtn4x4 == view ) {
short gridSize = 4;
return gridSize;
}else if (mIbtn5x5 == view ) {
short gridSize = 5;
return gridSize ;
}
return gridSize;
}
how am I supposed to finish the getGridSize method? thanks in advance

When you start an activity for result, your current code does not block. That is, startActivityForResult() returns quickly and you do not have the result yet. In order to receive the result (once it is available), you must provide an onActivityResult(int, int, Intent) method in your calling class. That method will be called automatically once the result is available.
In your child activity, you must do two things to provide the result. First, you call setResult(int) to provide the current expectation of what the result will be. This does not return anything, it just prepares the result -- you may change it if you wish at any time prior to the second step. Second, you call finish() to finish your activity.
See http://developer.android.com/reference/android/app/Activity.html for full documentation.

I think that when you compare mIbtn... == view maybe there is not any match check it :)

Related

Making a network call to update UI from within an observer method in Android Kotlin

I'm building an app where a user can add their calendar availabilities, and delete these availabilities. I set up an observer method in the onViewCreated of my Fragment that's called everytime a user clicks on my calendar date. Through my current implementation, the code works as expected the first time and then I run into some weird bugs (API call doesn't go through / UI doesn't update as expected) in subsequent calls. My code is below:
init {
view.setOnClickListener {
dateTimeViewModel.haveOwnTimeslotsBeenUpdated.observe(
viewLifecycleOwner,
Observer { isOwnTimeslotUpdated ->
if (isOwnTimeslotUpdated) {
val startOfTimeframe =
LocalDate.now().yearMonth.minusMonths(10).atDay(1)
.atStartOfDay(timezone).toEpochSecond()
val endOfTimeframe =
LocalDate.now().yearMonth.plusMonths(10).atDay(1)
.atStartOfDay(
timezone
).toEpochSecond()
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
val response = dateTimeViewModel.getOwnTimeslots(
startOfTimeframe,
endOfTimeframe
)
val listOfTimeslots = handleResponse(response)
mapOfDatesAndTimeslots =
storeLocalDateAndTimeslotsInAMap(listOfTimeslots)
val dates = mapOfDatesAndTimeslots.keys
if(selectedDate in dates){
val listOfTimeslotsOnADate = mapOfDatesAndTimeslots[selectedDate]
val areTimeslotsWorthDisplaying = listOfTimeslotsOnADate!!.any{ timeslot ->
timeslot.timeslot_status == 0 || timeslot.timeslot_status == 1 || timeslot.timeslot_status == 2
}
if(areTimeslotsWorthDisplaying){
calendarDayDotView.visibility = View.VISIBLE
sortTimeslotsOnAParticularDate(listOfTimeslotsOnADate)
} else {
calendarDayDotView.visibility = View.INVISIBLE
clearRecyclerViews()
}
} else {
calendarDayDotView.visibility = View.INVISIBLE
clearRecyclerViews()
}
}
dateTimeViewModel.setHaveOwnTimeslotsBeenUpdatedToFalse()
}
}
)
}
}
After the first call, my UI to display the dot doesn't work as expected, and neither does my sorting of timeslots despite working fine the first time. I have a feeling it's because this line of code is called repeatedly : viewLifecycleOwner.lifecycleScope.launchWhenStarted but I could be wrong. I'm not sure if it's best practice to make an API call from within an observer method and then reset the observed variable to false, so please share your suggestions if any. Please help me, and thank you in advance :D
What does your view model look like ?
A red flag would be setting the observers within your click listener but I'm not sure of you're thinking about it hence more code would be nice to review

How to load items in a RecyclerView in the same order as the API calls are done?

That's my problem:
I need to display some items in a RecyclerView in the same order they are called from the server to match the given design. However, I think I may probably be missing something very obvious on how Java actually works, because even though my calls are done in order, I've noticed the code placed after them is executed before a result is got from the server and afterwards, when the UI is updated, the order for the items displayed is not the same as originally intended.
That's the piece of code that has been taken away some days of my life now..
getGetMetricRangeAPI("bp_dia");
getGetMetricRangeAPI("bp_sys");
getGetMetricRangeAPI("glucose");
getGetMetricRangeAPI("lung_fev1");
getGetMetricRangeAPI("vo2");
getGetMetricRangeAPI("visceral");
getGetMetricRangeAPI("body_fat");
mGoalsRecyclerView.setAdapter(mGoalsAdapter);
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
mGoalsRecyclerView.setLayoutManager(layoutManager);
mGoalsRecyclerView.setNestedScrollingEnabled(false);
// mGoalsList is returning empty, as it should update *after* the
// response from the server, but for some reason, and that's what is
// confusing me a lot at the moment, that part of the code is read
// before it, so this whole for loop is being ignored at the moment.
for (GetAdvancedGoal goal : mGoalsList) {
mGoalsAdapter.addItem(goal);
}
Any help on that is really very much appreciated!! Thanks a lot!!! :)
Ps: I think another title for my question could be:
How do I make sure actions happen sequentially in Java?
As if I could make sure I can populate my adapter only when the mGoalsList array is completely filled (or even the hashmap, as per the suggestions), I could then order and display the items according to the desired sequence.
Thanks very much for your help!
You have multiple API calling at same time, there must be dependency between all this. For ordering of list according to api calling, you can use numbering assigned to each api calling and create hashmap of return result with numbers and displaying of list can be done according to numbers. But this is worst idea i think.
For better and pure solution, if a core developer. you must go for RxJava, you must be hearing about this. Here is description link:
RxJava
In RxJava, you defines dependency between calling of api's, here you can define observer's and observable's. Where Observer's always listen to observable(Sorry find detail description in link), so you must be insure that. 4th api should be call always after 2nd or 3rd one. Go for it, sorry i don't have any code related to that right now. if i will got that will post here.
getGetMetricRangeAPI("bp_dia",1);
getGetMetricRangeAPI("bp_sys",2);
getGetMetricRangeAPI("glucose",3);
getGetMetricRangeAPI("lung_fev1",4);
getGetMetricRangeAPI("vo2",5);
getGetMetricRangeAPI("visceral",6);
getGetMetricRangeAPI("body_fat",7);
Add an integer to your API call. Save the response in a HashMap and sort it according to this order
for (GetAdvancedGoal goal : mGoalsList) {
mGoalsAdapter.addItem(goal);
}
//this is missing in your code
mGoalsAdapter.notifyDataSetChanged()
That's the implementation of the hashmap suggestion that solved my problem
Added answer from #Ammer on my fragment
getGetMetricRangeAPI("bp_dia",1);
getGetMetricRangeAPI("bp_sys",2);
getGetMetricRangeAPI("glucose",3);
getGetMetricRangeAPI("lung_fev1",4);
getGetMetricRangeAPI("vo2",5);
getGetMetricRangeAPI("visceral",6);
getGetMetricRangeAPI("body_fat",7);
And that's my adapter using hashmap instead of arraylist
public void addItem(final GetAdvancedGoal item, int position) {
if (position == 0) {
mHashMap.put(item, 0);
mHashMapInvertedKeyValue.put(0, item);
} else if (position == 1) {
mHashMap.put(item, 1);
mHashMapInvertedKeyValue.put(1, item);
} else if (position == 2) {
mHashMap.put(item, 2);
mHashMapInvertedKeyValue.put(2, item);
} else if (position == 3) {
mHashMap.put(item, 3);
mHashMapInvertedKeyValue.put(3, item);
} else if (position == 4) {
mHashMap.put(item, 4);
mHashMapInvertedKeyValue.put(4, item);
} else if (position == 5) {
mHashMap.put(item, 5);
mHashMapInvertedKeyValue.put(5, item);
}
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
GetAdvancedGoal getAdvancedGoal = null;
if (mHashMapInvertedKeyValue.get(position) != null) {
getAdvancedGoal = mHashMapInvertedKeyValue.get(position);
// Name
holder.update_goal_editText.setText(getAdvancedGoal.getValue());
// Image
int id = getAdvancedGoal.getImageID();
switch (id) {
case R.drawable.blood_pressure:
SharedPreferences preferences = mActivity.getSharedPreferences("ADVANCED_METRIC_BP_SYS", Context.MODE_PRIVATE);
String valueSys = preferences.getString("bp_sys", "");
holder.update_goal_editText.setText(getAdvancedGoal.getValue() + "/" + valueSys);
holder.goal_image.setImageResource(R.drawable.blood_pressure);
break;
case R.drawable.glucose_level:
holder.goal_image.setImageResource(R.drawable.glucose_level);
break;
case R.drawable.visceral_fat:
holder.goal_image.setImageResource(R.drawable.visceral_fat);
break;
case R.drawable.lung_function:
holder.goal_image.setImageResource(R.drawable.lung_function);
break;
case R.drawable.v02_max:
holder.goal_image.setImageResource(R.drawable.v02_max);
break;
case R.drawable.body_fat:
holder.goal_image.setImageResource(R.drawable.body_fat);
break;
}
}
}

If statement with booleans android

I have been having a problem with a Boolean in an if statement all day and it is really starting to irritate me now!! I have looked at other Android threads on here and the solutions just don't seem t work.
My code started off like this:
public class MainActivity extends Activity
{
public static boolean isSignedIn = false;
public final static String USERNAME_MESSAGE = "com.example.libnoise.MESSAGE";
Button btnSignIn;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSignIn = (Button) findViewById(R.id.btnSignIn);
Intent intent = getIntent();
String message = intent.getStringExtra(PlayZone.USERNAME_MESSAGE);
if(isSignedIn == false))
{
btnSignIn.setText("SignIn");
}
else
{
btnSignIn.setText(message);
}
}
Then I had a thought that made it's not like other languages and I only need one "=" sign so I had it as this:
if(isSignedIn = false)
{
btnSignIn.setText("SignIn");
}
else
{
btnSignIn.setText(message);
}
That didn't work and that's when I started looking online, after finding a previous thread on here changed it to the following:
if("false".equals(isSignedIn))
{
btnSignIn.setText("SignIn");
}
else
{
btnSignIn.setText(message);
}
Now that doesn't look right to me in the first place but hoped it would work and it didn't.
As this is the MainActivity it loads first however since I added all this, the app crashes before it will even load when I take out the if statement it work as expected.
Any ideas?
This
if (isSignedIn == false)
is perfectly correct. (You could also write if (!isSignedIn), but that's just a matter of style.)
Note that, since you never change the value of isSignedIn (at least not in the code you have shown us), it will always be false.
i think you can simply use
if(!isSignedIn)
{
btnSignIn.setText("SignIn");
}
else
{
btnSignIn.setText(message);
}
the way you followed is also correct i didn't find any mistake in except you are using extra bracket in condition if(isSignedIn == false))
If statements with boolean are same how you do it in Java, == is the right way to compare
The problem in your code is extra bracket
if (isSignedIn == false))
Just to deviate from the question, but point out what is possibly your problem, your null pointer could be because you are accessing a UI object that may well not be ready to have it's text set yet.
While some API versions cope fine with what you're doing, I've found many device/API combos simply aren't ready to have anything changed from what's in the xml until onStart. The general guidance is to load data in onCreate, but not start doing anything until onStart.

Finish, reload activities

I have application where Activity A allows to set some options and starts (after click on button) Activity B. User can do something in B and when he finishes, he has choice (RadioButtons):
repeat - it means the B Activity will run again with the same options (taken from A),
new - it means application finishes B Activity and goes back to A, where user can set options again and start B again,
end - it goes out from application (I suppose it should finish B and then A Activity).
First I have done this way:
Intent intent = getIntent();
finish();
startActivity(intent);
Another way I could use is to clean all parameters in this Activity, but above was more quickly.
Second is just a finish().
Third is the biggest problem and i don't know how to to this. I tried with startActivityForResult(), onActivityResult() and setResult() but i saw it's impossible to set different results depending on selected RadioButton.
Other method I found is
public static void closeAllBelowActivities(Activity current) {
boolean flag = true;
Activity below = current.getParent();
if (below == null)
return;
System.out.println("Below Parent: " + below.getClass());
while (flag) {
Activity temp = below;
try {
below = temp.getParent();
temp.finish();
} catch (Exception e) {
flag = false;
}
}
}
source
But don't know how to put in current Activity.
Could you help me with this?
"i saw it's impossible to set different results depending on selected RadioButton" isn't really clear to me. Anyway, I suggest you what I would do: Activity A starts Activity B with startActivityForResult() and A wait for a bundle coming from B. When you build the exit function from B to A, create a bundle with your result. In A, you will analyze the bundle coming from B and decide what to do with. If you would exit, call finish().
Edit: Ok this could be your case:
Activity A:
public class XY extends Activity {
// you need that as a flag to go back and forth:
protected static final int SUB_ACTIVITY_REQUEST_CODE_04 = 5337; // choose the number you want...
int result_from_B; // I usually use an int, choose as you want....
static final String KEY_FROM_B = "mKey";
#Override
protected void onActivityResult(int result,int resultCode,Intent data) {
super.onActivityResult(result, resultCode, data);
if (result == SUB_ACTIVITY_REQUEST_CODE_04) {
if (data!=null){
Bundle extras = data.getExtras();
result_from_B = extras.getInt(XY.KEY_FROM_B);
if (result_from_B==1) {
// do what you want
} else {
// do somthing else...
}
}
To call the Activity B, use this:
Intent i = new Intent(this,
ActB.class);
this.startActivityForResult(i,SUB_ACTIVITY_REQUEST_CODE_04);
In the Activity B:
public class ActB extends Activity{
protected final int SUCCESS_RETURN_CODE = 1; // you need it to come back
int result; // this is the result to give to activity A
}
// in the function to build the output:
// I suppose you have already put something in result:
Bundle bundle = new Bundle();
bundle.putInt(XY.KEY_FORM_B, result);
Intent mIntent = new Intent();
mIntent.putExtras(bundle);
ActB.this.setResult(SUCCESS_RETURN_CODE,mIntent);
finish();
This is basic. You can manage also booleans back and forth, arrays, all you want (admitted by a bundle). Just put it in a bundle and go :)
Don't forget to declare your classes (activities) in the Manifest otherwise it will throw an exception runtime.
First of all, you need to keep track of the Intent used to call B. Try the putExtra() method of the intent to B. You can also package everything into a Bundle and restore it with getExtras() (if I recall correctly, that's the method name). When on B, read the Intent used to call it and save the parameters. You also need to startActivityForResult(B) for the following to work.
repeat - it means the B Activity will run again with the same options
(taken from A),
You probably want to call, from B, Activity B again using the FLAG_ACTIVITY_SINGLE_TOP flag in this case. I assume you don't want to have two B instances. Otherwise, just don't use the flag.
Put the Bundle you received from the Intent (from A) again, and catch it (if using single top) in the onNewIntent() method (or just normally, onCreate, if not single top). It goes like this: B -> B onPause() -> B onNewIntent() -> B onResume().
new - it means application finishes B Activity and goes back to A,
where user can set options again and start B again,
Depending on the exact behavior you want, you could call A with FLAG_ACTIVITY_REORDER_TO_FRONT. In this case, you end up with A in the foreground and B in the background (pressing back will go back to B).
Or you could call finish() if you just don't want B anymore, and want to go back to A.
end - it goes out from application (I suppose it should finish B and
then A Activity).
Do nothing on B, setResult() to something like "RESULT_FINISH_EVERYTHING", and when taking care of the results in A (override "onActivityResult()", IIRC), finish activity A also.
but i saw it's impossible to set different results depending on
selected RadioButton.
You could setResult() depending on thw button checked in the radio button. You can set listeners to the radio group and read which button is selected. See RadioGroup.OnCheckedChangeListener or View.OnClickListener if you need actions for eadch individual radio button.
Really, not too complicated. It just depends on what you want. I can clarify all this if you want.
Good luck!

Accessing program data from within onClick() inner class

i'm trying to access an EditText from an onClick() method within an onClickListener implementation for a button. here's the code:
transmit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//data validation
///////////////////////
boolean valid = true;
if(((EditText)findViewById(R.id.drv_in)).getText().toString() == "") {
TX_FAIL_TEXT = "Missing Driver ID!";
showDialog(DIALOG_FAIL);
TX_FAIL_TEXT = "Transmission Failed!"; //reset the dialog fail text to default
valid = false;
}
Log.e("smsDRVERR",((EditText)findViewById(R.id.drv_in)).getText().toString());
//begin transmission
///////////////////////
if(valid) {
showDialog(DIALOG_TX_PROGRESS);
Thread t = new Thread(txRunnable);
t.start();
} else {
//do things if needed
}
}
});
the Log.e is never called (does not show up in logcat). and the program executes as if the conditional statement doesn't exist. how do i reference layout items properly in an onClick implementation? i've also tried the following line:
Log.e("smsDRVERR",((EditText)smsActivity.this.findViewById(R.id.drv_in)).getText().toString());
which was alluded to in this question i found on SO:
Inside OnClickListener I cannot access a lot of things - how to approach?
but it does not solve the problem. i'm missing something that i need to reference these items within this inner class, or maybe i have my syntax a bit jarbled. any help is appreciated.
You are not comparing your String correctly.
if(((EditText)findViewById(R.id.drv_in)).getText().toString() == "") {
is checking if the objects are equal, whereas you want to check if the values are equal. You should be using:
if(((EditText)findViewById(R.id.drv_in)).getText().toString().equals("")) {
Personally, I'd assign the value returned by getText to a String variable, rather than calling getText multiple times:
String myEditTextValue = (EditText)findViewById(R.id.drv_in)).getText().toString();
...
if ("".equals(myEditTextValue)) {
First, is your onClick method being called? Second, don't use == to do string comparisons; use .equals(). (Strings that are equal are not necessarily the same object, which is what == tests.)

Categories