How to add delay in Google Places API request? - java

I want to reduce request to Google Places API by adding delay for every user input but i am not sure how to implement this. This is what i usually do to add delay to my EditText waiting for user's input:
editTextEmail.addTextChangedListener(new TextWatcher() {
final Handler handler = new Handler();
Runnable runnable;
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
isEmailValid = false;
textInputLayoutEmail.setError(null);
enableDisableButton();
handler.removeCallbacks(runnable);
}
#Override
public void afterTextChanged(Editable s) {
runnable = new Runnable() {
#Override
public void run() {
callGooglePlacesAPI()
}
};
handler.postDelayed(runnable, 1000);
}
});
This is my code to call Google PLaces API:
editTextLocation.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
editTextLocation.setShowSoftInputOnFocus(false);
searchLocation();
}
}
});
public void searchLocation(){
try
{
editTextLocation.clearFocus();
//hide soft keyboard
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_OVERLAY)
.build(getActivity());
startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);
}catch (Exception e){
e.printStackTrace();
}
}
Is there a way to do this? Please help give advice on this. Thank you.

Related

How to disable button with multiple edit text using Textwatcher?

I am trying to disable my button if my input edit texts are empty. I am using text watcher for this. To test it out , i have only tried with only two edit texts to start.
However, my button stays enabled no matter what.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_profile);
fnameInput = findViewById(R.id.et_firstname);
lnameInput = findViewById(R.id.et_lastname);
numberInput = findViewById(R.id.et_phone);
emailInput = findViewById(R.id.et_email);
nextBtn = findViewById(R.id.btn_next);
fnameInput.addTextChangedListener(loginTextWatcher);
lnameInput.addTextChangedListener(loginTextWatcher);
nextBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
launchNextActivity();
}
});
}
Text watcher method
private TextWatcher loginTextWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String firstNameInput =firstNameInput.getText().toString().trim();
String lastNameInput = lastNameInput.getText().toString().trim();
// tried doing it this way
nextBtn.setEnabled(!firstNameInput.isEmpty() && !lastNameInput.isEmpty());
//What i've also tried
if(firstNameInput.length()> 0 &&
lastNameInput.length()>0){
nextBtn.setEnabled(true);
} else{
nextBtn.setEnabled(false);
}
}
#Override
public void afterTextChanged(Editable s) {
}
};
I expect the button to be disabled if one or all inputs are empty and enabled when all input fields are filled out.
create a method check all condition there like
private void checkTheConditions(){
if(condition1 && condition2)
nextBtn.setEnabled(true)
else
nextBtn.setEnabled(false)
}
call this method from afterTextChanged(Editable s) method
Let us consider this case for 2 EditTexts only as for now.
define 2 global CharSequence as below
CharSequence fName="";
CharSequence lName="";
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_profile);
fnameInput = findViewById(R.id.et_firstname);
lnameInput = findViewById(R.id.et_lastname);
numberInput = findViewById(R.id.et_phone);
emailInput = findViewById(R.id.et_email);
nextBtn = findViewById(R.id.btn_next);
fnameInput.addTextChangedListener(textWatcher);
lnameInput.addTextChangedListener(textWatcher2);
nextBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
launchNextActivity();
}
});
}
then you have to define different textwatcher for each of your Edittext
then inside each of these textWatcher assign values to CharSequence defined above
private TextWatcher textWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
fName=s;
validate(); //method to enable or disable button (find method below)
}
#Override
public void afterTextChanged(Editable s) {
}
};
now textWatcher2
private TextWatcher textWatcher2 = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
lName=s;
validate(); //method to enable or disable button (find method below)
}
#Override
public void afterTextChanged(Editable s) {
}
};
now write validate method
void validate(){
if (fName.length()>0 && lName.length()>0){
nextBtn.setEnabled(true);
}else {
nextBtn.setEnabled(false);
}
}
Oh! You did a small mistake. Use OR condition instead of AND. So your code should be
nextBtn.setEnabled(!firstNameInput.isEmpty() || !lastNameInput.isEmpty());
And TextWatcher will only notify when you will manually change the inputs of EditText. So TextWatcher will not wark at starting. So at first in onCreate method you should manually check those EditText feilds.
Edit:
Android new DataBinding library is best suitable for this purpose.

TextWatcher crash when get edittext

After I type, it gives me the message: your app isn`t responding.
do you want to close it?
WAIT OK
I think because of the edt_search.gettext().tostring() inside the setData()
private void setupViews() {
edt_search = findViewById(R.id.edt_search);
progress = findViewById(R.id.progress);
progress.hide();
edt_search.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
if (editable.length() != 0) {
setData();
}
}
});
}
private void setData() {
AndroidNetworking.post("uri")
.addBodyParameter("word", edt_search.getText().toString())
.build()
.getAsObjectList(Search.class, new ParsedRequestListener<List<Search>>() {
#Override
public void onResponse(List<Search> searches) {
for (Search search : searches) {
searchList.add(search);
adapter.notifyDataSetChanged();
}
loading(false);
}
#Override
public void onError(ANError anError) {
Log.e("android-networking", "error: " + anError.getLocalizedMessage());
}
});
}
You are probably guessing it right. By empiric experience, I found out it's problematic to call methods from EditText inside afterTextChanged method (at least without removing the text watcher first). If possible, it's much better to use the Editable object that is passed as an argument. So, in your case, you could try two approaches:
First (easiest and which I most recommend in this specific case): Pass your string to the method setData(), so you don't need to access your EditText in this method:
....
#Override
public void afterTextChanged(Editable editable) {
if (editable.length() != 0) {
setData(editable.toString());
}
}
....
private void setData(String searchString) {
AndroidNetworking.post("http://akhbaresteghlal.ir/search/getInformations.php")
.addBodyParameter("word", searchString)
.build()
....
Second option (if, by any reason, you absolutely need to access your editText directly): Remove the TextWatcher before calling setData() (and any method from EditText) and then add it again after.
....
#Override
public void afterTextChanged(Editable editable) {
if (editable.length() != 0) {
edt_search.removeTextChangedListener(this);
setData();
edt_search.addTextChangedListener(this);
}
}
....
private void setData() {
AndroidNetworking.post("http://akhbaresteghlal.ir/search/getInformations.php")
.addBodyParameter("word", edt_search.getText().toString())
.build()
....
Hope it helps!

Cancel postDelayed within onTextChanged

I want make Web service called after by 3 seconds every time you update value of EditText, but in case if you update value of EditText before 3 seconds, remove all delayed callback and wait for 3 sec for Web Service call.Please see my cod and let me know proper way to do this task
#Override
public void onTextChanged(final CharSequence s, int start, int before, int count) {
if (s.length() > 2) {
final Handler handler = new Handler();
handler.removeCallbacksAndMessages(null);
handler.postDelayed(
new Runnable() {
#Override
public void run() {
// Soap call
}
},
3000);
}
}
Try this code
It will solve your issue.
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
#Override
public void run() {
//Soap Call;
}
};
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
handler.removeCallbacks(runnable);
}
#Override
public void afterTextChanged(Editable s) {
handler.postDelayed(runnable, 3000);
}
});
Try this .
long lastTime = System.currentTimeMillis();
final Handler handler;
public void onTextChanged(final CharSequence s, int start, int before, int count) {
if(s.length() > 2) {
if (System.currentTimeMillis() - lastTime > 3000) {
startWork();
}
lastTime = System.currentTimeMillis();
}
}
public void startWork() {
if (null == handler) {
handler = new Handler();
}
handler.removeCallbacksAndMessages(null);
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Soap call
}
}, 3000);
}

Handling Chat typing or Stop typing event (Android)

I am handling typing events if user enter text in editext typing function sends requests to server and use removed text i want to stoptyping function do work but its not working.
How to check if user have removed text after entering text
mEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
new Thread(new Runnable() {
#Override
public void run() {
try {
session.typing();
} catch (OmegleException e) {
e.printStackTrace();
}catch(NullPointerException e){
e.printStackTrace();
}
}
}).start();
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(final CharSequence s, final int start,
int before, int count) {
new Thread(new Runnable() {
#Override
public void run() {
try {
if(start==-1){
session.stopTyping();
}
} catch (OmegleException e) {
e.printStackTrace();
}catch(NullPointerException e){
e.printStackTrace();
}
}
}).start();
}
});
I changed to following :
mEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
lengthBeforeType = mEditText.getText().toString().length();
}
public void onTextChanged(final CharSequence s, final int start,
int before, final int count) {
lengthAfterType = mEditText.getText().toString().length();
new Thread(new Runnable() {
#Override
public void run() {
try {
if((lengthAfterType-lengthBeforeType)<0){
session.stopTyping();
}else{
session.typing();
}
} catch (OmegleException e) {
e.printStackTrace();
}
}
}).start();
int lenghtAfterType;
int lenghtBeforeType;
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
lenghtBeforeType = yourEdittext.getText.toString.Lenght;
}
public void afterTextChanged(Editable s) {
lenghtAfterType = yourEdittext.getText.toString.Lenght;
if((lenghtAfterType-lenghtBeforeType)<0){
// user while deleted text
}else{
// user while typing
}
}

Android - False when make thread

I want: if user already put name and choose game types, user can click button 'OK' but if user doesn't already put name and choose game types, user can't click button 'OK'.
public class UserConfig extends Activity {
Button userConfigBack;
Button userConfigOK;
EditText userNameTextbox;
Spinner gameTypes;
private String gameType;
private String playerName;
private Handler handler;
Thread validation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user_config);
userConfigBack = (Button) findViewById(R.id.user_config_back);
userConfigOK = (Button) findViewById(R.id.user_config_ok);
userNameTextbox = (EditText) findViewById(R.id.user_name_textbox);
gameTypes = (Spinner) findViewById(R.id.game_types);
gameTimes = (Spinner) findViewById(R.id.game_times);
userConfigOK.setEnabled(false);
userConfigOK.setClickable(false);
setName();
setGameType();
handler = new Handler();
autoValidation();
OK();
}
public void setName() {
playerName = userNameTextbox.getText().toString();
userNameTextbox.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
playerName = userNameTextbox.getText().toString();
nameLabel.setText(playerName);
}
#Override
public void afterTextChanged(Editable arg0) {
}
});
}
public void setGameType() {
gameTypes.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View arg1,
int arg2, long arg3) {
gameType = (String) gameTypes.getSelectedItem();
gameTypeLabel.setText(gameType);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
public void OK() {
userConfigOK.setOnClickListener( new OnClickListener() {
#SuppressWarnings("deprecation")
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(UserConfig.this, EnemyConfig1.class);
startActivity(intent);
}
});
}
public void autoValidation() {
validation = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
if(!gameType.equals("")) {
if(!playerName.equals("")) {
userConfigOK.setEnabled(true);
userConfigOK.setClickable(true);
}
}
}
});
}
});
validation.start();
}
}
I create thread inside method AUTOVALIDATION. If editText not null and user already choose game types spinner, user can click button OK. But
userConfigOK.setEnabled(true);
userConfigOK.setClickable(true);
doesn't work.
You can't change any UI elements from another Thread. Try to use a runOnUiThread this should solve the problem.
You really should read this carefully: http://developer.android.com/guide/components/processes-and-threads.html This will save you al lot of time if you are working with Threads.
And here is an example that helped me a lot:
how to use runOnUiThread
add a text watcher to your edittext and then use this if elsestatement:
if(!userNameTextbox.getText().toString().equals("")){
//do your job
}else{
//Toast some thing
}

Categories

Resources