Как добавить и обновить данные в SqliteDatabase с помощью адаптера RecyclerView - PullRequest
0 голосов
/ 26 марта 2019

Я просто пытаюсь составить список с помощью RecyclerView, где каждый элемент списка будет содержать кнопку-флажок. Поэтому, когда пользователь нажимает на флажок, он заменяет значение столбца таблицы, например, столбец страна получает значение «А», с другой стороны, снятие флажка заменяет значение столбца страны с «А» на «В» или что-либо еще.

Может кто-нибудь помочь мне с этим? Любое предложение, касающееся этого и других аналогичных способов добавления данных в базу данных SQLite с помощью Recyclable, будет очень полезным.

Ниже я добавил свой код для вашей справки и заранее спасибо.

My DatabaseHelper Class

    package com.hfad.ressql;

    import android.content.ContentValues;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import com.hfad.ressql.DatabaseContractor.*;

    import java.lang.reflect.Array;
    import java.util.ArrayList;
    import java.util.List;

    public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "workers.db";
    private static final int DATABASE_VERSION =7;

    SQLiteDatabase db;

    public DatabaseHelper( Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
     this.db=db;

     final String SQL_CREATE_TBALE="CREATE TABLE " +  EmployeeDetails.TABLE_NAME + "(" + EmployeeDetails._ID +" INTEGER PRIMARY KEY  AUTOINCREMENT, "+
             EmployeeDetails.COLUMN_FIRSTNAME+" TEXT,  "+EmployeeDetails.COLUMN_LASTNAME+" TEXT, "+EmployeeDetails.COLUMN_COUNTRY+" TEXT)";

     db.execSQL(SQL_CREATE_TBALE);
     fillquestion();

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {



        db.execSQL("DROP TABLE IF EXISTS " + EmployeeDetails.TABLE_NAME);
        onCreate(db);

    }


    public void fillquestion(){
    DataModel o4 = new DataModel("Earth","Soil","B");
    IntertData(o4);
    DataModel o5 = new DataModel("Sun","Light","B");
    IntertData(o5);
    DataModel o6 = new DataModel("Moon","Rock","B");
    IntertData(o6);

    }

    public void IntertData (DataModel data){

        ContentValues contentValues = new ContentValues();
        contentValues.put(EmployeeDetails.COLUMN_FIRSTNAME,     data.getFirstName());
        contentValues.put(EmployeeDetails.COLUMN_LASTNAME,   data.getLastName());
        contentValues.put(EmployeeDetails.COLUMN_COUNTRY, data.country);
        db.insert(EmployeeDetails.TABLE_NAME,null,contentValues);
    }

    public List<DataModel> object1() {
        ArrayList<DataModel> details = new ArrayList<DataModel>();
        db = getReadableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM " + EmployeeDetails.TABLE_NAME, null );
        if (cursor.moveToFirst()) {

            do {
                DataModel object2 = new DataModel();
                object2.setFirstName(cursor.getString(cursor.getColumnIndex(EmployeeDetails.COLUMN_FIRSTNAME)));
                object2.setLastName(cursor.getString(cursor.getColumnIndex(EmployeeDetails.COLUMN_LASTNAME)));
                object2.setCountry(cursor.getString(cursor.getColumnIndex(EmployeeDetails.COLUMN_COUNTRY)));


                details.add(object2);

            } while (cursor.moveToNext());
        }
        cursor.close();
        return details;
    }
}

Вот мой класс DataModel

    package com.hfad.ressql;

    public class DataModel {

    public String FirstName;
    public String LastName;
    public String country;



    public DataModel() {
    }

    public DataModel(String firstName, String lastName, String country) {
        this.FirstName = firstName;
        this.LastName = lastName;
        this.country = country;
    }

    public String getFirstName() {
        return FirstName;
    }

    public void setFirstName(String firstName) {
        FirstName = firstName;
    }

    public String getLastName() {
        return LastName;
    }

    public void setLastName(String lastName) {
        LastName = lastName;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
     }

Конструктор БД

       public final class DatabaseContractor {

       private DatabaseContractor (){}

        public static class EmployeeDetails implements BaseColumns {
        public static final String TABLE_NAME="employy";
        public static final String COLUMN_FIRSTNAME="First_Name";
        public static final String COLUMN_LASTNAME="Last_Name";
        public static final String COLUMN_COUNTRY="Country";
        public static final String COLUMN_FAVO="mfav";


        }

        }

Адаптер рециркуляции

Здесь я изо всех сил пытаюсь разобраться. Все, что мне нужно, это то, что если я нажму на флажок, одно заданное значение будет обновлено в базе данных, в то же время флажок будет установлен, пока пользователь не снимет его. И когда пользователь снимет галочку, база данных заменит предыдущее значение новым значением. На самом деле я просто пытаюсь получить значения в столбце таблицы, чтобы использовать его в качестве списка избранных или закладок.

    public class RecycAdapter extends       
    RecyclerView.Adapter<RecycAdapter.ViewHolder> {

    List<DataModel> dotamodeldataArraylist;
    Context context;
    SQLiteDatabase db;
    DatabaseHelper helper;
    ContentValues contentValues;
    Cursor cursor;

    public RecycAdapter(List<DataModel> dotamodeldataArraylist,Context context) {
        this.dotamodeldataArraylist=dotamodeldataArraylist;
        this.context=context;
    }

    @Override
    public ViewHolder onCreateViewHolder( ViewGroup parent, int ViewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemlist,parent,false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final RecycAdapter.ViewHolder holder, final int position) {

        DataModel obj3= dotamodeldataArraylist.get(position);
        holder.Fnam.setText(obj3.getFirstName());
        holder.Lname.setText(obj3.getLastName());
        holder.Country.setText(obj3.getCountry());
        holder.fav.();
      holder.fav.setChecked(fav);
      final int currentPosition = position;



           final boolean fav = 0==0;
      holder.fav.setChecked(fav);
      final int currentPosition = position;



        holder.fav.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                if(holder.fav.isChecked()){
                   try {
                       contentValues = new ContentValues();
                       contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY, "B");
                       db.update("DRINK", contentValues, "id_=?", new String[]{Integer.toString(currentPosition)});
                   } catch (SQLException e){
                       Toast.makeText(context,"error" + position , Toast.LENGTH_LONG).show();

                   }

                    Toast.makeText(context,"checked " + position , Toast.LENGTH_LONG).show();

                } if(!holder.fav.isChecked()){
                    Toast.makeText(context,"not checked" + position , Toast.LENGTH_LONG).show();
                }



            }
        });






    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView Fnam,Lname,Country;
        CheckBox fav;
        RelativeLayout relativeLayout;


        public ViewHolder(View itemView) {
            super(itemView);

            Fnam = itemView.findViewById(R.id.name1);
            Lname = itemView.findViewById(R.id.city1);
            Country = itemView.findViewById(R.id.country1);
            fav=itemView.findViewById(R.id.chk);
            relativeLayout = (RelativeLayout)     itemView.findViewById(R.id.layout);

        }
    }


    }

Просмотр класса

посмотреть все класс

    public class Viewall extends AppCompatActivity {

    RecyclerView recyclerView;
    DatabaseHelper databaseHelper;
    RecycAdapter recycAdapter;
    List<DataModel> dotamodeldataArraylist;
    Context context;
    Button show;


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

        show = findViewById(R.id.view);
        recyclerView=findViewById(R.id.recycle);

        databaseHelper =new DatabaseHelper(this);
        dotamodeldataArraylist = new ArrayList<DataModel>();
        dotamodeldataArraylist=databaseHelper.object1();
        recycAdapter =new RecycAdapter(dotamodeldataArraylist,this);
        RecyclerView.LayoutManager reLayoutManager =new            
        LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(reLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(recycAdapter);

Ответы [ 2 ]

1 голос
/ 27 марта 2019

Я полагаю, что следующее будет делать, как вы хотите.

Было довольно много проблем с кодом. Одна из основных проблем заключается в том, что вы ожидали, что позиция будет коррелировать с id (он же ваш столбец _id ).

Позиция первого элемента в списке: 0 , если вы не принудительно / специально не установите значение 0, псевдоним столбца rowid (ваш _id столбец является псевдонимом столбца rowid), первое назначенное значение будет 1, затем, вероятно, 2, затем, вероятно, 3 ...........

Таким образом, в лучшем случае будет на 1 меньше, чем идентификатор.

Если строка удаляется, кроме последней строки, то позиция будет на единицу меньше, кроме как до тех пор, пока не будет пройдена удаленная строка, а затем позиция будет на 2 меньше, чем rowid. Больше удалений и еще более сложная корреляция между позицией и идентификатором. Я предполагаю, что кто-то может придумать надежное преобразование, НО простой способ убедиться, что DataModel имеет значение соответствующего столбца _id .

Таким образом, DataModel.java следует изменить, чтобы включить элемент / переменную для идентификатора, поэтому использовалось следующее: -

public class DataModel {

    public String FirstName;
    public String LastName;
    public String country;

    public long id; //<<<<<<<<<< ADDED also added gettter and setter

    public DataModel() {
    }

    public DataModel(String firstName, String lastName, String country) {
        this(firstName,lastName,country,-1);
    }

    //<<<<<<<<<< ADDED so ID can be set
    public DataModel(String firstName, String lastName, String country, long id) {
        this.FirstName = firstName;
        this.LastName = lastName;
        this.country = country;
        this.id = id;
    }

    public String getFirstName() {
        return FirstName;
    }

    public void setFirstName(String firstName) {
        FirstName = firstName;
    }

    public String getLastName() {
        return LastName;
    }

    public void setLastName(String lastName) {
        LastName = lastName;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getId() {
        return id;
    }
}
  • см. Комментарии к изменениям

Поскольку вам нужно извлечь идентификатор из базы данных, метод object1 был изменен в DatabaseHelper.java (также было сделано несколько других изменений), было использовано следующее: -

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "workers.db";
    private static final int DATABASE_VERSION =7;

    SQLiteDatabase db;

    public DatabaseHelper( Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        db = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        this.db=db; //<<<<<<< WRONG PLACE as onCreate only ever runs when there is no database

        final String SQL_CREATE_TBALE="CREATE TABLE " +  DatabaseContractor.EmployeeDetails.TABLE_NAME + "(" + DatabaseContractor.EmployeeDetails._ID +" INTEGER PRIMARY KEY  AUTOINCREMENT, "+
                DatabaseContractor.EmployeeDetails.COLUMN_FIRSTNAME+" TEXT,  "+ DatabaseContractor.EmployeeDetails.COLUMN_LASTNAME+" TEXT, "+ DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY+" TEXT)";

        db.execSQL(SQL_CREATE_TBALE);
        fillquestion();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + DatabaseContractor.EmployeeDetails.TABLE_NAME);
        onCreate(db);
    }


    public void fillquestion(){
        IntertData(new DataModel("Earth","Soil","B"));
        IntertData(new DataModel("Sun","Light","B"));
        IntertData(new DataModel("Moon","Rock","B"));
    }

    public void IntertData (DataModel data){

        ContentValues contentValues = new ContentValues();
        contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_FIRSTNAME,data.getFirstName());
        contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_LASTNAME,data.getLastName());
        contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY,data.country);
        db.insert(DatabaseContractor.EmployeeDetails.TABLE_NAME,null,contentValues);
    }

    public List<DataModel> object1() {
        ArrayList<DataModel> details = new ArrayList<>();
        //db = getReadableDatabase(); db has already been set when database was instantiated/constructed
        Cursor cursor = db.rawQuery("SELECT * FROM " + DatabaseContractor.EmployeeDetails.TABLE_NAME, null );
        while (cursor.moveToNext()) {
            details.add(new DataModel(
                    cursor.getString(cursor.getColumnIndex(DatabaseContractor.EmployeeDetails.COLUMN_FIRSTNAME)),
                    cursor.getString(cursor.getColumnIndex(DatabaseContractor.EmployeeDetails.COLUMN_LASTNAME)),
                    cursor.getString(cursor.getColumnIndex(DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY)),
                    cursor.getLong(cursor.getColumnIndex(DatabaseContractor.EmployeeDetails._ID)) //<<<<<<<<< Added so id is available
            ));
        }
        cursor.close();
        return details;
    }
}

В RecycAdapter.java были внесены довольно обширные изменения, использовалось следующее: -

public class RecycAdapter extends RecyclerView.Adapter<RecycAdapter.ViewHolder> {

    List<DataModel> dotamodeldataArraylist;
    Context context;
    SQLiteDatabase db;
    DatabaseHelper helper;
    ContentValues contentValues;

    public RecycAdapter(List<DataModel> dotamodeldataArraylist,Context context) {
        this.dotamodeldataArraylist=dotamodeldataArraylist;
        this.context=context;
        helper = new DatabaseHelper(context);
        db = helper.getWritableDatabase();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int ViewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemlist,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final RecycAdapter.ViewHolder holder, final int position) {

        //DataModel obj3= dotamodeldataArraylist.get(position); //<<<<<<<<<< NOT NEEDED
        holder.Fnam.setText(dotamodeldataArraylist.get(position).getFirstName());
        holder.Lname.setText(dotamodeldataArraylist.get(position).getLastName());
        holder.Country.setText(dotamodeldataArraylist.get(position).getCountry());
        holder.fav.setChecked(false); //<<<<<<<<< not stored so initially set to false

        holder.fav.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String newcountry = "B";
                if(holder.fav.isChecked()){
                    if (dotamodeldataArraylist.get(position).getCountry().equals("B")) {
                        newcountry  = "A";
                    }
                    contentValues = new ContentValues();
                    contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY, newcountry);
                    if (db.update(
                            DatabaseContractor.EmployeeDetails.TABLE_NAME,
                            contentValues,
                            DatabaseContractor.EmployeeDetails._ID +"=?",
                            new String[]{String.valueOf(dotamodeldataArraylist.get(position).getId())}
                            ) > 0) {
                        dotamodeldataArraylist.get(position).setCountry(newcountry);
                        notifyItemChanged(position);
                        Toast.makeText(context,
                                "checked and updated " +
                                        position+ dotamodeldataArraylist.get(position).getFirstName() +
                                        " ID is " + String.valueOf(dotamodeldataArraylist.get(position).getId()),
                                Toast.LENGTH_LONG
                        ).show();
                    } else {
                        Toast.makeText(context,"error" + position , Toast.LENGTH_LONG).show();
                    }
                } else {
                    Toast.makeText(context,"not checked" + position , Toast.LENGTH_LONG).show();
                }
            }
        });
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView Fnam,Lname,Country;
        CheckBox fav;

        public ViewHolder(View itemView) {
            super(itemView);
            Fnam = itemView.findViewById(R.id.name1);
            Lname = itemView.findViewById(R.id.city1);
            Country = itemView.findViewById(R.id.country1);
            fav = itemView.findViewById(R.id.chk);
        }
    }
}

наконец, несколько небольших изменений были внесены в Viewall.java, использовалось следующее: -

public class Viewall extends AppCompatActivity {

    RecyclerView recyclerView;
    DatabaseHelper databaseHelper;
    RecycAdapter recycAdapter;
    List<DataModel> dotamodeldataArraylist;
    Button show;

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

        show = findViewById(R.id.view);
        recyclerView = findViewById(R.id.recycle);

        databaseHelper = new DatabaseHelper(this);
        dotamodeldataArraylist = databaseHelper.object1();
        recycAdapter = new RecycAdapter(dotamodeldataArraylist, this);
        RecyclerView.LayoutManager reLayoutManager = new
                LinearLayoutManager(this);
        recyclerView.setLayoutManager(reLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(recycAdapter);
    }
}

Результат

Обратите внимание, что макеты могут отличаться, но ваши, вероятно, должны работать и соответственно изменять презентацию

При первом запуске: -

enter image description here

После установки флажка Солнце

enter image description here

Нажмите еще раз и вернитесь в страну B и т. Д.

  • Обратите внимание, что флажок не установлен, это небольшая проблема, так как для правильного отображения измененных данных (страны) используется notifyItemChanged, который повторно обработает список и, таким образом, установит для флажка значение false. Вам нужно где-то хранить значение флажка (короче говоря, вы действительно должны использовать флажки таким образом).

Закрытие приложения и перезапуск сохраняют внесенные изменения, подтверждая, таким образом, изменения в базе данных.

0 голосов
/ 28 марта 2019

Помимо кода @ MiKe, я только что внес некоторые изменения в свой RecyclerAdapter внутри onClickListener, чтобы сохранить флажок Status, и добавил isChecked в качестве логического значения в классе dataModel . теперь работает отлично.

   holder.chkbox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
                Values = new ContentValues();
                Values.put(DatabaseContractor.EmployeeDetails.COLUMN_FAVORITE,holder.chkbox.isChecked());
                try{ db.update(DatabaseContractor.EmployeeDetails.TABLE_NAME,
                        Values,
                        DatabaseContractor.EmployeeDetails._ID + "=?",
                        new String[]{String.valueOf(dotamodeldataArraylist.get(position).getId())});

                } catch (SQLException e){
                    Toast.makeText(context,"Error"+position,Toast.LENGTH_LONG).show();
                }
        }
    });

Еще раз спасибо, Майк, за твое потрясающее руководство. Теперь я могу напрямую сохранить статус флажка в базе данных sqlite.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...