0

I need to include a search function for user to search through the listview.

This is my MainActivity.java

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // URL to the JSON data
        String strUrl = "http://10.0.2.2/get_stores.php";

        // Creating a new non-ui thread task to download json data
        DownloadTask downloadTask = new DownloadTask();

        // Starting the download process
        downloadTask.execute(strUrl);

        // Getting a reference to ListView of activity_main
        mListView = (ListView) findViewById(R.id.list);
        searchBox = (EditText)findViewById(R.id.searchBox);
    }

    /** A method to download json data from url */
    private String downloadUrl(String strUrl) throws IOException {
        String data = "";
        InputStream iStream = null;
        try{
            URL url = new URL(strUrl);

            // Creating an http connection to communicate with url
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

            // Connecting to url
            urlConnection.connect();

            // Reading data from url
            iStream = urlConnection.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

            StringBuffer sb  = new StringBuffer();

            String line = "";
            while( ( line = br.readLine())  != null){
                sb.append(line);
            }

            data = sb.toString();

            br.close();

        }catch(Exception e){
            Log.d("Exception:", e.toString());
        }finally{
            iStream.close();
        }

        return data;
    }

    /** AsyncTask to download json data */
    private class DownloadTask extends AsyncTask<String, Integer, String>{
        String data = null;
        @Override
        protected String doInBackground(String... url) {
            try{
                data = downloadUrl(url[0]);
            }catch(Exception e){
                Log.d("Background Task",e.toString());
            }
            return data;
        }

        @Override
        protected void onPostExecute(String result) {

            // The parsing of the xml data is done in a non-ui thread
            ListViewLoaderTask listViewLoaderTask = new ListViewLoaderTask();

            // Start parsing xml data
            listViewLoaderTask.execute(result);
        }
    }

    /** AsyncTask to parse json data and load ListView */
    private class ListViewLoaderTask extends AsyncTask<String, Void, SimpleAdapter>{

        JSONObject jObject;
        // Doing the parsing of xml data in a non-ui thread
        @Override
        protected SimpleAdapter doInBackground(String... strJson) {
            try{
                jObject = new JSONObject(strJson[0]);
                StoreJSONParser countryJsonParser = new StoreJSONParser();
                countryJsonParser.parse(jObject);
            }catch(Exception e){
                Log.d("JSON Exception1",e.toString());
            }

            // Instantiating json parser class
            StoreJSONParser countryJsonParser = new StoreJSONParser();

            // A list object to store the parsed countries list
            List<HashMap<String, Object>> countries = null;

            try{
                // Getting the parsed data as a List construct
                countries = countryJsonParser.parse(jObject);
            }catch(Exception e){
                Log.d("Exception",e.toString());
            }

            // Keys used in Hashmap
            String[] from = { "country","flag","details"};

            // Ids of views in listview_layout
            int[] to = { R.id.storename,R.id.icon,R.id.details};

            // Instantiating an adapter to store each items
            // R.layout.listview_layout defines the layout of each item
            adapter = new SimpleAdapter(getBaseContext(), countries, R.layout.restaurant_list, from, to);
            return adapter;
        }

        /** Invoked by the Android on "doInBackground" is executed */
        @Override
        protected void onPostExecute(SimpleAdapter adapter) {

            // Setting adapter for the listview
            mListView.setAdapter(adapter);
            met_search();

            for(int i=0;i<adapter.getCount();i++){
                HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(i);
                String imgUrl = (String) hm.get("flag_path");
                ImageLoaderTask imageLoaderTask = new ImageLoaderTask();

                HashMap<String, Object> hmDownload = new HashMap<String, Object>();
                hm.put("flag_path",imgUrl);
                hm.put("position", i);

                // Starting ImageLoaderTask to download and populate image in the listview
                imageLoaderTask.execute(hm);
            }
        }
    }

    /** AsyncTask to download and load an image in ListView */
    private class ImageLoaderTask extends AsyncTask<HashMap<String, Object>, Void, HashMap<String, Object>>{

        @Override
        protected HashMap<String, Object> doInBackground(HashMap<String, Object>... hm) {

            InputStream iStream=null;
            String imgUrl = (String) hm[0].get("flag_path");
            int position = (Integer) hm[0].get("position");

            URL url;
            try {
                url = new URL(imgUrl);

                // Creating an http connection to communicate with url
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

                // Connecting to url
                urlConnection.connect();

                // Reading data from url
                iStream = urlConnection.getInputStream();

                // Getting Caching directory
                File cacheDirectory = getBaseContext().getCacheDir();

                // Temporary file to store the downloaded image
                File tmpFile = new File(cacheDirectory.getPath() + "/wpta_"+position+".png");

                // The FileOutputStream to the temporary file
                FileOutputStream fOutStream = new FileOutputStream(tmpFile);

                // Creating a bitmap from the downloaded inputstream
                Bitmap b = BitmapFactory.decodeStream(iStream);

                // Writing the bitmap to the temporary file as png file
                b.compress(Bitmap.CompressFormat.PNG,100, fOutStream);

                // Flush the FileOutputStream
                fOutStream.flush();

                //Close the FileOutputStream
                fOutStream.close();

                // Create a hashmap object to store image path and its position in the listview
                HashMap<String, Object> hmBitmap = new HashMap<String, Object>();

                // Storing the path to the temporary image file
                hmBitmap.put("flag",tmpFile.getPath());

                // Storing the position of the image in the listview
                hmBitmap.put("position",position);

                // Returning the HashMap object containing the image path and position
                return hmBitmap;

            }catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(HashMap<String, Object> result) {
            // Getting the path to the downloaded image
            String path = (String) result.get("flag");

            // Getting the position of the downloaded image
            int position = (Integer) result.get("position");

            // Getting adapter of the listview
            SimpleAdapter adapter = (SimpleAdapter ) mListView.getAdapter();

            // Getting the hashmap object at the specified position of the listview
            HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(position);

            // Overwriting the existing path in the adapter
            hm.put("flag",path);

            // Noticing listview about the dataset changes
            adapter.notifyDataSetChanged();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    private void met_search() {
        // TODO Auto-generated method stub
        /**
         * Enabling Search Filter
         * */

        searchBox.addTextChangedListener(new TextWatcher() {

            public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {

            }

            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                          int arg3) {
                // TODO Auto-generated method stub

            }

            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub
                MainActivity.this.adapter.getFilter().filter(arg0);
            }
        });
    }

This is the JSONParser.java

public class StoreJSONParser {
    // Receives a JSONObject and returns a list
    public List<HashMap<String,Object>> parse(JSONObject jObject){

        JSONArray jCountries = null;
        try {
            // Retrieves all the elements in the 'countries' array
            jCountries = jObject.getJSONArray("storelistfood");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        // Invoking getCountries with the array of json object
        // where each json object represent a country
        return getCountries(jCountries);
    }

    private List<HashMap<String, Object>> getCountries(JSONArray jCountries){
        int countryCount = jCountries.length();
        List<HashMap<String, Object>> countryList = new ArrayList<HashMap<String,Object>>();
        HashMap<String, Object> country = null;

        // Taking each country, parses and adds to list object
        for(int i=0; i<countryCount;i++){
            try {
                // Call getCountry with country JSON object to parse the country
                country = getCountry((JSONObject)jCountries.get(i));
                countryList.add(country);

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return countryList;
    }

    // Parsing the Country JSON object
    private HashMap<String, Object> getCountry(JSONObject jCountry){

        HashMap<String, Object> country = new HashMap<String, Object>();
        String countryName = "";
        String flag="";
        /*String language = "";
        String capital = "";
        String currencyCode = "";
        String currencyName = "";*/

        try {
            countryName = jCountry.getString("STORENAME");
            flag = jCountry.getString("logo");
            /*language = jCountry.getString("language");
            capital = jCountry.getString("capital");
            currencyCode = jCountry.getJSONObject("currency").getString("code");
            currencyName = jCountry.getJSONObject("currency").getString("currencyname");*/

            /*String details =        "Language : " + language + "\n"; +
                    "Capital : " + capital + "\n" +
                    "Currency : " + currencyName + "(" + currencyCode + ")";*/

            country.put("country", countryName);
            country.put("flag", R.drawable.ninety_six);
            country.put("flag_path", flag);
            //country.put("details", details);

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return country;
    }

This is the error I am getting from logcat

java.lang.NullPointerException
            at android.widget.SimpleAdapter.getCount(SimpleAdapter.java:93)
            at android.widget.AdapterView.checkFocus(AdapterView.java:713)
            at android.widget.AdapterView$AdapterDataSetObserver.onInvalidated(AdapterView.java:836)
            at android.widget.AbsListView$AdapterDataSetObserver.onInvalidated(AbsListView.java:6288)
            at android.database.DataSetObservable.notifyInvalidated(DataSetObservable.java:50)
            at android.widget.BaseAdapter.notifyDataSetInvalidated(BaseAdapter.java:59)
            at android.widget.SimpleAdapter$SimpleFilter.publishResults(SimpleAdapter.java:383)
            at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)

All I need is for user to search through the listview via the edittext box provided. I have tried many solutions from google but it is not working for my situation.

SOFT1234
  • 181
  • 1
  • 6

1 Answers1

0

The NPE you're getting is caused by this:

at android.widget.SimpleAdapter.getCount(SimpleAdapter.java:93)

Which basically said that the items underlying your SimpleAdapter is null.

Make sure the return item from your JSON parser is not null by checking in this line in your MainActivity:

try{
    if(countryJsonParser.parse(jObject) != null) {
        countries = countryJsonParser.parse(jObject);
    }
}catch(Exception e){
    Log.d("Exception",e.toString());
}
Hadi Satrio
  • 4,272
  • 2
  • 24
  • 45