dynamic autocomplete textview displayes slowly,how to display faster? - android

I have written some code for autocompletetextview in custom dialog box.When typing some text that text dynamically search into the hashmap.This hashmap is with large lines of text.It works.But slowly giving me result.
AutoCompleteTextView searchText = (AutoCompleteTextView)searchDialog.findViewById(R.id.searchText);
if(searchText.getText()!=null){
// searchString = searchText.getText().toString().trim();
String[] autoList = getAutoCompletWords(searchText.getText().toString().trim());
ArrayAdapter<String> adapter = new ArrayAdapter<String>(ctx,android.R.layout.simple_dropdown_item_1line,autoList);
searchText.setAdapter(adapter);
}
private String[] getAutoCompletWords(String text){
Set<String> wordsSet = new TreeSet<String>();
Pattern wordPattern = Pattern.compile("\\b"+text+"\\w+",Pattern.CASE_INSENSITIVE);
Matcher matcher = wordPattern.matcher(bookContentMap.values().toString());
while(matcher.find()){
wordsSet.add(matcher.group());
}
String[] wordsArray = wordsSet.toArray(new String[0]);
return wordsArray;
}
If I take thread for above code it is giving me thread handler exception.Please give me an idea for quick response of list on autocomplettext.
Rajendar Are

To know for sure which bits are fast and which are slow, you need to use Android's profiler. Here are two things worth investigating, they're probably the largest resource drain:
You're compiling a regular expression each time a key is pressed, this is very slow. A better option would be to populate a database and query it instead.
You're creating both a TreeSet and an Array each time a key is pressed, which probably hurts.
Converting bookContentMap's values to a String is probably quite processor intensive. Consider caching this value.

Related

NumberPicker.Formatter does not seem to be invoking in Android

I am trying to use a NumberPicker to display an array of Strings, but when I try and get the value back of the current String, the value is the integer index value of the String within the array which is the default response.
I have been trying to use NumberPicker.Formatter to get the actual String as a value back as opposed to the integer index value. I have implemented this, but it doesn't seem to be invoked. Could someone please tell me why this is and what I can do to fix it. Thanks in advance.
Here is the code:
final NumberPicker npUnits = (NumberPicker) numberPickerView.findViewById(R.id.numberPicker2);
npUnits.setMinValue(1);
npUnits.setDisplayedValues(tableUnitsArray);
npUnits.setMaxValue(tableUnitsArray.length);
npUnits.setFormatter(new NumberPicker.Formatter()
{
#Override
public String format(int value)
{
ArrayList<String> stringArrayList = (ArrayList<String>) Arrays.asList(tableUnitsArray);
String defaultUnits = stringArrayList.get(value);
System.out.println("Value formatted result: " + defaultUnits);
return defaultUnits;
}
});
npUnits.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
NumberPicker allows you to pick your values based on the min and max values you specify. It does not need you to call setDisplayedValues(). NumberPicker uses the String array you specify as a set of alternate values which causes your formatter to be ignored. Try removing the call to setDisplayedValues().
If your values for your NumberPicker are not so straight forward (i.e not from min to max incrementing by 1), then you can transform your values in your formatter to get the desired number.
I have found out the answer to my question. NumberPicker.Formatter was the wrong thing that I was doing as I didn't actually need to format anything. I just needed to get the current value from the String[] displayed values.
This is the code that worked for me:
List<String> stringArrayList = (List<String>) Arrays.asList(npUnits.getDisplayedValues());
String defaultUnits = stringArrayList.get(npUnits.getValue() - 1);
I found a solution for a few bugs in NumberPicker that works in APIs 18-26 without using reflection and without using setDisplayedValues() here.

comparing edittext input to string array

Im new, so sorry if my question is lame.
But, im trying to make an AI chatbot (like, a simpler version of cleverbot that responds to certain input keywords.)
I have an edittext panel, which the user will input words to 'talk' to the AI. But, instead of coding every word in the java file, i want to compare the string input to an existing string array to check if the keyword is there and so that the AI can display the coressponding answer.
example:
if input is: Hellothere!
and on the string array, there is: Hello.
and:
If edittext=Hello, then display this: blah blah.
Here is my (amateurish) code:
public void onClick(View v){
Resources res = getResources();
String[] usernames = res.getStringArray(R.array.input2);
boolean submit_check = input1(wordy, usernames);
public boolean input1(String wordy, String[] input2){
if(candidate.equals(usernames))
{
wahh.start();
myString = res.getStringArray(R.array.OUTPUT);
pic.setImageResource(R.drawable.keel);
String q = myString[rgenerator.nextInt(myString.length)];
display.setText(q);
}
else{
wahh.start();
pic.setImageResource(R.drawable.keel);
myString = res.getStringArray(R.array.OUTPUT);
String q = myString[rgenerator.nextInt(myString.length)];
display.setText(q);
}
I think what you want is something more along the lines of this (pseudocode):
if(EditText.getText().Contains("Hello")) {
EditText.setText("What's up?");
}
You'd want to check if it contains a selection from the array though. If it does, get the index of the array. Based on the index, respond accordingly. The easiest way to do that would be using a for loop and a switch statement. Although AI is actually a lot more complicated than this, and my knowledge.

How to check if an Array contains specific term - Android

I currently have a statement which reads
if(Arrays.asList(results).contains("Word"));
and I want to add at least several more terms to the .contains parameter however I am under the impression that it is bad programming practice to have a large number of terms on one line..
My question is, is there a more suitable way to store all the values I want to have in the .contains parameters?
Thanks
You can use intersection of two lists:
String[] terms = {"Word", "Foo", "Bar"};
List<String> resultList = Arrays.asList(results);
resultList.retainAll(Arrays.asList(terms))
if(resultList.size() > 0)
{
/// Do something
}
To improve performance though, it's better to use the intersection of two HashSets:
String[] terms = {"Word", "Foo", "Bar"};
Set<String> termSet = new HashSet<String>(Arrays.asList(terms));
Set<String> resultsSet = new HashSet<String>(Arrays.asList(results));
resultsSet.retainAll(termSet);
if(resultsSet.size() > 0)
{
/// Do something
}
As a side note, the above code checks whether ANY of the terms appear in results. To check that ALL the terms appear in results, you simply make sure the intersection is the same size as your term list:
resultsSet.retainAll(termSet);
if(resultSet.size() == termSet.size())
You can utilize Android's java.util.Collections
class to help you with this. In particular, disjoint will be useful:
Returns whether the specified collections have no elements in common.
Here's a code sample that should get you started.
In your Activity or wherever you are checking to see if your results contain a word that you are looking for:
String[] results = {"dog", "cat"};
String[] wordsWeAreLookingFor = {"foo", "dog"};
boolean foundWordInResults = this.checkIfArrayContainsAnyStringsInAnotherArray(results, wordsWeAreLookingFor);
Log.d("MyActivity", "foundWordInResults:" + foundWordInResults);
Also in your the same class, or perhaps a utility class:
private boolean checkIfArrayContainsAnyStringsInAnotherArray(String[] results, String[] wordsWeAreLookingFor) {
List<String> resultsList = Arrays.asList(results);
List<String> wordsWeAreLookingForList = Arrays.asList(wordsWeAreLookingFor);
return !Collections.disjoint(resultsList, wordsWeAreLookingForList);
}
Note that this particular code sample will have contain true in foundWordInResults since "dog" is in both results and wordsWeAreLookingFor.
Why don't you just store your results in a HashSet? With a HashSet, you can benefit from hashing of the keys, and it will make your assertion much faster.
Arrays.asList(results).contains("Word") creates a temporary List object each time just to do linear search, it is not efficient use of memory and it's slow.
There's HashSet.containsAll(Collection collection) method you can use to do what you want, but again, it's not efficient use of memory if you want to create a temporary List of the parameters just to do an assertion.
I suggest the following:
HashSet hashSet = ....
public assertSomething(String[] params) {
for(String s : params) {
if(hashSet.contains(s)) {
// do something
break;
}
}
}

Calling a Resource by a string?

Here's the setup. I have a spinner, and each item in the spinner is associated with their own StringArray. I want to streamline the process of loading the StringArray when an item is selected in the spinner without using a bunch of if statements for each item.
The StringArray has the same name as the spinner item's text
Drawn out it would look like this:
String cat = parent.getItemAtPosition(pos).toString(); //Selected Spinner item (Category)
...
String catStringArray = "R.array." + cat;
listdata = getResources().getStringArray(catArray); //Get the StringArray
is there a way to do this correctly?
--Edit--
#EboMike
Your answer sent me on a hunt and ran into this which I'm now using:
Class res = R.array.class;
Field field = res.getField(selectedCategory);
int saId = field.getInt(null);
String[] myList = getResources().getStringArray(saId);
That's not a great approach. It's slow. It'd be better to have an internal integer array with all the R.string IDs or something similar.
If you really insist on using a string-based approach, use Resources.getIdentifier(). It's technically not a big deal if you only do it once.

How to efficiently manage search suggestion using Android QSB?

I try to make a dictionary using Quick Search Box in Android. As shown in the SearchableDictionary tutorial, it loads all (999 definitions)data and uses them as matches to the input text to get the search suggestion. in my case, I have 26963 rows of data that need to be suggest while user input a word on QSB. therefore, I want to grab the char data one by one from the QSB, so that it will be efficiently load necessary suggestion. how can i do this?
here's the code i use...
bringit(200);
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
// from click on search results
//Dictionary.getInstance().ensureLoaded(getResources());
String word = intent.getDataString();
//if(word.length() > 3){bringit(10);}
Dictionary.Word theWord = Dictionary.getMatches(word).get(0);
launchWord(theWord);
finish();
} else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
//SearchManager.
//String bb =
mTextView.setText(getString(R.string.search_results, query));
WordAdapter wordAdapter = new WordAdapter(Dictionary.getMatches(query));
//letsCount(query);
mList.setAdapter(wordAdapter);
mList.setOnItemClickListener(wordAdapter);
}
Log.d("dict", intent.toString());
if (intent.getExtras() != null) {
Log.d("dict", intent.getExtras().keySet().toString());
}
}
private void letsCount(String query) {
// TODO Auto-generated method stub
for(int i=0; i<query.length(); i++){
definite[i] = query.charAt(i);
}
}
public void bringit(int sum) {
// TODO Auto-generated method stub
String[] ss = new String[10];
Log.d("dict", "loading words");
for(int i=1; i<=sum; i++){
KamusDbAdapter a = new KamusDbAdapter(getApplicationContext());
a.open();
Cursor x = a.quick(String.valueOf(i));startManagingCursor(x);
if(x.moveToFirst()){
ss[0] = x.getString(1);
ss[1] = x.getString(2);
}
Dictionary.addWord(ss[0].trim(), ss[1].trim());
Log.v("Debug",ss[0]+" "+ss[1]);
//onStop();
}
}
I use SQLite to collect data. and the other code is just same as the tutorial...
Retrieving a cursor is generally slow. You only want to retrieve one cursor which contains all the matching results.
You should perform the searching using SQL rather than fetching everything. A FULL_TEXT search is usually fastest for text matching, it is however slightly more complicated to implement than a simple LIKE, but I highly recommend you give it a try.
So you want to execute an SQL statement like:
SELECT * FROM my_table WHERE subject_column MATCH 'something'
See SQLite FTS Extension for more information. You can also use wild-cards to match part of a word.
In terms of search suggestions there is really no point returning more than around ~100 results since generally no users ever bother to scroll down that far, so you can further speed things up by adding a LIMIT 0, 100 to the end of your SQL statement.
If possible only start getting cursors once the user has entered more than X number of characters (usually 3 but in you're case this may not be appropriate). That way you're not performing searches that could potentially match thousands of items.
You seem to be leaving lots of cursors open until the application closes them even though you don't actually need them anymore: instead of calling startManagingCursor just make sure to call x.close() after your if (x.moveToFirst()) { ... } - this will free up memory faster.
On an unrelated note: please don't name your variables and methods things like ss or bringIt() as it makes code hard to read -- what is ss and what does bringIt() bring exactly?
You could have a look at the full text search extension in SQL Lite. Idea is to have a SQL query that fetches only the matching results, not all the results and then filter.
There is also a sample for the Android SDK: com/example/android/searchabledict/DictionaryDatabase

Categories

Resources