Страницы

Поиск по вопросам

суббота, 14 декабря 2019 г.

Логика приложения Андроид (RecyclerView)

#java #android #sqlite #recyclerview


Здравствуйте. Пожалуйста, помогите разобраться со следующим.

Есть БД, данные из БД выводятся на CardViewы, которые в свою очередь генерятся в
зависимости от кол-ва записей в БД.

На этих карточках выведены данные полученные из полей БД. И на этих же карточках
присутствует кнопка для удаления записи из БД (нажатие кнопки на карточке удаляет эту
карточку и ту строку, которая послужила источником данных для этой карточки). 

Суть в том, что я не понимаю, как реализовать эти кнопки...

Скриншот для наглядности:


Итак, теперь к моей реализации:

Для создания объекта Exercise я создал следующий класс:

package dailytoys.exreminder.DataClasses;


public class Exercise {

    public String name;
    public String muscleGroup;
    public int repeats;
    public int ID;

    public Exercise(String name, String muscleGroup, int repeats, int ID) {
        this.name = name;
        this.muscleGroup = muscleGroup;
        this.repeats = repeats;
        this.ID = ID;
    }
}


Вот DBHelper:

package dailytoys.exreminder.DataBaseEx;


import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {

    String name;

    public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
int version) {
        super(context, name, factory, version);
        this.name = name;
    }

    public DBHelper(Context context) {
        super(context, "exeDB", null, 1);
    }

    public int getRowsQuantity (String table) throws SQLException {
        String countQuery = "SELECT * FROM " + table;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
        int cnt = cursor.getCount();
        return cnt;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        System.out.println("-------- CREATING TABLES ----------");

        db.execSQL("CREATE TABLE EXERCISES (" +
                "ID INTEGER PRIMARY KEY AUTOINCREMENT," +
                "NAME TEXT," +
                "REPEATS INTEGER," +
                "MUSCLE_GROUP TEXT" + ");");

        ...

    }

    ...

}


Собственно, вот Активити, которое отображает карточки:

package dailytoys.exreminder;

import android.app.DialogFragment;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

import dailytoys.exreminder.DataBaseEx.DBHelper;
import dailytoys.exreminder.DataClasses.Exercise;
import dailytoys.exreminder.Dialogs.DialogNewExercise;


public class ExercisesActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;

    private RecyclerView.LayoutManager mLayoutManager;

    /* Данные для добавления на карточки */
    private List exercises;

    DBHelper dbHelper;

    RecyclerAdapter adapter;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exercises);
        ...

        /* Инициализация БД помощника для построения карточек */
        dbHelper = new DBHelper(this);

        /* Генерация карточек */
        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        initializeData();
        initializeAdapter();
...
    }

    private void initializeData () {

        int rows = dbHelper.getRowsQuantity("EXERCISES");
        exercises = new ArrayList<>();

        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor c = db.query("EXERCISES", null, null, null, null, null, null);

        int idColIndex = c.getColumnIndex("ID");
        int nameColIndex = c.getColumnIndex("NAME");
        int repeatsColIndex = c.getColumnIndex("REPEATS");
        int muscleGroupColIndex = c.getColumnIndex("MUSCLE_GROUP");


        // Цикл для чтения таблицы БД и записи данных в переменные
        for (int i = 0; i < rows; i ++) {
            // Дефолтные значения переменных
            String name = null, muscleGroup = null;
            int repeats = 0; int ID = 0;

            // Получение значений из БД
            if (c.moveToNext()) {
                name = c.getString(nameColIndex);
                muscleGroup = c.getString(muscleGroupColIndex);
                repeats = c.getInt(repeatsColIndex);
                ID = c.getInt(idColIndex);

                // добавление в List
                exercises.add(new Exercise(name, muscleGroup, repeats, ID));

            } else {
                // Do nothing
            }
        }
    }

    private void initializeAdapter(){
        adapter = new RecyclerAdapter((ArrayList)exercises);
        mRecyclerView.setAdapter(adapter);
    }

    public void reloadActivity() {
        Intent intent = getIntent();
        startActivity(intent);
    }



    ...


}


Карточки генерятся через класс, расширяемый от RecyclerView.Adapter :

package dailytoys.exreminder;


import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import dailytoys.exreminder.DataClasses.Exercise;

public class RecyclerAdapter extends RecyclerView.Adapter {

    private List exercises;
    ExerciseViewHolder vh;
    public ImageView mDeleteBtn;

    public class ExerciseViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView, mTextViewName, mTextViewMusckeGroup, mTextViewRepeats;

        public ExerciseViewHolder(View v) {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.tv_recycler_item);
            mTextViewName = (TextView) v.findViewById(R.id.exerciseNameEx);
            mTextViewMusckeGroup = (TextView) v.findViewById(R.id.tvMuscleGroup);
            mTextViewRepeats = (TextView) v.findViewById(R.id.tvRepeats);
            mDeleteBtn = (ImageView) v.findViewById(R.id.deleteBtnEx);
        }

    }

    public RecyclerAdapter(ArrayList exercises) {
        this.exercises = exercises;

    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }

    @Override
    public RecyclerAdapter.ExerciseViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item,
parent, false);

        vh = new ExerciseViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(ExerciseViewHolder holder, int position) {
        holder.mTextView.setText("ID: " + Integer.toString(exercises.get(position).ID));
        holder.mTextViewName.setText(exercises.get(position).name);
        holder.mTextViewMusckeGroup.setText(exercises.get(position).muscleGroup);
        holder.mTextViewRepeats.setText(Integer.toString(exercises.get(position).repeats));
        mDeleteBtn.setTag(exercises.get(position).ID);

    }

    public ImageView getImgView () {
        return mDeleteBtn;
    }

    @Override
    public int getItemCount() {
        return exercises.size();
    }

}


Ну, и на всякий случай, оставлю разметки карточки, и RecyclerView.

activity_exercises.xml :




    

        

    

    

    




content_exercises.xml :



    





recycler_item.xml :




    


        

            

                

                

            

            

                

                

                    

                    
                

                

                    

                    
                

            

            

                
            
        
    





Ну, и, собственно, для того, чтобы по клику на кнопку "удалить" (та которая ImageView
с изображением корзины) происходило удаление записи по её ID, я решил сетить ей ID.
То есть, вот так:

@Override
public void onBindViewHolder(ExerciseViewHolder holder, int position) {
    mDeleteBtn.setTag(exercises.get(position).ID);
}


Но проблема в том, что абсолютно всем экземплярам кнопке (на всех карточках) сетится
один и тот же ID (последняя запись в таблице).

И вопрос в том, как же мне сделать так, чтобы на каждой кнопке висел тег с правильной
айдишкой (которая соответствует информации на карточке).
    


Ответы

Ответ 1



Попробуйте так: public ExerciseViewHolder(View v) { super(v); mTextView = (TextView) v.findViewById(R.id.tv_recycler_item); mTextViewName = (TextView) v.findViewById(R.id.exerciseNameEx); mTextViewMusckeGroup = (TextView)v.findViewById(R.id.tvMuscleGroup); mTextViewRepeats = (TextView) v.findViewById(R.id.tvRepeats); mDeleteBtn = (ImageView) v.findViewById(R.id.deleteBtnEx); mDeleteBtn.setOnClickListener(this); } @Override public void onClick(View v){ delete(getAdapterPosition()); } } .... public void delete(int position) { exercises.remove(position); notifyItemRemoved(position); } Можете всё в onClick запихать, но советую так оставить, не нужно грузить listner-ы в адаптере, будет удобней расширять потом.

Ответ 2



Не надо тэг для этого использовать. У вас mDeleteBtn член класса адаптера и всегда содержит ссылку на последний отрисованный элемент списка. Вам, видимо, хотелось кнопку удаления в разметку каждого элемента добавить. Если так, то получить ID при нажатии на неё вы можете просто по позиции в onBindViewHolder

Ответ 3



Возможно ошибка в этом методе @Override public RecyclerAdapter.ExerciseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false); vh = new ExerciseViewHolder(v); return vh; } У вас ViewHolder объявлен переменной класса private List exercises; ExerciseViewHolder vh; public ImageView mDeleteBtn;э Попробуйте сделать так @Override public RecyclerAdapter.ExerciseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false); ExerciseViewHolder vh = new ExerciseViewHolder(v); return vh; } И удалить строку ExerciseViewHolder vh; в начале класса

Комментариев нет:

Отправить комментарий