简体   繁体   中英

How to add an onclick to every button in a listview, populated with a custom arrayadapter, that deletes that item from the array and updates it?

I have only just started learning Android, so I apologize if I don't explain what I'm trying to do very well.

So in my presetList activity, I have an arraylist of Preset objects, and I am populating that arraylist with values from an sqlite database, which is created and defined within it's corresponding DBHelper. I have a presetAdapter that is using a custom view (a textView and an imageButton). I'm setting the imageButtons to be delete icons, that when clicked on, delete the corresponding textview from the database, repopulates the arraylist with the updated values, and then updates itself, in order to show the removal of the value.

I am able to properly delete the value from the database, and in order to repopulate and refresh the arraylist and the presetAdapter, I created a method within presetList called refreshList(). This method should handle that functionality, but when I call it, it throws a NullPointerException. More specifically, it crashes when I try to open a cursor to read the values from my database:

The error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.dmapp, PID: 5697
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
        at android.content.ContextWrapper.getDatabasePath(ContextWrapper.java:327)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:352)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:322)
        at com.example.dmapp.presetsDBHelper.getSpecificPresets(presetsDBHelper.java:93)
        at com.example.dmapp.PresetList.refreshList(PresetList.java:77)
        at com.example.dmapp.PresetAdapter$2.onClick(PresetAdapter.java:72)

Here is PresetList:

public class PresetList extends AppCompatActivity {

    MyRecyclerViewAdapter adapter;
    private PresetAdapter presetAdapter;
    private ArrayList<Preset> presetList = new ArrayList<>();
    String TAG = "PresetList";
    private String passedPresetVariable;
    private presetsDBHelper mPresetsDBHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.preset_list);
        setPassedPresetVariable(this.getIntent().getStringExtra("presetVariable"));
        Log.d(TAG, "onCreate: Passed Preset variable is " + getPassedPresetVariable());


        // data to populate the RecyclerView with

        mPresetsDBHelper = new presetsDBHelper(this);
        DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
        int deviceHeight = (displayMetrics.heightPixels);

        Button addEntry = findViewById(R.id.addEntry);
        ListView presetListView = findViewById(R.id.presetListView);

        ViewGroup.LayoutParams params = presetListView.getLayoutParams();
        params.height = (int)(deviceHeight * .80);
        presetListView.setLayoutParams(params);

        // set up the RecyclerView with data from the database
        //Log.d(TAG, "onCreate: Preset variable is " + getIntent().getStringExtra("presetVariable"));
        Cursor presets = mPresetsDBHelper.getSpecificPresets(getIntent().getStringExtra("presetVariable"));
        try {
            if (presets.moveToNext()) {
                do {
                    presetList.add(new Preset(presets.getString(2)));
                } while (presets.moveToNext());
            }
        } finally {
            presets.close();
        }

        presetAdapter = new PresetAdapter(this, presetList);
        presetListView.setAdapter(presetAdapter);

        /*
        addEntry.setOnClickListener(new View.OnClickListener() {
            // The code in this method will be executed when the numbers View is clicked on.
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(view.getContext(), CityInfo.class);
                startActivity(intent);
            }
        });
        */
    }

    public void refreshList(){
        mPresetsDBHelper = new presetsDBHelper(this);
        Log.d(TAG, "refreshList: Preset variable is " + getPassedPresetVariable());
        presetList.clear();
        Cursor presets = mPresetsDBHelper.getSpecificPresets("Environment"); //Didn't work with getPassedPresetVariable, attempted hardcoded value to test. Still not functional
        try {
            if (presets.moveToNext()) {
                do {
                    presetList.add(new Preset(presets.getString(2)));
                } while (presets.moveToNext());
            }
        } finally {
            presets.close();
        }
        presetAdapter.notifyDataSetChanged();
    }

    public void setPassedPresetVariable(String passedPresetVariable) {
        this.passedPresetVariable = passedPresetVariable;
    }

    public String getPassedPresetVariable() {
        return passedPresetVariable;
    }
}

And here is my adapter:

public class PresetAdapter extends ArrayAdapter<Preset> {

    private Context mContext;
    private List<Preset> presetList = new ArrayList<>();
    private PresetList presetListClass;
    String TAG = "PresetAdapter";

    public PresetAdapter(Context context, ArrayList<Preset> list) {
        super(context, 0 , list);
        mContext = context;
        presetList = list;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View listItem = convertView;
        if(listItem == null) {
            listItem = LayoutInflater.from(mContext).inflate(R.layout.preset_item, parent, false);
        }

        Preset currentPreset = presetList.get(position);
        final TextView name = listItem.findViewById(R.id.presetValue);
        ImageButton delete = listItem.findViewById(R.id.deleteIcon);

        name.setText(currentPreset.getValue());
        name.setTag(position);
        name.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                int position = (Integer) view.getTag();
                // Access the row position here to get the correct data item
                Preset preset = getItem(position);
                // Do what you want here...
                String presetValue = preset.getValue();
                Intent intent = new Intent(name.getContext(), CityInfo.class);
                intent.putExtra("presetValue", presetValue);
                mContext.startActivity(intent);
            }
        });

        delete.setTag(position);
        delete.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                int position = (Integer) view.getTag();
                // Access the row position here to get the correct data item
                Preset preset = getItem(position);
                // Do what you want here...
                String presetValue = preset.getValue();
                presetsDBHelper mPresetsDBHelper = new presetsDBHelper(name.getContext());
                mPresetsDBHelper.removeSpecificPreset(presetValue);
                presetListClass = new PresetList();
                presetListClass.refreshList();
            }
        });

        return listItem;
    }
}

I assume there is an easier way of going about this that I'm missing, or there is some easier solution. If anyone could give me some insight, it'd be greatly appreciated!

Sorry if my question seems stupid but this was a common mistake in my class when i got started so I ask: Did you know your cursor start at 0? So 2 is actually the 3rd field? Cursors are working like array indexes. Maybe it's obvious for you then I apologize.but half my class mates faces thé prob because of that.

And I'm not sure if extends ArrayAdapter<> should have a type specified? I'm new too, so I don't know, but When I used an adapter I did not specify and it was working

So this was much, much easier than I was making this out to be. I was already passing the arrayList into the arrayAdapter, where I was defining the onClick methods. All I needed to do was migrate the code from the refreshList() function over inside of the onClick in the arrayAdapter and notifyDataSetChanged();

The onClick method in my arrayAdapter now looks like this:

delete.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                int position = (Integer) view.getTag();
                // Access the row position here to get the correct data item
                Preset preset = getItem(position);
                // Do what you want here...
                String presetValue = preset.getValue();
                presetsDBHelper mPresetsDBHelper = new presetsDBHelper(name.getContext());
                mPresetsDBHelper.removeSpecificPreset(presetValue);

                presetList.clear();
                Cursor presets = mPresetsDBHelper.getSpecificPresets("Environment"); //Didn't work with getPassedPresetVariable, attempted hardcoded value to test. Still not functional
                try {
                    if (presets.moveToNext()) {
                        do {
                            presetList.add(new Preset(presets.getString(2)));
                        } while (presets.moveToNext());
                    }
                } finally {
                    presets.close();
                }
                notifyDataSetChanged();

            }
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM