Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

Creating Filter By activity from ListView Volley using JSON

Hello everyone!

I am trying to create a Filter By activity that is clickable from my actionbar in which some of the text that I use in my ListView Volley shows up in different categories using spinner or drop down option so when I press the filter button, it will only show what is selected. Have been trying to find different posts everywhere and the closests one is the following link: http://stackoverflow.com/questions/10973396/filter-a-listview-using-a-spinner-in-android. Although that post uses a ListView without Volley, its quite similar to the CustomAdapter I am using in my project.

He adds the following code to his adapter:

@Override
        public Filter getFilter() {

            Filter filter = new Filter() {

                @Override
                protected FilterResults performFiltering(CharSequence constraint) {

                    FilterResults results = new FilterResults();
                    ArrayList<HashMap<String, String>> filteredArrayVenues = new ArrayList<HashMap<String, String>>();
                    data.clear();

                    if (constraint == null || constraint.length() == 0) {
                        results.count = data.size();
                        results.values = data;
                    } else {
                        constraint = constraint.toString();
                        for (int index = 0; index < data.size(); index++) {
                            HashMap<String, String> dataVenues = data.get(index);

                            if (dataVenues.get(VenuesFragment.KEY_TAGS).toString().startsWith(
                            constraint.toString())) {
                                filteredArrayVenues.add(dataVenues);
                            }
                        }

                        results.count = filteredArrayVenues.size();
                        System.out.println(results.count);

                        results.values = filteredArrayVenues;
                        Log.e("VALUES", results.values.toString());
                    }

                    return results;
                }

                @SuppressWarnings("unchecked")
                @Override
                protected void publishResults(CharSequence constraint,
                FilterResults results) {

                    data = (ArrayList<HashMap<String, String>>) results.values;
                    notifyDataSetChanged();
                }

            };

            return filter;
        }

So my main question that I am asking is if somebody could give me a guidance on where to start and how I could integrate it with my JSON file.

This is my CustomListAdapter.java

package com.wlodsgn.bunbunup.adapter;

import com.wlodsgn.bunbunup.R;
import com.wlodsgn.bunbunup.app.AppController;
import com.wlodsgn.bunbunup.model.VeroxJeans;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;

/**
 * Created by WiLo on 3/3/2015.
 */
public class CustomListAdapter extends BaseAdapter {
    private Activity activity;
    private LayoutInflater inflater;
    private List<VeroxJeans> veroxJeansItems;
    ImageLoader imageLoader = AppController.getInstance().getImageLoader();

    public CustomListAdapter(Activity activity, List<VeroxJeans> veroxJeansItems) {
        this.activity = activity;
        this.veroxJeansItems = veroxJeansItems;
    }

    @Override
    public int getCount() {
        return veroxJeansItems.size();
    }

    @Override
    public Object getItem(int location) {
        return veroxJeansItems.get(location);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (inflater == null)
            inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null)
            convertView = inflater.inflate(R.layout.list_row, null);

        if (imageLoader == null)
            imageLoader = AppController.getInstance().getImageLoader();
        NetworkImageView thumbNail = (NetworkImageView) convertView
                .findViewById(R.id.thumbnail);
        TextView titulo = (TextView) convertView.findViewById(R.id.titulo);
        TextView marca = (TextView) convertView.findViewById(R.id.marca);
        TextView color = (TextView) convertView.findViewById(R.id.color);
        TextView tipo = (TextView) convertView.findViewById(R.id.tipo);
        TextView ref = (TextView) convertView.findViewById(R.id.ref);

        // getting verox jeans data for the row
        VeroxJeans m = veroxJeansItems.get(position);

        // thumbnail image
        thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);

        // titulo
        titulo.setText(m.getTitulo());

        // marca
        marca.setText(m.getMarca());

        // color
        color.setText(m.getColor());

        // tipo
        tipo.setText(m.getTipo());

        // referencia
        ref.setText(String.valueOf(m.getRef()));

        return convertView;
    }

}

If more info is needed, let me know.

Any help would be appreciated!

Harry James
Harry James
14,780 Points

Hey Wilfredo!

Before I go through ways you can go about doing this, there's a pretty important question I must ask.

How do you want to/how are you store(ing) your data?

So, by this, I mean are you wanting to use a database (e.g: SQLite), do you want to store from the code files itself (e.g: A variable storing all of the items), do you want to store from an external source (e.g: Parse) or do you have another idea in mind?

Depending on how you store the data depends on how you retrieve it.

I personally would recommend you use a database due to the fact that you're wanting to filter things. This means you're going to have relations on objects so, a sunhat, for example, would have a relation set up to be in the hats category.

You know your app better than I do though so, go for what you think is best and let me know and I'll try and find the best way to go about filtering items for you :)

Sure, no problem!

At first, I was using AsyncTask connected with JSON Parser and HttpRequest. It would go to a webhost that I am currentlly using in which it has phpMyAdmin and a FileManager to upload the images that I use. I would create database tables through phpMyAdmin and the text would show in the ListView with no problem but not the images via ImageView I had uploaded in FileManager. When I posted the problem in StackOverflow, I was recommended to use Google Volley in my ListView instead of AsyncTask. So I gave it a try and used this tutorial and was able to create a JSON file with the same info I had in myPhpAdmin database and uploaded it through the webhost's FileManager where the images are also stored. Now my TextView and ImageView shows with no problem.

So after writing that whole text of wall (sorry, just wanted to give you a history of what I have done in the project), yes, I want to use a database type of system and if it is possible, still use the JSON file I created to update my ListView.

Let me know what options are available :)

Once again, thanks for your time!

Harry James
Harry James
14,780 Points

That's a pretty sophisticated system you've got running there! So have you already set up the PHP system that exports data from your database in the JSON format and are able to retrieve items from your database in Android?

I still have the php system and files but I believe I am not using it since I switched to Google Volley. Now this is the file that I am using (not the tables I had created before when I had the AsyncTask, HttpRequest, and JSONParser) and these are the images that go inside the ListView now.

Hey Harry,

I forgot to mention that I will be also developing the same app for iOS so I guess that also has to be considered when checking which is the best option for this filter by and database option.

Let me know if you need more info

Have a nice day!

Harry James
Harry James
14,780 Points

Hello again!

I'm stuck with exams again until the end of the week so, I won't be able to post you a proper answer (With an example on) until the end of the week.

You have done most of the hard work already with the JSON file so, if you're interested in seeing how data can be retrieved from a JSON file, I'd highly recommend you take a look at the Soon to be discontinued Build a Blog Reader app Course. It is built on Eclipse but, the same concept applies here.

Alternatively, if you have time to wait till the end of the week, I should be able to get back to you then :)

No problem Harry!

Take your time in finishing your stuff and i'll in the meantime will check out this course.

Thanks for taking the time in helping :)

Harry James
Harry James
14,780 Points

In fact, it looks as though the newer Build a Weather App course also deals with JSON data and would be more up to date.

I haven't taken the course personally (Though plan on doing so) so I'm not sure as to whether it would be of help but, from the video titles, it looks like it should do the same job (But better!)

8 Answers

Harry James
Harry James
14,780 Points

Good news Wilfredo!

I managed to find some spare time in between my exams and got this done for you! I've tested my blog reader code out and adapted it with some of your data:

It's quite late now for me as I do have school tomorrow so, I'll get the code all sorted for you tomorrow! :)

Awesome! I really appreciate it. Thanks for taking the time out of your exams in helping create and understand the filter for the ListView :)

Harry James
Harry James
14,780 Points

Hey again Wilfredo!

I've put my project files into a zip file which you can download here

Along with the zip file are some instructions on how to import the project into Android Studio, should you need them.

Note that I haven't included everything from your JSON file and am only using three of the keys but, I'll leave the rest to you, I thought this would just act as a good starting point so that you can understand what is happening.

I've commented throughout the project so, everything should make sense but, if not, let me know what you don't understand :)

If you prefer to not download the project, you can also use the code which I will include some stripped down code below (This code is simply on how you access JSON data - I don't want to create a really long post of code even though it is already!)


GetJSONDataTask

    private class GetJSONDataTask extends AsyncTask<Object, Void, JSONArray> {

        @Override
        protected JSONArray doInBackground(Object... arg0) {
            // Set default values in case something goes wrong.
            int responseCode = -1;
            // Ignore this warning (Or suppress it). We are setting this default responseCode
            // in case something goes wrong.
            JSONArray jsonResponse = null;
            mData = null;

            try {
                // Start connection.
                URL jsonUrl = new URL("http://wlodsgn.x10host.com/json/vrxjns.json");
                HttpURLConnection connection = (HttpURLConnection) jsonUrl.openConnection();
                connection.connect();

                // Get the response code (If it is ok, if statement will run).
                responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    // This code will create an InputStream, storing each character and
                    // appending it to responseData.
                    InputStream inputStream = connection.getInputStream();
                    Reader reader = new InputStreamReader(inputStream);
                    int nextCharacter; // read() returns an int, we cast it to char later
                    String responseData = "";
                    while(true){ // Infinite loop, can only be stopped by a "break" statement
                        nextCharacter = reader.read(); // read() without parameters returns one character
                        if(nextCharacter == -1) // A return value of -1 means that we reached the end
                            break;
                        responseData += (char) nextCharacter; // The += operator appends the character to the end of the string
                    }

                    // Create a JSONArray (This is how you data is stored) with these characters.
                    jsonResponse = new JSONArray(responseData);
                }
                else {
                    Log.i(TAG, "Unsuccessful HTTP Response Code: " + responseCode);
                }
            } catch (Exception e) {
                Log.e(TAG, "Exception caught!", e);
            }
            return jsonResponse;
        }
        @Override
        protected void onPostExecute(JSONArray result) {
            mData = result;
            handleResponse();   // This is for you to handle this data - you can do this with a for loop as shown below, for example.
        }
    }

for loop to get JSONObjects

                for (int i = 0; i < mData.length(); i++) {
                    JSONObject post = mData.getJSONObject(i);

                    String title = post.getString(KEY_TITLE);
                    title = Html.fromHtml(title).toString();

                    String brand = post.getString(KEY_BRAND);
                    brand = Html.fromHtml(brand).toString();

                    HashMap<String, String> listItem = new HashMap<>();
                    listItem.put(KEY_TITLE, title);
                    listItem.put(KEY_BRAND, brand);

                    listItems.add(listItem);
                }

Hope it helps and good luck with your project! Any questions, give me a shout :)

Thanks a lot Harry! I'll be checking it out tonight or tomorrow since my PC's HD went nuts and its not letting me get in. Hope is not something bad and I am trying to get it fixed. Once again, thanks for taking your time and I will let you know if I need any help :)

Hey Harry!

Ok, so after a night of backing up my information from my now defunct hard drive, I was able to install android studio into my macbook pro and use it temporarily while I setup everything back into my new hard drive and get my PC back up and running.

I was able to check the example you did (which I really appreciate it) and basically thats the idea of creating my listview although when I click on any item in the list I would like to show an image with info like I did here with my listview using google volley:

This is ListView of the products

ListView Main

This is the next activity when you select on a product from ListView

ListView Selected Product

Now, what I would like to do is to have a Filter By in the actionbar where the listview of the products are located (actionbar in first image) just like JackThreads have in their application:

Jack Threads ListView with Filter

And this is the way I would like to show when you press on the filter

Jack Threads Filter

Any ideas on how to do it and which method I should use to implement it? I mean using Google Volley like the example I have above or do I have to use Asynctask and use a database like phpMyAdmin to create the filter.

Let me know :)

Thanks!

Harry James
Harry James
14,780 Points

I don't know how to go about this with Google Volley (I have never used Google Volley before) but, you can always filter with if statements by slightly modifying the for statement:

                for (int i = 0; i < mData.length(); i++) {
                    JSONObject post = mData.getJSONObject(i);

                    String title = post.getString(KEY_TITLE);
                    title = Html.fromHtml(title).toString();

                    String brand = post.getString(KEY_BRAND);
                    brand = Html.fromHtml(brand).toString();

                    HashMap<String, String> listItem = new HashMap<>();

                    if (title.equals("Verox's 1001 Jeans")) {
                        listItem.put(KEY_TITLE, title);
                        listItem.put(KEY_BRAND, brand);
                        listItems.add(listItem);
                    }
                }

As you can see, I've added a if statement that will check if the title is equal to Verox's 1001 Jeans. If it is, add the item to the list. If it isn't, ignore it.


Alternatively, you can also run this in the php file when outputting to JSON. So, instead of outputting everything to JSON, only output the JSONObjects you want.

Either way works, it's personal preference which way you want to do it!


Hope it helps and, if you have any more questions, give me a shout :)

Awesome! Going to give it a try and will let you know if need any help.

Thanks!

Hello Harry!

Sorry to bother you again but have been fiddling around with the project you sent me and implementing it to the one I am currently working with some modifications. Was trying to implement your code when pressing ListView to WebView and change it from a clicklistener NetworkImageView to a Fullscreen NetworkImageView in another activity.

This is the screenshot of the three images I want to make Fullscreen when pressed:

alt text

By the way, I decided to upload my project here So you can have an idea how I am elaborating everything and also you can see how Volley library is implemented and get to know it a little. A win win for both! :D

So, here is what I am doing right now under JeansDetailsActivity.java:

@Override
    public void onItemClick(NetworkImageView n, View v, int position, long id) {
        super.onItemClick(n, v, position, id);

        // Let's show the image when the user clicks on the entry!

        try {
            JSONObject obj = response.getJSONObject(i);
            String imgUrl = obj.getString("image");
            Intent intent = new Intent(this, JnsDetailsFSActivity.class);
            intent.setData(Uri.parse(imgUrl));
            startActivity(intent);
        } catch (JSONException e) {
            /**logException(e);**/
        }
    }

I am trying to implement a clicklistener so when the image is pressed, it will open another activity that will show the image in fullscreen but haven't been able to solve the errors that are being shown (You will see them when you open the project). Hope to add a page adapter or something similar in the future so when I click one of the images, it can show all three of them while swiping.

This is what I have in the activity that will have the fullscreen image when clicked:

package com.wlodsgn.bunbunup;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.WebView;

public class JnsDetailsFSActivity {

    protected String mImage;

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

        Intent intent = getIntent();
        Uri blogUri = intent.getData();
        mImage = blogUri.toString();

        JnsDetailsFSActivity jnsDetailsFSActivity = (JnsDetailsFSActivity) findViewById(R.id.thumbnailfs);
        jnsDetailsFSActivity.loadImage(mImage);
    }

}

Once again appreciate your time since I know you got a lot of work (like I do) so take your time in answering.

Cheers!

Harry James
Harry James
14,780 Points

No problem! The link to Google Drive that you sent me is set as being shared with specific people - if you could update the file to Anyone with the link then I'll download it and take a look tomorrow :)

Done! By the way, I created an account through GitHub last night so if you find it more easier to use it this way, then you are more than welcome :D

Harry James
Harry James
14,780 Points

Thanks!

I've gone ahead and created a Pull Request on your GitHub repository. Please review it and merge it into your branch if you're happy with it :)

Going to check it out and i'll let you know...

Thanks!