>Search/Filter MySQL >>Show In RecyclerView >> AsyncTask" />

Android MySQL RecyclerView – ServerSide Search/Filter

Android MySQL RecyclerView – ServerSide Search/Filter







This is an Android MySQL Search tutorial.

Introduction

  The world we live in is indeed large.The data we have is in astonishing quantity.Even programming,atleast in most cases involve manipulating or reading some data.This tutorial is no exception.Our aim is to see how to filter data from our MySQL database.Then we show our results in Realtime. We are performing a server-side search.Generally speaking,this is much faster than filtering at the client.Its faster than say,downloading your data to the device,then filling some sort of arraylist.Then filtering the arraylist.What if am having 100,10000,1 million records etc.You get the point. You'll hog the users bandwidth.And it takes time.Writing optimized java code to search can be tricky itself.Now we can save ourselves some trouble.Perform the search on the big beefy servers.Then download results.SQL is normally optimized for search/select performance.And we trust it better than ourselves. Anyway we use java.net.HttpURLConnection class,a subclass of java.net.URLConnection.

HttpURLConnection

  • Basically,its a URLConnection for the web.HTTP,remember.
  • Its used to send and receive data over the web.Clients to server and vice versa.
  • Input and Output like we do in this tutorial.Using POST request method.We make a HTTP POST request.
  • HTTP POST is supports both input and output of data.And basically that's what we need here as we are searching.
  • While searching,you send a query via outputstream,then receive an inputstream through which you read query results.
  • HttpURLConnection is the default networking class in android.ApacheHttpClient is dead n gone.

If you prefer video tutorial,please one is below. Video Otherwise we continue

Sending Data

  • First the HttpUrlConnetions’s setDoOutput(true) to allow connection.
  • HTTP POST allows sending data.

Receiving Response

  • First the HttpUrlConnetions’s setDoInput(true) to allow connection.
  • HTTP POST allows receiving data.

The Main Points

This android php mysql save save tutorial.We are using HttpURLConnection to make a HTTP POST request.

Section 1 : Our Connector Class

  • Has a static connect method that takes a URL Address string and returns a HttpURLConnection object.
  • Simply establishes connection to our server.
  • We set connction properties like Request method which is "POST",as we are making a HTTP POST request.
package com.tutorials.hp.recyclermysqlserver_sidesearch.MySQL;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
 * Created by Oclemmy on 4/2/2016 for ProgrammingWizards Channel.
 */
public class Connector {
    public static HttpURLConnection connect(String urlAddress)
    {
        try {
            URL url=new URL(urlAddress);
            HttpURLConnection con= (HttpURLConnection) url.openConnection();
            //SET PROPERTIES
            con.setRequestMethod("POST");
            con.setConnectTimeout(20000);
            con.setReadTimeout(20000);
            con.setDoInput(true);
            con.setDoOutput(true);
            //RETURN
            return con;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Section 2 : Our DataPackager Class

  • Basically,we package our data here for sending.
  • Obviously in this case our data is our query string
  • First we add them to a JSON Object.
  • Then we encode them into UTF-8 format using URLEncorder class.
  • Then we return it as a string ready to be written over the network.
package com.tutorials.hp.recyclermysqlserver_sidesearch.MySQL;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
/**
 * Created by Oclemmy on 4/2/2016 for ProgrammingWizards Channel.
 */
public class DataPackager {
    String query;
    public DataPackager(String query) {
        this.query = query;
    }
    public String packData()
    {
        JSONObject jo=new JSONObject();
        StringBuffer queryString=new StringBuffer();
        try {
            jo.put("Query",query);
            Boolean firstValue=true;
            Iterator it=jo.keys();
            do{
                String key=it.next().toString();
                String value=jo.get(key).toString();
                if(firstValue)
                {
                    firstValue=false;
                }else {
                    queryString.append("&");
                }
                queryString.append(URLEncoder.encode(key,"UTF-8"));
                queryString.append("=");
                queryString.append(URLEncoder.encode(value,"UTF-8"));
            }while (it.hasNext());
            return queryString.toString();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Section 3 : Our SenderReceiver Class

  • Yes,its our SenderReceiver class.To send us our query.To receive a response.
  • We send and receive our data in a background thread using AsyncTask,the super class of this SenderReceiver class.
  • While sending query or receiving results in background,we show our Progressdialog,starting it in onPreExcecute() and dismissing immediately onPostExecute() is called.
  • We establish an outputStream,write to it using OutputStreamWriter().
  • Thats how we send.
  • The OutputStreamWriter() instance,we pass to BufferedWriter() instance.
  • The bufferedWriter() instance writes our data.
  • We then read the server response using bufferedreader instance.
package com.tutorials.hp.recyclermysqlserver_sidesearch.MySQL;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
/**
 * Created by Oclemmy on 4/2/2016 for ProgrammingWizards Channel.
 */
public class SenderReceiver extends AsyncTask<Void,Void,String> {
    Context c;
    String query;
    ProgressDialog pd;
    String urlAddress;
    RecyclerView rv;
    ImageView noDataImg,noNetworkImg;
    public SenderReceiver(Context c, String query, String urlAddress, RecyclerView rv,ImageView...imageViews) {
        this.c = c;
        this.query = query;
        this.urlAddress = urlAddress;
        this.rv = rv;
        this.noDataImg=imageViews[0];
        this.noNetworkImg=imageViews[1];
    }
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pd=new ProgressDialog(c);
        pd.setTitle("Search");
        pd.setMessage("Searching...Please wait");
        pd.show();
    }
    @Override
    protected String doInBackground(Void... params) {
        return this.sendAndReceive();
    }
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        pd.dismiss();
        rv.setAdapter(null);
        if(result != null)
        {
            if(! result.contains("null"))
            {
                Parser p=new Parser(c,result,rv);
                p.execute();
                noNetworkImg.setVisibility(View.INVISIBLE);
                noDataImg.setVisibility(View.INVISIBLE);
            }else {
                noNetworkImg.setVisibility(View.INVISIBLE);
                noDataImg.setVisibility(View.VISIBLE);
            }
        }else {
            noNetworkImg.setVisibility(View.VISIBLE);
            noDataImg.setVisibility(View.INVISIBLE);
        }
    }
    private String sendAndReceive()
    {
        HttpURLConnection con=Connector.connect(urlAddress);
        if(con==null)
        {
            return null;
        }
        try
        {
            OutputStream os=con.getOutputStream();
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));
            bw.write(new DataPackager(query).packData());
            bw.flush();
            //RELEASE RES
            bw.close();
            os.close();
            //RESPONSE ???
            int responseCode=con.getResponseCode();
            StringBuffer response=new StringBuffer();
            if(responseCode==con.HTTP_OK)
            {
                InputStream is=con.getInputStream();
                BufferedReader br=new BufferedReader(new InputStreamReader(is));
                String line;
                if(br != null)
                {
                    while ((line=br.readLine()) != null)
                    {
                        response.append(line+"n");
                    }
                }else {
                    return null;
                }
                br.close();
                is.close();
                return response.toString();
            }else
            {
                return String.valueOf(responseCode);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Section 4 : Our Parser

  • Well we shall receive a JSON string
  • And it needs to be parsed.So we parse it here.
  • This may be time consuming hence blocking,depending on your data size.
  • So we do it in background thread.Once more using AsyncTask.
  • We don't use any thirdparty library in this tutorial.Not even when parsing.
  • JSONObject and JSONArray are sufficient for us.So we use them.
  • Thereafter,we fill an arraylist.And pass it to our MyAdapter class.
  • So that it can be bound to RecyclerView.
package com.tutorials.hp.recyclermysqlserver_sidesearch.MySQL;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;
import com.tutorials.hp.recyclermysqlserver_sidesearch.Recycler.MyAdapter;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
/**
 * Created by Oclemmy on 4/2/2016 for ProgrammingWizards Channel.
 */
public class Parser extends AsyncTask<Void,Void,Integer> {
    String data;
    RecyclerView rv;
    Context c;
    ArrayList<String> names=new ArrayList<>();
    public Parser(Context c, String data, RecyclerView rv) {
        this.c = c;
        this.data = data;
        this.rv = rv;
    }
    @Override
    protected Integer doInBackground(Void... params) {
        return this.parse();
    }
    @Override
    protected void onPostExecute(Integer integer) {
        super.onPostExecute(integer);
        if(integer==1)
        {
            rv.setAdapter(new MyAdapter(c,names));
        }else {
            Toast.makeText(c,"Unable to parse",Toast.LENGTH_SHORT).show();
        }
    }
    private int parse()
    {
        try {
            JSONArray ja=new JSONArray(data);
            JSONObject jo=null;
            names.clear();
            for(int i=0;i<ja.length();i++)
            {
                jo=ja.getJSONObject(i);
                String name=jo.getString("Name");
                names.add(name);
            }
            return 1;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return 0;
    }
}

Our Recycler Package

This is the package where we deal with RecyclerView stuff.

Section 5 : Our MyHolder

  • Our ViewHolder class
  • Derives from RecyclerView.ViewHolder
  • We only need one TextView,so this is the only view we shall be holding.
package com.tutorials.hp.recyclermysqlserver_sidesearch.Recycler;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import com.tutorials.hp.recyclermysqlserver_sidesearch.R;
/**
 * Created by Oclemmy on 4/2/2016 for ProgrammingWizards Channel.
 */
public class MyHolder  extends RecyclerView.ViewHolder {
    TextView nameTxt;
    public MyHolder(View itemView) {
        super(itemView);
        nameTxt= (TextView) itemView.findViewById(R.id.nameTxt);
    }
}

Section 6 : Our MyAdapter

  • Where we bind our views to our dataset.
  • We receive a Context object as well as an arraylist.The latter acts as our dataset.
  • So we first inflate our model layout using LayoutInflater class.
package com.tutorials.hp.recyclermysqlserver_sidesearch.Recycler;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.tutorials.hp.recyclermysqlserver_sidesearch.R;
import java.util.ArrayList;
/**
 * Created by Oclemmy on 4/2/2016 for ProgrammingWizards Channel.
 */
public class MyAdapter extends RecyclerView.Adapter<MyHolder> {
    Context c;
    ArrayList<String> names;
    public MyAdapter(Context c, ArrayList<String> names) {
        this.c = c;
        this.names = names;
    }
    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.model,parent,false);
        MyHolder holder=new MyHolder(v);
        return holder;
    }
    @Override
    public void onBindViewHolder(MyHolder holder, int position) {
        holder.nameTxt.setText(names.get(position));
    }
    @Override
    public int getItemCount() {
        return names.size();
    }
}

 MainActivity

Section 7 : Yes,Our MainActivity

  • Launcher activity.
  • Initialize UI like SearchView.
  • Handle SearchView's onQueryTextChangeListener();
  • Starts the sender Asynctask on button click,passing on context, urladdress, query string as well as recyclerview.
package com.tutorials.hp.recyclermysqlserver_sidesearch;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ImageView;
import com.tutorials.hp.recyclermysqlserver_sidesearch.MySQL.SenderReceiver;
public class MainActivity extends AppCompatActivity {
    RecyclerView rv;
    SearchView sv;
    ImageView noDataImg,noNetworkImg;
    String urlAddress="http://10.0.2.2/android/searcher.php";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        rv= (RecyclerView) findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));
        sv= (SearchView) findViewById(R.id.sv);
        noDataImg= (ImageView) findViewById(R.id.nodataImg);
        noNetworkImg= (ImageView) findViewById(R.id.noserver);
        sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                SenderReceiver sr=new SenderReceiver(MainActivity.this,query,urlAddress,rv,noDataImg,noNetworkImg);
                sr.execute();
                return false;
            }
            @Override
            public boolean onQueryTextChange(String query) {
                SenderReceiver sr=new SenderReceiver(MainActivity.this,query,urlAddress,rv,noDataImg,noNetworkImg);
                sr.execute();
                return false;
            }
        });
    }
}

Section 6 : Our Layouts

ContentMain.xml

  • Our nice layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.tutorials.hp.recyclermysqlserver_sidesearch.MainActivity"
    tools:showIn="@layout/activity_main">
 <android.support.v7.widget.SearchView
     android:id="@+id/sv"
     android:layout_width="match_parent"
     android:layout_height="50dp"
     app:defaultQueryHint="Search.."></android.support.v7.widget.SearchView>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_below="@+id/sv"
        android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
    <ImageView
        android:id="@+id/nodataImg"
        android:visibility="invisible"
        android:src="@drawable/nodata"
        android:layout_centerInParent="true"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <ImageView
        android:id="@+id/noserver"
        android:visibility="invisible"
        android:src="@drawable/noserver"
        android:layout_centerInParent="true"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

Section 7 : Reminders

  • Remember to add permission for internet in your manifest file.
  • Under your <application> tag
<uses-permission android:name="android.permission.INTERNET"/>

SOURCE CODE REFERENCE

FULL SOURCE CODE ==> Android RecyclerView MySQL Server Side Search/Filter

Cheers.



Leave a Reply

Your email address will not be published. Required fields are marked *

6 + 14 =

COMMENTS