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