简体   繁体   中英

Is there a more efficient way to update the listview or loop through a string array

I am currently trying to write a simple word search program for android. It is supposed to match each letter searched by the user and display all matches from a local dictionary.

Everything is working for a smaller dictionary but when I try to use a larger one the program collapses. My guess is that my search function that loops through each word is to inefficient.

Following is the code for my project.

public class MainActivity extends ActionBarActivity {
    String[] items;
    int length;
    ArrayList<String> listItems;
    ArrayAdapter<String> adapter;
    ListView listView;
    EditText editText;

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView=(ListView)findViewById(R.id.listview);
        editText=(EditText)findViewById(R.id.txtsearch);
        items = readFile().split("\\n");
        initList();



        editText.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                length=s.toString().length();
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (s.toString().equals("")) {
                    initList();
                }
                else {
                    searchItem(s.toString());
                }
            }

            @Override
            public void afterTextChanged(Editable s) {
                if (s.toString().length() < length) {
                    initList();
                    for (String item:items) {
                        if (!item.toLowerCase().contains(s.toString().toLowerCase())) {
                            listItems.remove(item);
                        }
                    }
                }
            }
        });
    }

    public String readFile(){

        InputStream input = getResources().openRawResource(getResources().getIdentifier("words","raw", getPackageName()));
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();

        String finalstring = "";

        try {
            String line;
            br = new BufferedReader(new InputStreamReader(input));

            while ((line = br.readLine()) != null) {
               // finalstring += line + "\n";
                sb.append(line + "\n");
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return sb.toString();

    }

    public void searchItem (String searchword) {
        for(String item:items){
            if(!item.contains(searchword)){
                listItems.remove(item);
            }
        }
        adapter.notifyDataSetChanged();
    }


public void initList(){

        listItems=new ArrayList<>(Arrays.asList(items));
        adapter=new ArrayAdapter<String>(this, R.layout.list_item, R.id.txtitem, listItems);
        listView.setAdapter(adapter);
    }

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

}

As previously mentioned, I believe that my SearchItem(String SearchWord) is the problem but maybe there is something wrong with the data update of the adapter?

Note: I have used breakpoints and it crashes when the loop within SearchItem(String SearchWord) is called upon.

Many thanks guys!

I changed the editText and used searchView instead. That fixed the problem!

Put your code in handler and it will run after sometime of your search.

new Handler().postDelayed(new Runnable(

    public void run(){

       // your update code here..

    }

), 3000);

This is called breathing time while user is typing in the edit text. so as soon as he start typing it will not start searching the word but after 3 second it will start searching.

Hope this will help you.

Okay there are many issues here I like to address:

  1. If you have a large data set and want to Search in it, I would highly recommend using an SQLite Database. That is exactly what this databases are made for. See Storing and Searching for Data for further details

  2. Long running tasks like this should always run as an AsyncTask

  3. Consider your storage management! Eg. your readFile reads a file to an String, and than splits it to an Array. Why not directly split it while loading. You keep an array of all strings then afterwards create a list from it and afterwards copy it into an ArrayList. From this list you remove all entries that you do not need. When you think about all the copy work and how often you code runs threw the list, I think you can find a much faster solution by eliminating tasks!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM