Java 同时从ListView中删除多个项,空指针异常

Java 同时从ListView中删除多个项,空指针异常,java,android,listview,nullpointerexception,Java,Android,Listview,Nullpointerexception,我正在尝试实现一种同时从ListView中删除多个项目的方法。我找到了一个在线教程,它似乎运行良好,并在我的应用程序中实现了它 教程中的代码允许我们在按下其中一个按钮几秒钟后,从ListView中选择多个项目,并用delete按钮弹出一个小菜单。我们可以选择多个项目,然后按delete键将其从列表中删除 当我测试它时,一切似乎都正常工作,除了一件事,当我在选择一个或多个要删除的项目后按delete按钮时,我不断得到一个空指针异常 以下是我的教程: 这是我的活动代码: public class F

我正在尝试实现一种同时从ListView中删除多个项目的方法。我找到了一个在线教程,它似乎运行良好,并在我的应用程序中实现了它

教程中的代码允许我们在按下其中一个按钮几秒钟后,从ListView中选择多个项目,并用delete按钮弹出一个小菜单。我们可以选择多个项目,然后按delete键将其从列表中删除

当我测试它时,一切似乎都正常工作,除了一件事,当我在选择一个或多个要删除的项目后按delete按钮时,我不断得到一个空指针异常

以下是我的教程:

这是我的活动代码:

public class Favoris extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{

/**fields*/

private ListView produitFavorisListView;
private List<StackProduits> listProduits = new ArrayList<>();
private ProduitsAdapter adapterFavoris;
//SharedPreferences mPrefs;

/**
 * Method used to initialize the current activity, by inflating the activity's UI and interacting with
 * implemented widgets in the UI. Used to get and set the toolbar, (a floating action button), the
 * drawer which is used as the side menu, a navigation view.
 * @param savedInstanceState
 */
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_favoris);

    /**get ListView reference*/
    produitFavorisListView = (ListView) findViewById(R.id.favoritesList);

    /**getting back data from shared preferences*/
    final SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    final Gson gson = new Gson();

     //getting back favorites
    Set<String> myJson = mPrefs.getStringSet("listJson2", new HashSet<String>());
    //adapterFavoris = new ProduitsAdapter(getApplicationContext(), 0, listProduits);

    if (myJson.isEmpty() && listProduits.isEmpty()) {
        produitFavorisListView.setAdapter(null);
        //Log.i("INFO", "No items"); todo - log info: no items
    }
    else if (myJson.isEmpty() && listProduits != null) {
        adapterFavoris.notifyDataSetChanged();
        adapterFavoris = new ProduitsAdapter(getApplicationContext(), -1, listProduits);
        produitFavorisListView.setAdapter(adapterFavoris);
    }
    else{
        //for each where we get back values from sting set, then convert to product
        for (String id : myJson) {
            StackProduits savedProduct = gson.fromJson(id, StackProduits.class);
            //savedProduct.setIsAddedAsFav("1");
            listProduits.add(savedProduct);
        }
        adapterFavoris = new ProduitsAdapter(getApplicationContext(), -1, listProduits);
        produitFavorisListView.setAdapter(adapterFavoris);
    }

    //Set the click listener to launch the browser when a row is clicked.
    produitFavorisListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int pos, long id) {
            Intent intentProduitFavorisDetail = new Intent(Favoris.this, ProduitDetail.class);
            StackProduits ProduitFavoris = ProduitsXmlPullParser.getStackProduitFromFile(Favoris.this).get(pos);
            intentProduitFavorisDetail.putExtra("produit", ProduitFavoris);
            startActivity(intentProduitFavorisDetail);
        }
    });

    /**handle multiple item selection for deletion*/
    produitFavorisListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    produitFavorisListView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener(){

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.favorite_menu, menu);
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;   //done
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()){
                case R.id.delete_fav:
                    // Calls getSelectedIds method from ListViewAdapter Class
                    SparseBooleanArray selected = adapterFavoris.getSelectedIds();
                    // Captures all selected ids with a loop
                    for (int i = (selected.size() - 1); i >= 0; i--) {
                        if (selected.valueAt(i)) {
                            StackProduits selecteditem = adapterFavoris.getItem(selected.keyAt(i));
                            // Remove selected items following the ids
                            adapterFavoris.remove(selecteditem);
                            adapterFavoris.notifyDataSetChanged();
                            /*if(listProduits.isEmpty()){
                                if()
                            }*/
                        }
                    }
                    //save after modifications
                    String getProduct;
                    Set<String> stringListProductSave = new HashSet<>();
                    Gson gsonSave = new Gson();
                    for(int i=0; i<listProduits.size();i++){
                        getProduct = gsonSave.toJson(listProduits.get(i));
                        stringListProductSave.add(getProduct);
                    }
                    SharedPreferences.Editor prefsEditorSave = mPrefs.edit();
                    prefsEditorSave.putStringSet("listJson2", stringListProductSave);
                    prefsEditorSave.apply();
                    adapterFavoris.notifyDataSetChanged();
                    // Close CAB
                    mode.finish();
                    return true;
                default:
                    return false;
            }
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            adapterFavoris.removeSelection();
        }

        @Override
        public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
            // Capture total checked items
            final int checkedCount = produitFavorisListView.getCheckedItemCount();
            // Set the CAB title according to total checked items
            mode.setTitle(checkedCount + " Selected");
            // Calls toggleSelection method from ListViewAdapter Class
            adapterFavoris.toggleSelection(position);
        }
    });
}
}
如果你能在任何可能的情况下帮助我,我将不胜感激,我已经在这个问题上坚持了几个小时,找不到我的错误。我到处检查,不知道为什么会出现空指针异常


编辑:对于将问题标记为重复的用户,我确实知道如何解决空指针异常,这里的问题是找到导致它的原因。

在显示的代码中,您没有初始化productList,因此您得到了空指针

应在构造函数中:

public ProduitsAdapter(Context ctx, int textViewResourceId, List<StackProduits> sites) {
    super(ctx, textViewResourceId, sites);
    this.productList = sites;//////////here 
    //Setup the ImageLoader, we'll use this to display our images
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
    imageLoader = ImageLoader.getInstance();
    imageLoader.init(config);

    mSelectedItemsIds = new SparseBooleanArray();

    //Setup options for ImageLoader so it will handle caching for us.
    options = new DisplayImageOptions.Builder()
            .cacheInMemory()
            .cacheOnDisc()
            .build();
}
publicproduitsadapter(上下文ctx、int-textViewResourceId、列表站点){
超级(ctx、textViewResourceId、站点);
this.productList=sites;//此处
//设置ImageLoader,我们将使用它来显示图像
ImageLoaderConfiguration config=新建ImageLoaderConfiguration.Builder(ctx.build();
imageLoader=imageLoader.getInstance();
init(config);
mSelectedItemsIds=new SparseBooleanArray();
//ImageLoader的设置选项,以便它为我们处理缓存。
选项=新建DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.build();
}

您会得到NullPointerException,因为在ProduitsAdapter类中,您没有初始化productList变量。您可以在构造函数中初始化它,如下所示:

public ProduitsAdapter(Context ctx, int textViewResourceId, List<StackProduits> sites) {
super(ctx, textViewResourceId, sites);
productList = sites;

//Setup the ImageLoader, we'll use this to display our images
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
imageLoader = ImageLoader.getInstance();
imageLoader.init(config);

mSelectedItemsIds = new SparseBooleanArray();

//Setup options for ImageLoader so it will handle caching for us.
options = new DisplayImageOptions.Builder()
        .cacheInMemory()
        .cacheOnDisc()
        .build();
}

我更喜欢第二种解决方案,因为您不会复制StackProduit的列表。

您必须修改您的
onActionItemClicked()

查看要删除项目的注释区域,然后在每次不必执行此操作时更新
notifyDataSetChanged()
<代码>notifyDataSetChanged()仅一次

如我所评论的,评论下面的内容

而且我认为你必须改变你的for循环逻辑

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()){
                case R.id.delete_fav:
                    // Calls getSelectedIds method from ListViewAdapter Class
                    SparseBooleanArray selected = adapterFavoris.getSelectedIds();
                    // Captures all selected ids with a loop
                    for (int i = (selected.size() - 1); i >= 0; i--) {
                        if (selected.valueAt(i)) {
                            StackProduits selecteditem = adapterFavoris.getItem(selected.keyAt(i));
                            // Remove selected items following the ids
                            adapterFavoris.remove(selecteditem);

                            // Look here you remove all item item from list
                            // and then update notifyDataSetChanged() only once.                           
                            // Comment the below as i commented.
                            //adapterFavoris.notifyDataSetChanged();
                            /*if(listProduits.isEmpty()){
                                if()
                            }*/
                        }
                    }
                    //save after modifications
                    String getProduct;
                    Set<String> stringListProductSave = new HashSet<>();
                    Gson gsonSave = new Gson();
                    for(int i=0; i<listProduits.size();i++){
                        getProduct = gsonSave.toJson(listProduits.get(i));
                        stringListProductSave.add(getProduct);
                    }
                    SharedPreferences.Editor prefsEditorSave = mPrefs.edit();
                    prefsEditorSave.putStringSet("listJson2", stringListProductSave);
                    prefsEditorSave.apply();
                    adapterFavoris.notifyDataSetChanged();
                    // Close CAB
                    mode.finish();
                    return true;
                default:
                    return false;
            }
        }
@覆盖
公共布尔值onActionItemClicked(ActionMode模式,菜单项){
开关(item.getItemId()){
案例R.id.delete\U fav:
//从ListViewAdapter类调用GetSelectedDS方法
SparseBooleanArray selected=adapterFavoris.getSelectedId();
//使用循环捕获所有选定的ID
对于(int i=(selected.size()-1);i>=0;i--){
如果(选定。值位于(i)){
StackProduits selecteditem=adapterFavoris.getItem(selected.keyAt(i));
//删除ID后面的选定项目
适配器avoris.remove(选择编辑项);
//看这里,您将从列表中删除所有项目
//然后只更新一次notifyDataSetChanged()。
//如我所评论的,评论下面的内容。
//AdapterAvoris.notifyDataSetChanged();
/*if(listProduits.isEmpty()){
if()
}*/
}
}
//修改后保存
字符串产品;
Set stringListProductSave=newhashset();
Gson gsonSave=新的Gson();
对于(int i=0;i可能的重复项)
public ProduitsAdapter(Context ctx, int textViewResourceId, List<StackProduits> sites) {
super(ctx, textViewResourceId, sites);
productList = sites;

//Setup the ImageLoader, we'll use this to display our images
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
imageLoader = ImageLoader.getInstance();
imageLoader.init(config);

mSelectedItemsIds = new SparseBooleanArray();

//Setup options for ImageLoader so it will handle caching for us.
options = new DisplayImageOptions.Builder()
        .cacheInMemory()
        .cacheOnDisc()
        .build();
}
@Override
public void remove(StackProduits object) {
    super.remove(object);
    notifyDataSetChanged();
}
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()){
                case R.id.delete_fav:
                    // Calls getSelectedIds method from ListViewAdapter Class
                    SparseBooleanArray selected = adapterFavoris.getSelectedIds();
                    // Captures all selected ids with a loop
                    for (int i = (selected.size() - 1); i >= 0; i--) {
                        if (selected.valueAt(i)) {
                            StackProduits selecteditem = adapterFavoris.getItem(selected.keyAt(i));
                            // Remove selected items following the ids
                            adapterFavoris.remove(selecteditem);

                            // Look here you remove all item item from list
                            // and then update notifyDataSetChanged() only once.                           
                            // Comment the below as i commented.
                            //adapterFavoris.notifyDataSetChanged();
                            /*if(listProduits.isEmpty()){
                                if()
                            }*/
                        }
                    }
                    //save after modifications
                    String getProduct;
                    Set<String> stringListProductSave = new HashSet<>();
                    Gson gsonSave = new Gson();
                    for(int i=0; i<listProduits.size();i++){
                        getProduct = gsonSave.toJson(listProduits.get(i));
                        stringListProductSave.add(getProduct);
                    }
                    SharedPreferences.Editor prefsEditorSave = mPrefs.edit();
                    prefsEditorSave.putStringSet("listJson2", stringListProductSave);
                    prefsEditorSave.apply();
                    adapterFavoris.notifyDataSetChanged();
                    // Close CAB
                    mode.finish();
                    return true;
                default:
                    return false;
            }
        }