2016-07-08 5 views
-2

私はリストビューから複数のアイテムを同時に削除する方法を実装しようとしています。私はよく働いているようで、私のアプリでそれを実装したオンラインチュートリアルを見つけました。ListView、nullポインタ例外から複数のアイテムを同時に削除する

チュートリアルのコードを使用すると、時間の1つを数秒間押すとListViewから複数の項目を選択して、削除ボタン付きの小さなメニューポップアップを作成できます。複数の項目を選択してから、削除を押してリストから削除することができます。

1つのことを除いて、テストしたときにすべてうまく動作しているようですが、1つ以上のアイテムを削除してから削除ボタンを押したときにnullポインタ例外が発生します。

ここで私は、次の午前のチュートリアルさ:Android Delete Multiple Selected Items in ListView Tutorial

ここでは、私の活動のコードです:ここで

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); 
     } 
    }); 
} 
} 

は私のListViewアダプタのコードです:ここで

public class ProduitsAdapter extends ArrayAdapter<StackProduits> { 

/** 
* fields 
*/ 
ImageLoader imageLoader; 
DisplayImageOptions options; 
List<StackProduits> productList; 
SparseBooleanArray mSelectedItemsIds; 

/** 
* Constructor. 
* 
* @param ctx 
* @param textViewResourceId 
* @param sites 
*/ 
public ProduitsAdapter(Context ctx, int textViewResourceId, List<StackProduits> sites) { 
    super(ctx, textViewResourceId, 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(); 
} 

/** 
* This method is responsible for creating row views out of a StackProduits object that can be put 
* into our ListView. 
* <p/> 
* (non-Javadoc) 
* 
* @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup) 
*/ 
@Override 
public View getView(int pos, View convertView, ViewGroup parent) { 
    RelativeLayout row = (RelativeLayout) convertView; 
    //Log.i("StackSites", "getView pos = " + pos); 
    if (null == row) { //No recycled View, we have to inflate one. 
     LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     row = (RelativeLayout) inflater.inflate(R.layout.item_row, null); 
    } 

    //Get our View References from item_row.xml 
    final ImageView iconImg = (ImageView) row.findViewById(R.id.iconImg); 
    TextView txtDesignation = (TextView) row.findViewById(R.id.nameTxt); 
    TextView txtAbout = (TextView) row.findViewById(R.id.aboutTxt); 
    TextView txtPrice = (TextView) row.findViewById(R.id.priceTxt); 
    TextView txtTotalArea = (TextView) row.findViewById(R.id.areaTxt); 
    final ProgressBar indicator = (ProgressBar) row.findViewById(R.id.progress); 

    //Initially we want the progress indicator visible, and the image invisible 
    indicator.setVisibility(View.VISIBLE); //show progress indicator 
    iconImg.setVisibility(View.INVISIBLE); //make image invisible 

    //Setup a listener we can use to switch from the loading indicator to the Image once it's ready 
    //changed ImageLoadingListener with SimpleImageLoadingListener 
    SimpleImageLoadingListener listener = new SimpleImageLoadingListener() { 
     @Override 
     public void onLoadingStarted(String arg0, View arg1) { 
      // TODO Auto-generated method stub 
     } 

     @Override 
     public void onLoadingCancelled(String arg0, View arg1) { 
      // TODO Auto-generated method stub 
     } 

     @Override 
     public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) { 
      indicator.setVisibility(View.INVISIBLE); 
      iconImg.setVisibility(View.VISIBLE); 
     } 

     @Override 
     public void onLoadingFailed(String arg0, View arg1, FailReason arg2) { 
      // TODO Auto-generated method stub 
     } 
    }; 

    //Load the image and use our options so caching is handled. 
    imageLoader.displayImage(getItem(pos).getImgUrl(), iconImg, options, listener); 

    //Set the relevant text in our TextViews (ListView) 
    txtDesignation.setText(getItem(pos).getDesignation()); 
    txtAbout.setText(getItem(pos).getAbout()); 
    txtPrice.setText(getItem(pos).getPrice()); 
    txtTotalArea.setText(getItem(pos).getArea()); 

    //return view that represents the full row 
    return row; 
} 

@Override 
public void remove(StackProduits object) { 
    productList.remove(object); 
    notifyDataSetChanged(); 
} 

public void removeSelection() { 
    mSelectedItemsIds = new SparseBooleanArray(); 
    notifyDataSetChanged(); 
} 

public void toggleSelection(int position) { 
    selectView(position, !mSelectedItemsIds.get(position)); 
} 

public void selectView(int position, boolean value) { 
    if (value) 
     mSelectedItemsIds.put(position, value); 
    else 
     mSelectedItemsIds.delete(position); 
    notifyDataSetChanged(); 
} 

public SparseBooleanArray getSelectedIds() { 
    return mSelectedItemsIds; 
} 
} 

は私のlogcatです:

07-08 11:51:28.106 23049-23049/com.example.adam_jaamour.cfimmobilier W/System: ClassLoader referenced unknown path: /data/app/com.example.adam_jaamour.cfimmobilier-1/lib/x86 
07-08 11:51:28.260 23049-23049/com.example.adam_jaamour.cfimmobilier W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable 
07-08 11:51:28.437 23049-23087/com.example.adam_jaamour.cfimmobilier D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true 

                         [ 07-08 11:51:28.443 23049:23049 D/   ] 
                        HostConnection::get() New Host Connection established 0xac33dfb0, tid 23049 


                        [ 07-08 11:51:28.484 23049:23087 D/   ] 
                        HostConnection::get() New Host Connection established 0xac33e100, tid 23087 
07-08 11:51:28.487 23049-23087/com.example.adam_jaamour.cfimmobilier I/OpenGLRenderer: Initialized EGL, version 1.4 
07-08 11:51:35.513 23049-23049/com.example.adam_jaamour.cfimmobilier E/libEGL: call to OpenGL ES API with no current context (logged once per thread) 
07-08 11:51:35.664 23049-23059/com.example.adam_jaamour.cfimmobilier I/art: Background sticky concurrent mark sweep GC freed 14665(1431KB) AllocSpace objects, 16(572KB) LOS objects, 16% free, 8MB/10MB, paused 9.804ms total 28.247ms 
07-08 11:51:35.735 23049-23087/com.example.adam_jaamour.cfimmobilier E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa9e5ee50 
07-08 11:51:38.871 23049-23049/com.example.adam_jaamour.cfimmobilier W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=316.2744, y[0]=1459.6875, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=13426969, downTime=13423514, deviceId=0, source=0x1002 } 
07-08 11:51:38.872 23049-23049/com.example.adam_jaamour.cfimmobilier W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=316.2744, y[0]=1459.6875, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=13426969, downTime=13423514, deviceId=0, source=0x1002 } 
07-08 11:51:38.872 23049-23049/com.example.adam_jaamour.cfimmobilier W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=316.2744, y[0]=1459.6875, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=13426969, downTime=13423514, deviceId=0, source=0x1002 } 
07-08 11:51:38.872 23049-23049/com.example.adam_jaamour.cfimmobilier W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=316.2744, y[0]=1459.6875, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=13426969, downTime=13423514, deviceId=0, source=0x1002 } 
07-08 11:51:42.399 23049-23049/com.example.adam_jaamour.cfimmobilier D/AndroidRuntime: Shutting down VM 


                        --------- beginning of crash 
07-08 11:51:42.401 23049-23049/com.example.adam_jaamour.cfimmobilier E/AndroidRuntime: FATAL EXCEPTION: main 
                        Process: com.example.adam_jaamour.cfimmobilier, PID: 23049 
                        java.lang.NullPointerException: Attempt to invoke interface method 'boolean java.util.List.remove(java.lang.Object)' on a null object reference 
                         at com.example.adam_jaamour.cfimmobilier.Produits.ProduitsAdapter.remove(ProduitsAdapter.java:144) 
                         at com.example.adam_jaamour.cfimmobilier.Favoris$2.onActionItemClicked(Favoris.java:138) 
                         at android.widget.AbsListView$MultiChoiceModeWrapper.onActionItemClicked(AbsListView.java:6242) 
                         at com.android.internal.policy.PhoneWindow$DecorView$ActionModeCallback2Wrapper.onActionItemClicked(PhoneWindow.java:3540) 
                         at android.support.v7.view.SupportActionModeWrapper$CallbackWrapper.onActionItemClicked(SupportActionModeWrapper.java:168) 
                         at android.support.v7.app.AppCompatDelegateImplV7$ActionModeCallbackWrapperV7.onActionItemClicked(AppCompatDelegateImplV7.java:1750) 
                         at android.support.v7.app.AppCompatDelegateImplV7$ActionModeCallbackWrapperV7.onActionItemClicked(AppCompatDelegateImplV7.java:1750) 
                         at android.support.v7.view.StandaloneActionMode.onMenuItemSelected(StandaloneActionMode.java:136) 
                         at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811) 
                         at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152) 
                         at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958) 
                         at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:948) 
                         at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:618) 
                         at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:139) 
                         at android.view.View.performClick(View.java:5198) 
                         at android.view.View$PerformClick.run(View.java:21147) 
                         at android.os.Handler.handleCallback(Handler.java:739) 
                         at android.os.Handler.dispatchMessage(Handler.java:95) 
                         at android.os.Looper.loop(Looper.java:148) 
                         at android.app.ActivityThread.main(ActivityThread.java:5417) 
                         at java.lang.reflect.Method.invoke(Native Method) 
                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

とにかく可能な限り手助けができれば、それは非常に気楽になるでしょう。私は数時間このことに執着しており、間違いを見つけることはできません。私はどこでもチェックし、なぜnullポインタの例外が出てくるのか分かりません!

編集:質問を重複としてフラグを立てたユーザーの場合、nullポインタ例外を解決する方法を知っています。ここで問題の原因は何かを見つけることでした。

+0

[NullPointerExceptionがある、と私はそれをどのように修正すればよいか?](http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-の可能性のある重複i-fix-it) –

答えて

1

ProduitsAdapterクラスにあなたがproductList変数を初期化していないので、あなたは、NullPointerExceptionが得られます。

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(); 
} 

あなたがStackProduitsのリストを重複しないように私は、第二の溶液を好みます。

+0

私はこれを見ていないと信じられません。 2つのソリューションも提供してくれてありがとう。どちらが最善であるかを述べる(私はあなたに同意する。リストは今複製されていないので、2番目の方が良い)。再度、感謝します! –

1

このコードでは、productListを初期化していないため、nullPointerを取得します。

はコンストラクタであるべき:

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(); 
} 
1

は、あなたが削除している項目をコメントした領域上ご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; 
      } 
     } 
関連する問題