首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Nullpointerexception尝试在列表视图上实现搜索

Nullpointerexception尝试在列表视图上实现搜索
EN

Stack Overflow用户
提问于 2018-06-13 08:00:28
回答 2查看 103关注 0票数 1

我已经使用AsyncTask创建了一个SQL数据库,它接受一个活动中的输入,并在另一个活动中显示它们。现在我正在尝试学习如何使用searchview在listview中搜索数据库。

我有一个绑定到listview的适配器类。其中有一个过滤函数,用于过滤搜索视图,我认为这就是错误的来源;因为错误发生在adapter.filter(s);。

我的错误:

代码语言:javascript
复制
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)

DisplayDatabase.java

代码语言:javascript
复制
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);
}
}

ProductAdapter.java

代码语言:javascript
复制
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线程中的相关代码

代码语言:javascript
复制
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]);
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-13 09:18:46

正如@Psypher指出的那样,你必须初始化ProductAdapter。但是,仅仅在AsyncTask中添加ProductAdapter adapter = new ProductAdapter()是行不通的,因为它引用的对象与您之前创建的对象不同。

您需要首先创建适配器,然后将其传递给AsyncTask (或将其设为静态)。

票数 0
EN

Stack Overflow用户

发布于 2018-06-13 08:36:49

在调用product.filter()方法之前,您尚未初始化ProductAdapter adapter;。当您在onQueryTextChange中调用filter()时,适配器为空,因此出现错误。

如果ProductAdapter类被声明为静态,那么您现在拥有的代码可能已经可以工作了,因为在调用类中的方法之前,您必须创建该类的一个新实例。

在调用filter方法之前,您需要有ProductAdapter adapter= new ProductAdapter()

BackgroundTask类中也是如此,在调用add或addList之前,您尚未初始化适配器变量。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50827409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档