1

I've been trying to implement a SearchView in my actionBar that filters a recyclerview that gets its data from an Async task for days now and I cant seem to get it to work.

On all the answers I've seen here gets The adapter for the recycler class is on the same class as the SearchView. but on my app the adapter is in the Async class while the Searchview is in a fragment. I made an Async class because I dont want my UI thread slowing down or crashing when my app is trying to load the items on the RecyclerView. Bellow are my codes, any help would be lovely.

and lastly for my fragment, I have a few codes so ill just cut most of them out and leave whats relevant to the question. Thanks.

for MyAsync.java

public class MyAsync extends AsyncTask<Void,RafTask,Void>{

private RecyclerView recyclerView;
private ProgressBar progressBar;
private Context context;
private static ClientRecycler recycler;
private SearchView searchView;
private ArrayList<RafTask> newLists = new ArrayList<>();
String am;
private static ArrayList<RafTask> raftask = new ArrayList<>();
private static final String TAG = "ListDataActivity";

public MyAsync(RecyclerView recyclerView, ProgressBar progressBar,Context context, ArrayList<RafTask> newList){

    this.recyclerView = recyclerView;
    this.progressBar = progressBar;
    this.context = context;
    this.newLists = newList;
}

@Override
protected void onPreExecute() {

    recycler = new ClientRecycler(raftask);
    recyclerView.setAdapter(recycler);
    progressBar.setVisibility(View.VISIBLE);
}


@Override
protected Void doInBackground(Void... voids) {


    MyHelper mHelper = new MyHelper(context,null,null,1);

    SQLiteDatabase database = mDatabaseHelper.getReadableDatabase();


    String Name;
    int  count = 0;
    Cursor c = mHelper.getRafData();



    while(c.moveToNext()){

        //Database codes
        publishProgress(new RafTask(Name,"","",String.valueOf(count),"",""));

    return null;
}

@Override
protected void onProgressUpdate(RafTask... value) {
    raftask.add(value[0]);
    recycler.notifyDataSetChanged();
}

@Override
protected void onPostExecute(Void aVoid) {

    progressBar.setVisibility(View.GONE);
    Log.d(TAG, "fragment text pass: " + am);
}
public static void setFilter(ArrayList<RafTask> newList){
   // newList = newLists;
    raftask = new ArrayList<>();
    raftask.addAll(newList);
    recycler.notifyDataSetChanged();
}
}

And for the Rafadapter.java

public class RafRecycler extends RecyclerView.Adapter<RafRecycler.MyViewHolder> {
private static ArrayList<RafTask> rafTasks = new ArrayList<>();



public RafRecycler(ArrayList<RafTask> rafTasks){
    this.rafasks = rafTasks;

}

@Override
public RafRecycler.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.raw_rafs,parent,false);
    return new RafRecycler.MyViewHolder(view);

}

@Override
public void onBindViewHolder(ClientRecycler.MyViewHolder holder, int position) {

    holder.name.setText(rafTasks.get(position).get_raftaskname());
    holder.id.setText(String.valueOf(rafTasks.get(position).get_raftaskid())+".");
    // holder.id.setText(String.valueOf("->"));


    holder.m = rafTasks.get(position).get_raftaskid();

}

@Override
public int getItemCount() {
    return clientTasks.size();
}

public static class MyViewHolder extends RecyclerView.ViewHolder{

    TextView id,name;
    String m;



    public MyViewHolder(View itemView) {
        super(itemView);
        id = itemView.findViewById(R.id.txt_id);
        name = itemView.findViewById(R.id.txt_name);
        m=itemView.toString();


        final MyDatabaseHelper mDatabaseHelper = new MyDatabaseHelper(itemView.getContext(),null,null,1);





        final boolean clicked = false;

        name.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String names = name.getText().toString();

                Cursor c = mHelper.getClientItemID(names);
                int itemID = -1;
                String email = "";
                String address = "";
                String shipaddress = "";
                String number = "";
                while (c.moveToNext()){

                    //Chech here for the codes to edit all plus numbers
                    //
                    //
                    itemID = c.getInt(0);
                    address =c.getString(4);
                    number =c.getString(2);
                    shipaddress =c.getString(5);
                    email =c.getString(3);
                }
                if(itemID >-1){
                    Log.d(TAG, "onItemClick: The id is: " + itemID);
                    Log.d(TAG, "onItemClick: The desc is: " + address);
                    Log.d(TAG, "onItemClick: The price is: " + shipaddress);
                    Intent editScreenIntent = new Intent(v.getContext(), EditClientActivity.class);
                    editScreenIntent.putExtra("id", itemID);
                    editScreenIntent.putExtra("name", names);
                    editScreenIntent.putExtra("number", number);
                    editScreenIntent.putExtra("address", address);
                    editScreenIntent.putExtra("email", email);
                    editScreenIntent.putExtra("shipaddress", shipaddress);
                    v.getContext().startActivity(editScreenIntent);
                    ((MainActivity) v.getContext()).overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left);
                }else{
                    Toast.makeText(v.getContext(),"No idd clicked", Toast.LENGTH_SHORT).show();
                }

            }

        });
    }
}

public void setFilter(ArrayList<ClientTask> newList){
    clientTasks = new ArrayList<>();
    clientTasks.addAll(newList);
    notifyDataSetChanged();
}
}

And lastly my fragment.java

public class ClientFragment extends Fragment implements SearchView.OnQueryTextListener {

private static final String TAG = "ListDataActivity";
MyDatabaseHelper mDatabaseHelper;
private ProgressBar progressBar;
private RecyclerView recyclerView;
public static SearchView searchView;
static String am;
private MenuItem menua;
public static ArrayList<ClientTask> newList;
RecyclerView.LayoutManager layoutManager;
public BackgroundAsync backgroundAsync;
private ArrayList<ClientTask> clienttask = new ArrayList<>();
ClientRecycler recycler;

private ListView mListView;

Button opencon;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

public ClientFragment() {
    // Required empty public constructor
}
public static ClientFragment newInstance(String param1, String param2) {
    ClientFragment fragment = new ClientFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onPrepareOptionsMenu(Menu menu){


    am="asdf";
    MenuItem menuItem = menu.findItem(R.id.mysearchbtn);
    SearchView searchView = (SearchView) menuItem.getActionView();
     searchView.setOnQueryTextListener(this);
    Log.d(TAG, "onCreateFragment ");
    super.onPrepareOptionsMenu(menu);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    if (getArguments() != null) {
        setRetainInstance(true);
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }

}




@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment

    View view = inflater.inflate(R.layout.fragment_client, container, false);

    progressBar = view.findViewById(R.id.progressbar);
    recyclerView = view.findViewById(R.id.recyclerView);
    layoutManager = new LinearLayoutManager(getActivity());
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setHasFixedSize(true);


    recycler = new ClientRecycler(clienttask);

    opencon = view.findViewById(R.id.opencon);
    opencon.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(getActivity(), AddClient.class);
            startActivity(intent);
        }
    });

    return view;
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
     //   Toast.makeText(context, " Off", Toast.LENGTH_SHORT).show();

    }
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

@Override
public boolean onQueryTextSubmit(String query) {
    return false;
}

@Override
public boolean onQueryTextChange(String newText) {
    newText = newText.toLowerCase();
    newList = new ArrayList<>();
        for (ClientTask clientTask : clienttask) {
            String name = clientTask.get_clienttaskname().toLowerCase();
            if (name.contains(newText)) {
                Log.d(TAG, "u get any: "+ name);
                newList.add(clientTask);
            }else{
                Log.d(TAG, "we aint got shit: "+ name);
            }

        }

        Log.d(TAG, "the usual fail ");
    recyclerView.setAdapter(recycler);
    return true;
}

void filter(String text){
    ArrayList<ClientTask> newList = new ArrayList();

      for (ClientTask c : clienttask) {
     //   String name = clientTask.get_clienttaskname().toLowerCase();
        if (c.get_clienttaskname().contains(text)) {
            newList.add(c);
        }

          Log.d(TAG, "the usual fail ");
          BackgroundAsync.setFilter(newList);
          recyclerView.setAdapter(recycler);
    }
}


public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}
@Override
public void onResume() {
    super.onResume();
    new BackgroundAsync(recyclerView,progressBar,getActivity(),newList).execute();
}


}

Some parts of my code may be quite unecessary to solve my problem, but I've tried so many fixes that didn't work and as a result, I have some weird looking implementations.Sorry for the trouble and again, thanks for thew help.

  • use [this](https://gist.github.com/Shywim/127f207e7248fe48400b) generic `Filterable` adapter as a base class and setup its `FilterQueryProvider` - filtering is done as usual: `adapter.getFilter().filter(....)` – pskink Dec 09 '17 at 19:25
  • you should consider writing a better code why `AsyncTask ` is holding the views? you should have an interface to communicate between your `AsyncTask ` and the views please check this answer https://stackoverflow.com/questions/9963691/android-asynctask-sending-callbacks-to-ui – tamtom Dec 09 '17 at 19:41
  • @pskink Thanks for the reply, I really appreciate it, but I'll basically changing my code and wont know what the problem is, and I also wouldn't get to know what I'm doing wrong. I'm new to Android development so I really want to Also learn so any explanation would be appreciated. – Ibrahim Usman Dec 09 '17 at 19:47
  • @tamtom My knowledge about Async task isn't that good so thats the way I know how to implement an Async task. I'll look into Interface and and see what I can do with it. Thanks for the help – Ibrahim Usman Dec 09 '17 at 19:49
  • @pskink Ok, I'll do that. but does that mean there's no fix for my code? – Ibrahim Usman Dec 09 '17 at 20:11
  • @pskink Link is not available. I cant access it yet – Ibrahim Usman Dec 09 '17 at 23:39
  • @pskink I finally got to see the codes. Thanks for the second link. I noticed that the code doesn't really solve my problem. What i need is a way to perform the filter (or search) on my Async class and Use the SearchView in the fragment just for collecting the text I'll be using to perform the filtering or search – Ibrahim Usman Dec 10 '17 at 19:55
  • yes, it solves: see `public Cursor runQuery(CharSequence constraint) {` method (line 14) - it is where filtering (or searching) is done - did you try to run those 28 lines of code? did you see how it works? – pskink Dec 10 '17 at 20:14
  • Ok. I'll work with the code and see how it functions and how to use it. But is there a way of doing it without completely changing the codes I used? if not, why? – Ibrahim Usman Dec 10 '17 at 22:18
  • @pskink thanks for the feedback. it helped me research a little bit better and see what I did wrong – Ibrahim Usman Dec 13 '17 at 00:09
  • I know but I want an async task so that the process is not done on my UI thread just in case my database ends up having a lot of data. I thought about using a Filter class but I felt this was a lot simpler since I basically added not up to 5 lines of code – Ibrahim Usman Dec 13 '17 at 10:18

1 Answers1

0

I managed to solve the problem by Moving the Async task class into the Fragment class So they share the same variables. I cleared all the input in the constructor so it became new BackgroundBsync().execute();. That solved it and I am now able to search all the data with a separate method i made in the Rafadapter class. the codes are below.

public void setFilter(ArrayList<ClientTask> newList){
        clientTasks = new ArrayList<>();
        clientTasks.addAll(newList);
        notifyDataSetChanged();
    }

so all i needed to add in my onQueryTextChange was to add a few lines of code

newText = newText.toLowerCase();
        ArrayList<ClientTask> newList = new ArrayList();

        for (ClientTask c : clienttask) {
               String name = c.get_clienttaskname().toLowerCase();
            if (name.contains(newText)) {
                newList.add(c);
            }

            Log.d(TAG, "the usual fail ");
        }
        recycler.setFilter(newList);
        return true;

And it solved my problem. Please note that RafAdapter is the same as ClientRecycler.