I'm new to Android in general, so I looked up the documentation for AutoCompleteTextView.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, USERS);
AutoCompleteTextView textView = (AutoCompleteTextView)
findViewById(R.id.searchUserTextField);
textView.setAdapter(adapter);
I see that it's up and running with very little code.
private static final String[] COUNTRIES = new String[] {
"user1", "user1", "user3", "user4", "user5"
};
I realize this is a stretch, but what would the next steps be with respect to implementing an autocomplete function based on my ParseUser table, especially as the text in the AutoCompleteTextView is changed by one character at a time?. Obviously, I wouldn't populate the USERS array with a Parse query displaying all of my users on each attempted search. How would I logically arrange such a thing?
To begin with, I'd probably include a TextChangedListener:
adapter.setNotifyOnChange(true);
textView.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (count % 3 == 1) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
textview.setDropDownHeight(LayoutParams.WRAP_CONTENT);
adapter.clear();
// Run my background task here
}
}, 1000);
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
}
});
textView.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterview, View v,
int position, long arg3) {
// TODO Auto-generated method stub
searchUserTextField.setText(adapterview.getItemAtPosition(position)
.toString());
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
But what would I provide as the background task? What am I querying so that I'm not searching through, say, 1000 users all at once, which is how many users I have in my app currently?
This seems to work. It's static in the sense that it always prints out the first 100 users in your User class. I'm sure you could add a constraint that matches the first or second letters of the AutoCompleteTextView to the usernames.
ParseQuery<ParseUser> userQuery = ParseUser.getQuery();
userQuery.findInBackground(new FindCallback<ParseUser>() {
public void done(List<ParseUser> parseUsers, ParseException e) {
if (e == null) {
Log.d("users", "Retrieved " + parseUsers.size());
ParseUser[] data = parseUsers.toArray(new ParseUser[parseUsers.size()]);
String[] strings = new String[data.length];
for (int i = 0; i < data.length; i++) {
strings[i] = data[i].getString(ParseConstants.KEY_USERNAME);
}
// Test to see if it was correctly printing out the array I wanted.
// System.out.println(Arrays.toString(strings));
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_dropdown_item_1line, strings);
AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.searchUserTextField);
if(parseUsers.size() < 40) textView.setThreshold(1);
else textView.setThreshold(2);
textView.setAdapter(adapter);
} else {
Log.d("users", "Error: " + e.getMessage());
}
}
});
Related
based on the image below, I have NIK & NAMA fields. the concept is when I fill in the NIK field then I press the GET button it will display the name(NAMA FIELD)
Picture : Menu add
Database structure example
NIK
NAMA
96296
Farrasta
94878
Alfian
Java class
btnGet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NikKry = etNik.getText().toString();
getNama(); // THE FUNCTION
}
});
private void getNama(){
APIRequestData armNama = RetroMaster.konekRetrofit().create(APIRequestData.class);
Call<ResponseMaster> tampilNama = armNama.ardGetNama(NikKry);
tampilNama.enqueue(new Callback<ResponseMaster>() {
#Override
public void onResponse(Call<ResponseMaster> call, Response<ResponseMaster> response) {
// HOW TO CODE PROPERLY ?
}
#Override
public void onFailure(Call<ResponseMaster> call, Throwable t) {
}
});
}
PHP file
<?php
include ("koneksi.php");
$response = array();
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$NIK = $_POST["NIK"];
$query = "SELECT NAMA FROM MASTER_KRY WHERE NIK = '$NIK'";
$eksekusi = oci_parse($conn, $query);
$cek = oci_execute($eksekusi);
if($cek > 0){
$response["data"] = array();
while($ambil = oci_fetch_object($eksekusi)){
$F["NAMA"] = $ambil->NAMA;
array_push($response["data"], $F);
}
}else{
$response["pesan"] = "Data tidak tersedia";
}
}
else{
$response["pesan"] = "*&*%4668%*%^$%#*&*(()%$!##%";
}
echo json_encode($response);
oci_close($conn);
?>
If you used EditText then this method will be help you to notify when text change in EditText.
editTextObject.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) {
}
#Override
public void afterTextChanged(Editable s) {
// here you get text via "s.toString();"
NikKry = s.toString();
getNama();
}
});
If you used AutoCompleteTextView then this method will be help you like:
autoCompleteTextView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
NikKry = yourArrayList.get(position).getText().toString();
getNama();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
This depends on your entity of ResponseMaster. If the entity has field Nama and getter setter exists, you can use below:
if(response.isSuccessful()){
edNama.setText(response.body().getNama());
}else{
// show toast or log error
}
Firebase database contains data for different keys. I need to query and show this data with recyclerview. but since the same data are saved many times in the database, the same results appear many times in recyclerview. I want to prevent this. Even though the queried value is dozens of times in the database, I want it to be displayed only once in recyclerview. How can I do that. I will be happy if you help.
InfiniteFirebaseArray infiniteFirebaseArray = new InfiniteFirebaseArray();
infiniteFirebaseArray.getSearch(areaCode + phoneNumber);
mAdapter = new InfiniteFirebaseRecyclerAdapter<ContactList, NameViewHolder>(ContactList.class, R.layout.layout_search_contact_list_item,
NameViewHolder.class, mUserDatabase, mPageLimit) {
#Override
protected void populateViewHolder(NameViewHolder viewHolder, ContactList model, int position) {
Logger.enter();
if (model != null) {
String string = model.getDisplay_name();
String firstletter = string.substring(0, 1);
resultcount++;
viewHolder.name.setText(model.getDisplay_name());
viewHolder.phone.setText(model.getPhone_number());
viewHolder.userImageText.setText(firstletter);
ContactResult contactResult = new ContactResult();
contactResult.setName(model.getDisplay_name());
contactResult.setPhone(model.getPhone_number());
contactLists.add(contactResult);
Log.d("testcontacts",String.valueOf(contactLists.get(position).getName()));
viewHolder.callPhone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String phoneNumber = contactLists.get(position).getPhone();
callPhone(phoneNumber);
}
});
viewHolder.addContact.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String contactName = contactLists.get(position).getName();
String contactPhoneNumber = contactLists.get(position).getPhone();
addContact(contactName, contactPhoneNumber);
}
});
}
Logger.exit();
}
};
Search_Contact_List.setAdapter(mAdapter);
Search_Contact_List.addOnScrollListener(new EndlessRecyclerViewScrollListener(gridLayoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
Logger.enter();
mAdapter.more();
Logger.exit();
}
});
Database result:
public class Cari extends AppCompatActivity implements TextWatcher,View.OnClickListener {
TextView hasil, teks, teks2;
AutoCompleteTextView edit;
Button prev, terpilih;
String[] item = { "Matahari","Merkurius","Venus","Bumi","Mars","Yupiter","Saturnus","Uranus","Neptunus" };
hasil = findViewById(R.id.hasil);
edit = findViewById(R.id.edit);
edit.addTextChangedListener(this);
edit.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, item));
teks = findViewById(R.id.title);
Typeface customfont = Typeface.createFromAsset(getAssets(), "font/Starjout.ttf");
teks.setTypeface(customfont);
teks2 = findViewById(R.id.titleDes);
Typeface customfont2 = Typeface.createFromAsset(getAssets(), "font/Starjout.ttf");
teks2.setTypeface(customfont2);
terpilih = findViewById(R.id.pilih);
terpilih.setOnClickListener(this);
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
edit.getText();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//not used
}
public void afterTextChanged(Editable s) {
//not used
}
public void onClick(View a) {
switch (a.getId()) {
case R.id.pilih:
Toast.makeText(this, "Kamu memilih Planet "+edit.getText(), Toast.LENGTH_SHORT).show();
mpilih();
break;
}
}
private void mpilih() {
if (//what statement should add) {
//here too *hasil.setText();
}
else {
//here too
}
}
How to make if else statement and set TextView hasil to get res/value/string name sun
this my first time programming using android studio, so i don't know too much about java mobile code. And sorry for bad English. Hope you understand
Use getText() to get AutoCompleteTextView value.
Here's the example of checking condition if AutoCompleteTextView is empty.
private void mpilih() {
if (!TextUtils.isEmpty(edit.getText())) {
hasil.setText(getString(R.string.sun));
} else {
edit.setError("Please enter your selection");
}
}
If you're using only those fixed item as selection, i suggest you use Spinner instead..
EDIT
For multiple 'if' you can use it like this
if (edit.getText().equals("Matahari")) {
hasil.setText(getString(R.string.sun));
} else if (edit.getText().equals("Bumi"){
hasil.setText(getString(R.string.earth));
}
I have a textWatcher for my editText. The idea is:
I have two list views and they are both updated after every inserted in editText field character. Somehow I could't implement this using standart ArrayAdapter with filter method. So I had to make my own realization of search. At the beggining it seemed good, but as soon as I added to my data base more less enough data the interface started to freeze.
This is the call
inputSearch.addTextChangedListener(createAndReturnTextWatcher());
And this is the method that creates and returns textWatcher
private TextWatcher createAndReturnTextWatcher() {
final List<String> list = dbExtractor.getDataForSearchAdapters();
TextWatcher watcher1;
watcher1 = new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
if (cs.length() == 0) {
lv.setAdapter(null);
lv2.setAdapter(null);
dc.clickedOnce = true;
dc.decrement();
dc.checkDimCounter();
} else {
setSecondListData(list, String.valueOf(cs));
setFirstListData(list, String.valueOf(cs));
if (dc.clickedOnce) {
dc.increment();
dc.checkDimCounter();
dc.clickedOnce = false;
}
}
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
#Override
public void afterTextChanged(Editable arg0) {
}
};
return watcher1;
}
And this are methods that perform filtering
private void setSecondListData(List<String> inputData, String cs) {
List<String> result = turkishSearcher.performFiltering(inputData, cs);
ArrayAdapter turkAdapt = new ArrayAdapter(this, R.layout.dictionary_list_item, R.id.product_name,
result);
lv2.setAdapter(turkAdapt);
}
private void setFirstListData(List<String> inputData, String cs) {
List<String> result = normSearcher.performFiltering(inputData, cs);
ArrayAdapter turkAdapt = new ArrayAdapter(this, R.layout.dictionary_list_item, R.id.product_name,
result);
lv.setAdapter(turkAdapt);
}
And this is the class that filters data
public class TurkishSearcher extends Searcher{
#Override
int returnPosition() {
return 1;
}
#Override
String reverse(String couples) {
java.lang.String[] arr = couples.split(" — ");
return arr[1]+ " — " + arr[0];
}
#Override
String replaceTurkish(String words) {
if (checkWithRegExp(words)) {
return words.toLowerCase().replaceAll("ç", "c").replaceAll("ğ", "g").replaceAll("ı", "i").
replaceAll("ö", "o").replaceAll("ş", "s").replaceAll("ü", "u");
} else return words;
}
public static boolean checkWithRegExp(String word){
Pattern p = Pattern.compile("[öçğışü]", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(word);
return m.find();
}
}
I clearly understand that the way I keep data is wrong and the search algorhytm isn't good as well. But my question is:
Is it possible to avoid freezes using Threads for search implementations. Can i puth both searchers to their own threads to somehow avoid interface freezes? If it's possible, pls tell me the best place in code where I can use threads.
Thank you in advance!
You should never block the main thread by database operations. Instead use:
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... unusedParams) {
// TODO: do your database stuff
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
// TODO: refresh UI elements, because thread finished
super.onPostExecute(aVoid);
}
}.execute();
Best way to do long tasks in background thread. You can use asynctask to do this.
I have DB table with 10,000 rows which I want to display in the listview. I want to display first 20 and when the user scrolls down to the last item the next 20 should be loaded (and so on.). it really takes a lot of time to load all the datas in the listview so thats why i want it to load 20 datas first..
inside onCreate() Method the code is:
dbHelper = new WordDbAdapter(this);
dbHelper.open();
//Generate ListView from SQLite Database
displayListView();
then on the displayListView() method the code is like this:
#SuppressWarnings("deprecation")
private void displayListView() {
final Cursor cursor = dbHelper.fetchAllWords();
// The desired columns to be bound
String[] columns = new String[] {
WordDbAdapter.KEY_WORD,
WordDbAdapter.KEY_ROWID,
};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.Word,
R.id.imgStar,
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.word_info,
cursor,
columns,
to
);
ListView listView = (ListView) findViewById(R.id.Diclist);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
listView.setOnScrollListener(new OnScrollListener(){
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
int lastInScreen = firstVisibleItem + visibleItemCount;
if(cursor != null){
if(lastInScreen == totalItemCount && isLoadingMore == false){
isLoadingMore = true;
loadedPage ++;
new LoadWords().execute();
}
}
}
public void onScrollStateChanged(AbsListView view, int scrollState) {}
});
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the word name from this row in the database.
String wordSelected =
cursor.getString(cursor.getColumnIndexOrThrow("word"));
String wordSyllabication =
cursor.getString(cursor.getColumnIndexOrThrow("syllabication"));
String wordPartofSpeech =
cursor.getString(cursor.getColumnIndexOrThrow("partofspeech"));
String wordMeaning =
cursor.getString(cursor.getColumnIndexOrThrow("meaning"));
String wordSpeak =
cursor.getString(cursor.getColumnIndexOrThrow("speakword"));
EditText TextDic = (EditText) findViewById(R.id.TextDic);
TextDic.setText(wordSelected);
speakMeaning = wordMeaning;
speakSyllabication = wordSyllabication;
speakPartOfSpeech = wordPartofSpeech;
speakWord = wordSpeak;
speakGetWord = wordSelected;
//Toast.makeText(getApplicationContext(),
// wordSyllabication + "\n" + wordPartofSpeech + "\n" + wordMeaning , Toast.LENGTH_SHORT).show();
}
});
EditText TextDic = (EditText) findViewById(R.id.TextDic);
TextDic.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
speakWord = "";
speakMeaning = "";
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
dataAdapter.getFilter().filter(s.toString());
}
});
dataAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return dbHelper.fetchWordsByWord(constraint.toString());
}
});
}
then my AsyncTask is like this:
private class LoadWords extends AsyncTask<String, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(DictionaryActivity.this);
Cursor cursor = dbHelper.fetchAllWords();
#Override
protected void onPreExecute() {
this.dialog.setMessage("Loading books...");
this.dialog.show();
}
public void execute() {
// TODO Auto-generated method stub
}
#Override
protected Void doInBackground(String... arg0) {
try{
cursor = dbHelper.fetchAllWords();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
#SuppressWarnings("deprecation")
#Override
protected void onPostExecute(final Void unused){
if(cursor != null){
if(dataAdapter == null){
startManagingCursor(cursor);
String[] columns = new String[] {
WordDbAdapter.KEY_WORD,
WordDbAdapter.KEY_ROWID,
};
int[] to = new int[] {
R.id.Word,
R.id.imgStar,
};
getListView().setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
dataAdapter = new SimpleCursorAdapter(DictionaryActivity.this, R.layout.word_info, cursor, columns, to);
ListView listView = (ListView) findViewById(R.id.Diclist);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
}else{
dataAdapter.notifyDataSetChanged();
}
}
if(dialog != null && dialog.isShowing()){
dialog.dismiss();
}
isLoadingMore = false;
}
private AbsListView getListView() {
// TODO Auto-generated method stub
return null;
}
}
The adapter doesn't load everything at once, and that should not be the reason you're seeing poor performance. ListView and SimpleCursorAdapter are fully capable of scrolling a list of only 10,000 items. The adapter only loads items as the user scrolls through the list. From the code that you've posted, I would say that your performance issues come from
dbHelper.deleteAllWords();
dbHelper.insertSomeWords();
If you post the code for these methods and dbHelper.fetchAllWords(), perhaps we can offer more help. Additionally, you can solve user interface problems by executing these long running tasks on a background thread (check out AsyncTask) and using a ProgressDialog to inform the user what is going on.
Take a look at Endless Adapter from the great Mark Murphy. It makes it really easy. You'll have your dataset that contains just the items you're displaying. In the adapter you can then tell it to grab the next set from your database and add it to the dataset.