尝试在listview上实现搜索的Nullpointerexception [重复]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尝试在listview上实现搜索的Nullpointerexception [重复]相关的知识,希望对你有一定的参考价值。
这个问题在这里已有答案:
我使用AsyncTask创建了一个SQL数据库,该数据库接收一个活动中的输入并将其显示在另一个活动中。现在我想学习如何使用searchview在listview中搜索数据库。
我有一个绑定到listview的适配器类。在其中有一个过滤功能,用于过滤搜索视图,这是我认为错误源自的地方;因为错误发生在adapter.filter(s);.
我的错误:
7167-7167/com.example.andrewg.sqltutorial E/androidRuntime: FATAL EXCEPTION:
main
Process: com.example.andrewg.sqltutorial, PID: 7167
java.lang.NullPointerException: Attempt to invoke virtual method 'void
com.example.andrewg.sqltutorial.ProductAdapter.filter(java.lang.String)' on a
null object reference
at
com.example.andrewg.sqltutorial.DisplayProduct$1.onQueryTextChange
(DisplayProduct.java:47)
at android.widget.SearchView.onTextChanged(SearchView.java:1250)
at android.widget.SearchView.access$2100(SearchView.java:98)
at android.widget.SearchView$10.onTextChanged(SearchView.java:1776)
at android.widget.TextView.sendOnTextChanged(TextView.java:9754)
at android.widget.TextView.handleTextChanged(TextView.java:9851)
at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:12512)
at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:1263)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:575)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:506)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:36)
at android.view.inputmethod.BaseInputConnection.replaceText(BaseInputConnection.java:843)
at android.view.inputmethod.BaseInputConnection.setComposingText(BaseInputConnection.java:616)
at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:396)
at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:85)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6649)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:826)
display database.Java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.SearchView;
public class DisplayProduct extends AppCompatActivity {
ListView listView;
ProductAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.display_product_layout);
listView = findViewById(R.id.Display_listview);
BackgroundTask backgroundTask = new BackgroundTask(this);
backgroundTask.execute("get_info");
//-----------------------------EDIT--------------------------------
adapter = new ProductAdapter(this, R.layout.display_product_row);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) myActionMenuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
return false;
}
@Override
public boolean onQueryTextChange(String s) {
if(TextUtils.isEmpty(s)){
adapter.filter("");
listView.clearTextFilter();
}
else{
adapter.filter(s);
}
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.action_settings){
//do your functionality here
return true;
}
return super.onOptionsItemSelected(item);
}
}
product adapter.Java
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class ProductAdapter extends ArrayAdapter {
List list = new ArrayList();
//Menu Search
Context context;
ArrayList<Product> productArrayList = new ArrayList<>();
public ProductAdapter(@NonNull Context context, int resource) {
super(context, resource);
this.context = context;
this.productArrayList.addAll(list);
}
public void addList(ArrayList<Product> Oldarraylist){
this.productArrayList = Oldarraylist;
}
public void add(Product object) {
list.add(object);
super.add(object);
}
@Override
public int getCount() {
return list.size();
}
@Nullable
@Override
public Object getItem(int position) {
return list.get(position);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//Referencing each row as a View, which is an object
View row = convertView;
ProductHolder productHolder;
if(row == null){
//There is no view at this position, so we are creating a new one
//In this case we are inflating an XML layout
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.display_product_row, parent, false);
//Locate the views in row.xml
productHolder = new ProductHolder();
productHolder.id = row.findViewById(R.id.ID);
productHolder.name = row.findViewById(R.id.NAME);
productHolder.price = row.findViewById(R.id.PRICE);
productHolder.quantity = row.findViewById(R.id.QUANTITY);
/*setTag is very useful for custom ArrayAdapter using. It is some kind of optimization.
There setTag used as reference to object that references on some parts of layout
(that displaying in ListView) instead of findViewById.
*/
row.setTag(productHolder);
}
else{
//We are recycling a view that already exists
productHolder = (ProductHolder) row.getTag();
}
//Once we have a reference to the View we are returning, we set its values
//Setting results into textviews
Product product = (Product) getItem(position);
productHolder.id.setText(product.getID().toString());
productHolder.name.setText(product.getName().toString());
productHolder.price.setText(Integer.toString(product.getPrice()));
productHolder.quantity.setText(Integer.toString(product.getQuantity()));
//Menu
//Listview item clicks
row.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
return row;
}
//Menu
public void filter(String charText){
charText = charText.toLowerCase(Locale.getDefault());
list.clear();
if(charText.length() == 0){
list.addAll(productArrayList);
}
else{
for (Product product : productArrayList){
if(product.getName().toLowerCase(Locale.getDefault()).contains(charText)){
list.add(product);
}
}
}
notifyDataSetChanged();
}
static class ProductHolder{
TextView id, name, price, quantity;
}
}
我的AsyncTask线程中的相关代码
public class BackgroundTask extends AsyncTask<String,Product,String> {
Context context;
ProductAdapter productAdapter;
Activity activity;
ListView listView;
ArrayList<Product> arrayList = new ArrayList<>();
@Override
protected String doInBackground(String... params) {
listView = activity.findViewById(R.id.Display_listview);
SQLiteDatabase db = dbOperations.getReadableDatabase();
Cursor cursor = dbOperations.getInformation(db);
productAdapter = new ProductAdapter(context,
R.layout.display_product_row);
String id, name;
int price, quantity;
while(cursor.moveToNext()){
id =
cursor.getString(cursor.getColumnIndex(ProductContract.ProductEntry.ID));
name =
cursor.getString(cursor.getColumnIndex(ProductContract.ProductEntry.NAME));
price =
cursor.getInt(cursor.getColumnIndex(ProductContract.ProductEntry.PRICE));
quantity =
cursor.getInt(cursor.getColumnIndex(ProductContract.ProductEntry.QUANTITY));
Product product = new Product(id, name, price, quantity);
publishProgress(product);
}
return "get_info";
}
@Override
protected void onPostExecute(String s) {
//Bind the array adapter to the listview
listView.setAdapter(productAdapter);
productAdapter.addList(arrayList);
@Override
protected void onProgressUpdate(Product... values) {
productAdapter.add(values[0]);
arrayList.add(values[0]);
}
正如@Psypher指出的那样,您必须初始化ProductAdapter。但是,只是在AsyncTask中添加ProductAdapter adapter = new ProductAdapter()
将不起作用,因为它不是指您之前创建的同一个对象。
您需要先创建适配器,然后将其传递给AsyncTask(或使其成为静态)。
在调用product.filter()方法之前,尚未初始化ProductAdapter adapter;
。在onQueryTextChange中调用filter()时,适配器为null,因此出错。
如果ProductAdapter类被声明为静态,那么您现在拥有的代码可能有效,因为在调用类中的方法之前,您不必创建该类的新实例。
在调用filter方法之前,你需要有ProductAdapter adapter= new ProductAdapter()
。
在BackgroundTask
类中也是如此,在调用add或addList之前,您尚未对适配器变量进行初始化。
以上是关于尝试在listview上实现搜索的Nullpointerexception [重复]的主要内容,如果未能解决你的问题,请参考以下文章
我正在尝试通过 Google Places 在 Google Maps 上实现搜索。但是谷歌搜索出现了
onItemClickListener 在自定义 ListView 的其他行上实现
在 recyclerview kotlin 上实现搜索的问题