【问题标题】:SearchView on a JSON object retrieved from a server从服务器检索的 JSON 对象上的 SearchView
【发布时间】:2018-01-30 16:36:55
【问题描述】:

我已经处理了很长一段时间的应用程序,并且即将完成,但我需要最后一件事的帮助。

在这个应用程序中,用户可以输入name of clientmobile number of clientemail id of client,所有这些信息都会存储到在线数据库中。我有一个生成 JSON 文件的 PHP 文件,我的应用程序获取此 JSON 文件并将其内容设置为 listview。

这是我的 ListActivity,它有一个负责获取 JSON 文件的子类

public class ListActivity extends AppCompatActivity implements MaterialSearchView.OnQueryTextListener {

    String json_string;
    ListDataAdapter listDataAdapter;
    MaterialSearchView materialSearchView;
    DataProvider dataProvider;


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

        Toolbar searching = (Toolbar)findViewById(R.id.searchBar);
        setSupportActionBar(searching);
        getSupportActionBar().setTitle("Search");
        searching.setTitleTextColor(Color.parseColor("#ffffff"));

        materialSearchView = (MaterialSearchView)findViewById(R.id.search_view);

        final ListView listView = (ListView)  findViewById(R.id.list_view);
        listDataAdapter = new ListDataAdapter(getApplicationContext(),R.layout.row_layout);
        listView.setAdapter(listDataAdapter);
        Log.e("data=======", String.valueOf(listDataAdapter));

        new GetJSONfile().execute();

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                DataProvider dataProvider = (DataProvider) listDataAdapter.getItem(i);

                int idofclient = dataProvider.getId();
                String nameOfClient = dataProvider.getName();
                String mobileOfClient = dataProvider.getMob();
                String emailOfClient = dataProvider.getEmail();

                Intent calAct = new Intent(ListActivity.this, UserProfile.class);

                Bundle bundle = new Bundle();
                bundle.putInt("idofCC", (idofclient));
                bundle.putString("name", nameOfClient);
                bundle.putString("mobile", mobileOfClient);
                bundle.putString("email", emailOfClient);

                calAct.putExtras(bundle);
                startActivity(calAct);
            }
        });
    }

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

    @Override
    public boolean onQueryTextChange(String newText) {
        newText = newText.toLowerCase();
        ArrayList<DataProvider> dataProvider2 = new ArrayList<>();
        //dataProvider is your data which is provide to adapter in onPostExecute
        // so make it as global variable so you can access it
        for (DataProvider dp : listDataAdapter) {
            String name = dp.getName().toLowerCase();
            if (name.contains(newText)) {
                dataProvider2.add(dp);
            }
        }
        listDataAdapter.setFilter(dataProvider2);
        return true;
    }


    public class GetJSONfile extends AsyncTask<Void, Void, String> {
        String url_get;
        String jsondata;

        @Override
        protected void onPreExecute() {
            url_get = "http://10.0.2.2/webapp/jasonclient.php";
        }

        @Override
        protected String doInBackground(Void... voids) {
            try {
                URL url = new URL(url_get);
                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = httpURLConnection.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder stringBuilder = new StringBuilder();
                while((jsondata = bufferedReader.readLine())!=null){
                    stringBuilder.append(jsondata+"\n");
                }

                bufferedReader.close();
                inputStream.close();
                httpURLConnection.disconnect();
                Log.e("Tag =============", String.valueOf(stringBuilder));

                return stringBuilder.toString();

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(String jsonResult) {
            json_string = jsonResult;
            try{
                JSONObject jsonn = new JSONObject(json_string);
                JSONArray jsonArray = jsonn.getJSONArray("clientinfo");

                int count = 0;
                while(count<jsonArray.length()){
                    JSONObject JO = jsonArray.getJSONObject(count);
                    int id = JO.getInt("client_id");
                    String name = JO.getString("client_name");
                    String mobile = JO.getString("client_mobile");
                    String email = JO.getString("client_email");

                    Log.e("nameeeeeeeee==========",name);
                    Log.e("mobileeeeeee==========",mobile);
                    Log.e("emaillllllll==========",email);

                    dataProvider = new DataProvider(id,name,mobile,email);
                    Log.e("tag==================", String.valueOf(dataProvider));
                    listDataAdapter.add(dataProvider);
                    count++;
                }
            } catch (JSONException e) {

            }

        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu,menu);
        MenuItem menuItem = menu.findItem(R.id.ActionSearchView);
        materialSearchView.setMenuItem(menuItem);
        materialSearchView.setOnQueryTextListener(this);
        return true;
    }
}

以下是我的 ListDataAdapter 类

public class ListDataAdapter extends ArrayAdapter {

    List list = new ArrayList();

    public ListDataAdapter( Context context,  int resource) {
        super(context, resource);
    }

    static  class LayoutHandler {
        TextView ID,NAME,MOB,EMAIL;
    }

    @Override
    public void add(Object object) {
        super.add(object);
        list.add(object);
    }

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


    @Override
    public Object getItem(int position) {
        return list.get(position);
    }


    @Override
    public View getView(int position,  View convertView,  ViewGroup parent) {
        View row = convertView;
        LayoutHandler layoutHandler;

        if(row == null){
            LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = layoutInflater.inflate(R.layout.row_layout,parent,false);

            layoutHandler = new LayoutHandler();
            layoutHandler.NAME = (TextView) row.findViewById(R.id.text_user_name);

            row.setTag(layoutHandler);
        }else{
            layoutHandler = (LayoutHandler) row.getTag();
        }
        DataProvider dataProvider = (DataProvider) this.getItem(position);
        layoutHandler.NAME.setText(dataProvider.getName());

        return row;
    }

    public void setFilter(ArrayList<DataProvider> dataProvider2)
    {
        //dataProvider is your List which is used in constructor of adapter
        //class
        ArrayList<Object> dataProvider = new ArrayList<>();
        dataProvider.addAll(dataProvider2);
        notifyDataSetChanged();
    }
}

这是一个示例,说明当我开始在搜索栏中输入一些字符时,我希望应用执行什么操作。

这是一个漫长的项目,所以我没有包含我所有的源代码,但是如果你需要什么,请评论,我会添加它。

【问题讨论】:

  • 你可以通过两种方式来做这些事情,要么将所有列表数据存储在 sqlite 上,要么在 edittext 上搜索时从 sqlite 获取数据,或者通过每个字符的 json 请求? @TanavSharma
  • @AmrBerag 你怎么能说这是你提到的问题的重复?
  • @Abhishekkumar 你真的读了吗?
  • 您的适配器类是否扩展了BaseAdapter
  • @Yupi 不,它没有延伸到那个.. 它延伸到 ArrayAdapter

标签: php android json


【解决方案1】:

你需要先设置list.setadapter(null), 然后您可以在适配器或适配器数据集中填充值,最后调用 list.setadapter(adap),然后调用 adap.setNotifyDataChanged() 除了 "" 之外的每个字符更改都应该这样做,你应该很好

【讨论】:

  • 嘿伙计,我们可以私信吗,因为我觉得你可以帮助我。我想向您展示我的完整源代码,以便您可以更轻松地帮助我。让我知道,因为您的回答是有道理的,但我仍然不确定如何执行。我对应用程序开发仍然很陌生,并且正在尝试尽可能多地学习,所以让 mw 知道!再次感谢。
  • 您可以在我的 stackoverflow 个人资料中查看我的联系方式,谢谢
【解决方案2】:

您可以尝试以这种方式实现搜索。我没有测试它,我希望它会工作。在适配器类中创建一个方法:

 public void setFilter(ArrayList<Object> dataProvider2)
{
    //list is your List which is used in constructor of adapter
    //class
    list = new ArrayList<>();
    list.addAll(dataProvider2);
    notifyDataSetChanged();
}

然后在Activity 内部,我会假设你implements SearchView.OnQueryTextListener 和你override onQueryTextSubmitonQueryTextChange 内部onCreateOptionsMenu 你做了这样的事情:

 @Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.action_search, menu);

    final MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
    searchView = (SearchView) myActionMenuItem.getActionView();
    searchView.setOnQueryTextListener(this);
    return true;
}

然后在onQueryTextChange里面使用下一个代码:

@Override
public boolean onQueryTextChange(String newText) {

    newText = newText.toLowerCase();
    ArrayList<DataProvider> dataProvider2 = new ArrayList<>();
   //listDataAdapter is your data which is provide to adapter in onPostExecute
   // so make it as global variable so you can access it
    for (int i = 0; i < listDataAdapter.getCount(); i++) {
         DataProvider dp = listDataAdapter.getItem(i);
        String name = dp.getName().toLowerCase(); 
        if (name.contains(newText)) {
            dataProvider2.add(dp);
        }
    }
    listAdapter.setFilter(dataProvider2);
    return true;
}

确保您遵循传递正确的数据,因为如果您在不应该为空的地方提供空的List,它将不起作用,并且不会过滤数据。

【讨论】:

  • 我在将dataProvider 声明为全局变量时遇到了麻烦,目前它被声明为DataProvider dataProvider = new DataProvider(id,name,mobile,email);,我尝试过public static final ...... ,但它似乎不起作用。它给了我红线,并要求我删除所有这些。
  • 在类的顶部创建目标变量:DataProvider dataProvider; 然后在onPostExecute 中进行初始化:dataProvider = new DataProvider(id,name,mobile,email);
  • GetJSONfile 是单独的类还是在 Activity 类中的子类?
  • 我已经做到了,现在在onQueryTextSubmit 我尝试像sooo 一样拨打电话...for(DataProvider dp: GetJSONfile.dataProvider)... 这给了我一个错误并声明non static field cannot be referenced from a static context 我尝试拨打DataProvider 是静态的,但它仍然不起作用。 :(((((((((()))
  • GetJSONfile 在 Activity 内部,换句话说,它是 subclass
【解决方案3】:

您可以通过两种方式实现:

  1. 在每个键入的字符处调用 API。
  2. 将所有列表数据存储在 Sqlite 中,搜索时列表将来自本地数据库。

使用 RecyclerView 来实现:

参考:https://www.learn2crack.com/2017/03/searchview-with-recyclerview.html

在您的 Activity 类上执行以下代码:

  EditText editTextSearch;


 editTextSearch = (EditText) findViewById(R.id.searcheditTxtTI); 

 editTextSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                if(editTextSearch.getText().length()>=1){
                    adapter.getFilter().filter(editTextSearch.getText().toString());
                    recyclerView.setVisibility(View.VISIBLE);
                }else{
                    recyclerView.setVisibility(View.GONE);
                }




            }
        });

在你的适配器上做这样的代码:

 @Override
public Filter getFilter() {

    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {

            String charString = charSequence.toString();

            if (charString.isEmpty()) {

                mFilteredList = list;
            } else {

                ArrayList<LoadDataResult> filteredList = new ArrayList<>();

                for (LoadDataResult txt : list) {

                    if (txt.getName().toString().toLowerCase().contains(charString)|| txt.getUpc().toString().toLowerCase().contains(charString)) {

                        filteredList.add(txt);
                    }
                }

                mFilteredList = filteredList;
            }

            FilterResults filterResults = new FilterResults();
            filterResults.values = mFilteredList;
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            mFilteredList = (ArrayList<LoadDataResult>) filterResults.values;
            notifyDataSetChanged();
        }
    };
}

【讨论】:

  • 你也可以在listview中做同样的事情,但是如果你使用recyclerview的话,以后如果你想做更多的事情,你会很容易执行更多的操作。 @TanavSharma
  • 如果您遇到任何问题,请开始编码,我在这里为您提供帮助。 @TanavSharma
猜你喜欢
  • 2012-07-17
  • 2018-07-10
  • 1970-01-01
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
  • 2023-04-08
  • 2017-04-18
  • 1970-01-01
相关资源
最近更新 更多