Search In Json Functionality

Issue

So, I get some data from a nutrition database and I want to add a search option. I’m new to Android Studio so some advice would help me.

This is the app:

enter image description here

This edittext should search in the database and show after the name of products. Is there an easier way to make this work?

This is the activity layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".NutritionDatabase">

    <EditText
        android:id="@+id/et_dataInput"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Search Database"
        android:inputType="textPersonName"
        android:layout_marginTop="-58dp"
        app:layout_constraintTop_toTopOf="@id/list"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="123dp"

        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteX="0dp" />

    <RelativeLayout
        android:id="@+id/relativeLayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="411dp"
            android:layout_height="wrap_content"
            android:background="#000000" />

        <ImageView
            android:id="@+id/back_to_home"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:minWidth="40dp"
            android:minHeight="45dp"
            android:paddingTop="15dp"
            android:src="@drawable/ic_back" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="16dp"
            android:text="Nutrition Database"
            android:textAlignment="center"
            android:textColor="#FFFFFFFF"
            android:textSize="20sp"
            android:textStyle="bold" />

    </RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
                                                                                           

This is the java class:

package com.example.myapplication;

import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;

public class NutritionDatabase extends AppCompatActivity {

    EditText et_dataInput;

    private String TAG = MainActivity.class.getSimpleName();
    private ListView lv;
    ArrayList<HashMap<String, String>> resultList;

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                break;
        }
        return true;
    }

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

        et_dataInput=findViewById(R.id.et_dataInput);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        if (getSupportActionBar() != null){
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setDisplayShowHomeEnabled(true);
        }
        resultList = new ArrayList<>();
        lv = (ListView) findViewById(R.id.list);
        new GetContacts().execute();
    }

    private class GetContacts extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Toast.makeText(NutritionDatabase.this,"Json Data is downloading",Toast.LENGTH_LONG).show();
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            HttpHandler sh = new HttpHandler();
            // Making a request to url and getting response
            String url = "https://wger.de/api/v2/ingredient/?language=2&limit=11865";
            String jsonStr = sh.makeServiceCall(url);

            Log.e(TAG, "Response from url: " + jsonStr);
            if (jsonStr != null) {
                try {
                    JSONObject jsonObj = new JSONObject(jsonStr);

                    // Getting JSON Array node
                    JSONArray results = jsonObj.getJSONArray("results");

                    // looping through All Contacts
                    for (int i = 0; i < results.length(); i++) {
                        JSONObject c = results.getJSONObject(i);
                        String name = c.getString("name");
                        String fat = c.getString("fat");
                        String protein = c.getString("protein");
                        String energy = c.getString("energy");
                        String carbohydrates = c.getString("carbohydrates");
                        String carbohydrates_sugar = c.getString("carbohydrates_sugar");
                        String fat_saturated = c.getString("fat_saturated");
                        String fibres = c.getString("fibres");
                        String sodium = c.getString("sodium");

                        // tmp hash map for single contact
                        HashMap<String, String> result = new HashMap<>();

                        // adding each child node to HashMap key => value
                        result.put("name","Name :"+ name);
                        result.put("fat","Fat :"+ fat);
                        result.put("protein","Protein :"+ protein);
                        result.put("energy","Energy :"+ energy);
                        result.put("carbohydrates","Carbohydrates :"+ carbohydrates);
                        result.put("carbohydrates_sugar","Carbohydrates from sugar :"+ carbohydrates_sugar);
                        result.put("fat_saturated","Saturated Fat:"+ fat_saturated);
                        result.put("fibres","Fibres :"+ fibres);
                        result.put("sodium","Sodium :"+ sodium);

                        // adding contact to contact list
                        resultList.add(result);
                    }
                } catch (final JSONException e) {
                    Log.e(TAG, "Json parsing error: " + e.getMessage());
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(),
                                    "Json parsing error: " + e.getMessage(),Toast.LENGTH_LONG).show();
                        }
                    });
                }
            } else {
                Log.e(TAG, "Couldn't get json from server.");
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(),
                                "Couldn't get json from server. Check LogCat for possible errors!",
                                Toast.LENGTH_LONG).show();
                    }
                });
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            ListAdapter adapter = new SimpleAdapter(NutritionDatabase.this, resultList,
                    R.layout.list_item_nutrition, new String[]{ "name","fat","energy","protein","carbohydrates","carbohydrates_sugar","fat_saturated","fibres","sodium"},
                    new int[]{R.id.name, R.id.fat,R.id.protein,R.id.energy,R.id.carbohydrates,R.id.carbohidrates_sugar,R.id.fat_saturated,R.id.fibres,R.id.sodium});
            lv.setAdapter(adapter);
        }
    }
} 

This is the list that I use :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="@dimen/activity_horizontal_margin">

    <TextView
        android:paddingTop="10dp"
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/colorAccent"
        android:text="Name:"/>

    <TextView
        android:id="@+id/energy"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#5d5d5d"
        android:textStyle="bold"
        android:paddingTop="10dp"
        android:text="Energy:"
        />

    <TextView
        android:id="@+id/protein"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#5d5d5d"
        android:textStyle="bold"
        android:text="Protein:"
        />

    <TextView
        android:id="@+id/carbohydrates"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#5d5d5d"
        android:textStyle="bold"
        android:text="Carbohydrates:"
        />

    <TextView
        android:id="@+id/carbohidrates_sugar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#5d5d5d"
        android:textStyle="bold"
        android:text="Carbohydrates from sugar:"
        />

    <TextView
        android:id="@+id/fat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#5d5d5d"
        android:textStyle="bold"
        android:text="Fat:"
        />

    <TextView
        android:id="@+id/fat_saturated"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#5d5d5d"
        android:textStyle="bold"
        android:text="Saturated Fat:"
        />

    <TextView
        android:id="@+id/fibres"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#5d5d5d"
        android:textStyle="bold"
        android:text="Fibres:"
        />

    <TextView
        android:id="@+id/sodium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#5d5d5d"
        android:textStyle="bold"
        android:text="Sodium:"
        />
</LinearLayout>

Solution

Implements NutritionDatabase activity with Filterable class and implements Filterable class method in your NutritionDatabase activity.

@Override
public Filter getFilter() {
    return myFilter;
}


Filter myFilter = new Filter() {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults filterResults = new FilterResults();
        ArrayList<String> tempList = new ArrayList<String>();
        //constraint is the result from text you want to filter against.
        //objects is your data set you will filter from
        if (constraint != null && your_list != null) {
            int length = your_list.size();
            int i = 0;
            while (i < length) {
                String item = your_list.get(i);
                //do whatever you wanna do here
                //adding result set output array
                tempList.add(item);
                i++;
            }

//following two lines is very important
            //as publish result can only take FilterResults objects
            filterResults.values = tempList;
            filterResults.count = tempList.size();
        }
        return filterResults;
    }

    @Override
    protected void publishResults(CharSequence contraint, FilterResults results) {
        your_list = (ArrayList<String>) results.values;
        if (results.count > 0) {
            your_adapter.notifyDataSetChanged();
        } else {
        }
    }
};
            


Implement your search edittext like

et_dataInput.addTextChangedListener(new TextWatcher() {

    @Override
    public void afterTextChanged(Editable arg0) {
        // TODO Auto-generated method stub
        String text = et_dataInput.getText().toString());
        your_adapter.getFilter().filter(text);
    }

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

    @Override
    public void onTextChanged(CharSequence arg0, int arg1, int arg2,
                              int arg3) {
        // TODO Auto-generated method stub
    }
});

use this code for search name from your list.

Answered By – Android

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published